mirror of
https://github.com/pure-admin/vue-pure-admin.git
synced 2025-06-06 16:37:18 +08:00
commit
dd8cc8508e
@ -1,4 +1,4 @@
|
|||||||
public
|
public
|
||||||
dist
|
dist
|
||||||
*.d.ts
|
*.d.ts
|
||||||
package.json
|
package.json
|
29
.eslintrc.js
29
.eslintrc.js
@ -3,6 +3,35 @@ module.exports = {
|
|||||||
env: {
|
env: {
|
||||||
node: true
|
node: true
|
||||||
},
|
},
|
||||||
|
globals: {
|
||||||
|
// Ref sugar (take 2)
|
||||||
|
$: "readonly",
|
||||||
|
$$: "readonly",
|
||||||
|
$ref: "readonly",
|
||||||
|
$shallowRef: "readonly",
|
||||||
|
$computed: "readonly",
|
||||||
|
|
||||||
|
// index.d.ts
|
||||||
|
// global.d.ts
|
||||||
|
Fn: "readonly",
|
||||||
|
PromiseFn: "readonly",
|
||||||
|
RefType: "readonly",
|
||||||
|
LabelValueOptions: "readonly",
|
||||||
|
EmitType: "readonly",
|
||||||
|
TargetContext: "readonly",
|
||||||
|
ComponentElRef: "readonly",
|
||||||
|
ComponentRef: "readonly",
|
||||||
|
ElRef: "readonly",
|
||||||
|
global: "readonly",
|
||||||
|
ForDataType: "readonly",
|
||||||
|
ComponentRoutes: "readonly",
|
||||||
|
|
||||||
|
// script setup
|
||||||
|
defineProps: "readonly",
|
||||||
|
defineEmits: "readonly",
|
||||||
|
defineExpose: "readonly",
|
||||||
|
withDefaults: "readonly"
|
||||||
|
},
|
||||||
extends: [
|
extends: [
|
||||||
"plugin:vue/vue3-essential",
|
"plugin:vue/vue3-essential",
|
||||||
"eslint:recommended",
|
"eslint:recommended",
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<link rel="stylesheet" href="/iconfont.css" />
|
<link rel="stylesheet" href="/iconfont.css" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>后台管理系统</title>
|
<title>后台管理系统</title>
|
||||||
<script src="https://cdn.bootcdn.net/ajax/libs/Sortable/1.13.0/Sortable.js"></script>
|
<script src="/sortable.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
window.process = {};
|
window.process = {};
|
||||||
</script>
|
</script>
|
||||||
|
13
package.json
13
package.json
@ -8,20 +8,20 @@
|
|||||||
"build": "rimraf dist && cross-env vite build",
|
"build": "rimraf dist && cross-env vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"preview:build": "yarn build && vite preview",
|
"preview:build": "yarn build && vite preview",
|
||||||
"clean:cache": "rm -rf node_modules && yarn cache clean && yarn install",
|
"clean:cache": "rm -rf node_modules && rm -rf .eslintcache && yarn cache clean && yarn",
|
||||||
"lint:eslint": "eslint --cache --max-warnings 0 \"{src,mock}/**/*.{vue,ts,tsx}\" --fix",
|
"lint:eslint": "eslint --cache --max-warnings 0 \"{src,mock}/**/*.{vue,ts,tsx}\" --fix",
|
||||||
"lint:prettier": "prettier --write \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
|
"lint:prettier": "prettier --write \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
|
||||||
"lint:stylelint": "stylelint --cache --fix \"**/*.{vue,css,scss,postcss,less}\" --cache --cache-location node_modules/.cache/stylelint/",
|
"lint:stylelint": "stylelint --cache --fix \"**/*.{vue,css,scss,postcss,less}\" --cache --cache-location node_modules/.cache/stylelint/",
|
||||||
"lint:lint-staged": "lint-staged -c ./.husky/lintstagedrc.js",
|
"lint:lint-staged": "lint-staged -c ./.husky/lintstagedrc.js",
|
||||||
"lint:pretty": "pretty-quick --staged",
|
"lint:pretty": "pretty-quick --staged",
|
||||||
"lint:all": "yarn lint:eslint && yarn lint:prettier && yarn lint:stylelint && yarn lint:pretty",
|
"lint": "yarn lint:eslint && yarn lint:prettier && yarn lint:stylelint && yarn lint:pretty",
|
||||||
"prepare": "husky install"
|
"prepare": "husky install"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@amap/amap-jsapi-loader": "^1.0.1",
|
"@amap/amap-jsapi-loader": "^1.0.1",
|
||||||
"@logicflow/core": "^0.4.6",
|
"@logicflow/core": "^0.4.6",
|
||||||
"@logicflow/extension": "^0.4.6",
|
"@logicflow/extension": "^0.4.6",
|
||||||
"@vueuse/core": "^6.0.0",
|
"@vueuse/core": "^6.4.1",
|
||||||
"animate.css": "^4.1.1",
|
"animate.css": "^4.1.1",
|
||||||
"await-to-js": "^3.0.0",
|
"await-to-js": "^3.0.0",
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
@ -41,12 +41,13 @@
|
|||||||
"pinia": "^2.0.0-rc.6",
|
"pinia": "^2.0.0-rc.6",
|
||||||
"resize-observer-polyfill": "^1.5.1",
|
"resize-observer-polyfill": "^1.5.1",
|
||||||
"responsive-storage": "^1.0.9",
|
"responsive-storage": "^1.0.9",
|
||||||
|
"sortablejs": "1.13.0",
|
||||||
"v-contextmenu": "^3.0.0",
|
"v-contextmenu": "^3.0.0",
|
||||||
"vue": "^3.2.11",
|
"vue": "3.2.11",
|
||||||
"vue-i18n": "^9.2.0-beta.3",
|
"vue-i18n": "^9.2.0-beta.3",
|
||||||
"vue-json-pretty": "^2.0.2",
|
"vue-json-pretty": "^2.0.2",
|
||||||
"vue-router": "^4.0.11",
|
"vue-router": "^4.0.11",
|
||||||
"vue-types": "^4.0.3",
|
"vue-types": "^4.1.0",
|
||||||
"vuedraggable": "^4.1.0",
|
"vuedraggable": "^4.1.0",
|
||||||
"vxe-table": "^4.0.27",
|
"vxe-table": "^4.0.27",
|
||||||
"wangeditor": "^4.7.7",
|
"wangeditor": "^4.7.7",
|
||||||
@ -65,7 +66,7 @@
|
|||||||
"@typescript-eslint/parser": "^4.31.0",
|
"@typescript-eslint/parser": "^4.31.0",
|
||||||
"@vitejs/plugin-vue": "^1.6.0",
|
"@vitejs/plugin-vue": "^1.6.0",
|
||||||
"@vitejs/plugin-vue-jsx": "^1.1.7",
|
"@vitejs/plugin-vue-jsx": "^1.1.7",
|
||||||
"@vue/compiler-sfc": "^3.2.11",
|
"@vue/compiler-sfc": "3.2.11",
|
||||||
"@vue/eslint-config-prettier": "^6.0.0",
|
"@vue/eslint-config-prettier": "^6.0.0",
|
||||||
"@vue/eslint-config-typescript": "^7.0.0",
|
"@vue/eslint-config-typescript": "^7.0.0",
|
||||||
"autoprefixer": "^10.2.4",
|
"autoprefixer": "^10.2.4",
|
||||||
|
2607
public/sortable.min.js
vendored
Normal file
2607
public/sortable.min.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
41
src/App.vue
41
src/App.vue
@ -1,28 +1,25 @@
|
|||||||
<template>
|
<script setup lang="ts">
|
||||||
<el-config-provider :locale="currentLocale">
|
import { getCurrentInstance } from "vue";
|
||||||
<router-view />
|
|
||||||
</el-config-provider>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { ElConfigProvider } from "element-plus";
|
import { ElConfigProvider } from "element-plus";
|
||||||
import zhCn from "element-plus/lib/locale/lang/zh-cn";
|
import zhCn from "element-plus/lib/locale/lang/zh-cn";
|
||||||
import en from "element-plus/lib/locale/lang/en";
|
import en from "element-plus/lib/locale/lang/en";
|
||||||
export default {
|
|
||||||
name: "app",
|
let locale: string =
|
||||||
components: {
|
getCurrentInstance().appContext.config.globalProperties.$storage?.locale
|
||||||
[ElConfigProvider.name]: ElConfigProvider
|
?.locale;
|
||||||
},
|
|
||||||
computed: {
|
let currentLocale = () => {
|
||||||
// eslint-disable-next-line vue/return-in-computed-property
|
switch (locale) {
|
||||||
currentLocale() {
|
case "zh":
|
||||||
switch (this.$storage.locale?.locale) {
|
return zhCn;
|
||||||
case "zh":
|
case "en":
|
||||||
return zhCn;
|
return en;
|
||||||
case "en":
|
|
||||||
return en;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<el-config-provider :locale="currentLocale()">
|
||||||
|
<router-view />
|
||||||
|
</el-config-provider>
|
||||||
|
</template>
|
||||||
|
@ -1,3 +1,52 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, watch, Ref } from "vue";
|
||||||
|
import { useRoute, useRouter, RouteLocationMatched } from "vue-router";
|
||||||
|
|
||||||
|
const levelList: Ref<RouteLocationMatched[]> = ref([]);
|
||||||
|
const route = useRoute();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const isDashboard = (route: RouteLocationMatched): boolean | string => {
|
||||||
|
const name = route && (route.name as string);
|
||||||
|
if (!name) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return name.trim().toLocaleLowerCase() === "welcome".toLocaleLowerCase();
|
||||||
|
};
|
||||||
|
|
||||||
|
const getBreadcrumb = (): void => {
|
||||||
|
let matched = route.matched.filter(item => item.meta && item.meta.title);
|
||||||
|
const first = matched[0];
|
||||||
|
if (!isDashboard(first)) {
|
||||||
|
matched = [
|
||||||
|
{
|
||||||
|
path: "/welcome",
|
||||||
|
meta: { title: "message.hshome" }
|
||||||
|
} as unknown as RouteLocationMatched
|
||||||
|
].concat(matched);
|
||||||
|
}
|
||||||
|
levelList.value = matched.filter(
|
||||||
|
item => item.meta && item.meta.title && item.meta.breadcrumb !== false
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
getBreadcrumb();
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => route.path,
|
||||||
|
() => getBreadcrumb()
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleLink = (item: RouteLocationMatched): any => {
|
||||||
|
const { redirect, path } = item;
|
||||||
|
if (redirect) {
|
||||||
|
router.push(redirect.toString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
router.push(path);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<el-breadcrumb class="app-breadcrumb" separator="/">
|
<el-breadcrumb class="app-breadcrumb" separator="/">
|
||||||
<transition-group appear name="breadcrumb">
|
<transition-group appear name="breadcrumb">
|
||||||
@ -15,62 +64,6 @@
|
|||||||
</el-breadcrumb>
|
</el-breadcrumb>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { ref, defineComponent, watch, Ref } from "vue";
|
|
||||||
import { useRoute, useRouter, RouteLocationMatched } from "vue-router";
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: "ReBreadCrumb",
|
|
||||||
setup() {
|
|
||||||
const levelList: Ref<RouteLocationMatched[]> = ref([]);
|
|
||||||
const route = useRoute();
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
const isDashboard = (route: RouteLocationMatched): boolean | string => {
|
|
||||||
const name = route && (route.name as string);
|
|
||||||
if (!name) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return name.trim().toLocaleLowerCase() === "welcome".toLocaleLowerCase();
|
|
||||||
};
|
|
||||||
|
|
||||||
const getBreadcrumb = (): void => {
|
|
||||||
let matched = route.matched.filter(item => item.meta && item.meta.title);
|
|
||||||
const first = matched[0];
|
|
||||||
if (!isDashboard(first)) {
|
|
||||||
matched = [
|
|
||||||
{
|
|
||||||
path: "/welcome",
|
|
||||||
meta: { title: "message.hshome" }
|
|
||||||
} as unknown as RouteLocationMatched
|
|
||||||
].concat(matched);
|
|
||||||
}
|
|
||||||
levelList.value = matched.filter(
|
|
||||||
item => item.meta && item.meta.title && item.meta.breadcrumb !== false
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
getBreadcrumb();
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => route.path,
|
|
||||||
() => getBreadcrumb()
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleLink = (item: RouteLocationMatched): any => {
|
|
||||||
const { redirect, path } = item;
|
|
||||||
if (redirect) {
|
|
||||||
router.push(redirect.toString());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
router.push(path);
|
|
||||||
};
|
|
||||||
|
|
||||||
return { levelList, handleLink };
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.app-breadcrumb.el-breadcrumb {
|
.app-breadcrumb.el-breadcrumb {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import type { CSSProperties } from "vue";
|
import type { CSSProperties } from "vue";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
defineComponent,
|
defineComponent,
|
||||||
onBeforeMount,
|
onBeforeMount,
|
||||||
@ -40,46 +39,48 @@ const defaultOptions: Cropper.Options = {
|
|||||||
rotatable: true
|
rotatable: true
|
||||||
};
|
};
|
||||||
|
|
||||||
export default defineComponent({
|
const props = {
|
||||||
name: "Cropper",
|
src: {
|
||||||
props: {
|
type: String,
|
||||||
src: {
|
required: true
|
||||||
type: String,
|
},
|
||||||
required: true
|
alt: {
|
||||||
},
|
type: String
|
||||||
alt: {
|
},
|
||||||
type: String
|
width: {
|
||||||
},
|
type: [String, Number],
|
||||||
width: {
|
default: ""
|
||||||
type: [String, Number],
|
},
|
||||||
default: ""
|
height: {
|
||||||
},
|
type: [String, Number],
|
||||||
height: {
|
default: "360px"
|
||||||
type: [String, Number],
|
},
|
||||||
default: "360px"
|
crossorigin: {
|
||||||
},
|
type: String || Object,
|
||||||
crossorigin: {
|
default: undefined
|
||||||
type: String || Object,
|
},
|
||||||
default: undefined
|
imageStyle: {
|
||||||
},
|
type: Object as PropType<CSSProperties>,
|
||||||
imageStyle: {
|
default() {
|
||||||
type: Object as PropType<CSSProperties>,
|
return {};
|
||||||
default() {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
type: Object as PropType<Options>,
|
|
||||||
default() {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
options: {
|
||||||
|
type: Object as PropType<Options>,
|
||||||
|
default() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: "Cropper",
|
||||||
|
props,
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const cropper: any = ref<Nullable<Cropper>>(null);
|
const cropper: any = ref<Nullable<Cropper>>(null);
|
||||||
const imgElRef = templateRef<HTMLImageElement | null>("imgElRef", null);
|
const imgElRef = templateRef<HTMLImageElement | null>("imgElRef", null);
|
||||||
|
|
||||||
const isReady = ref(false);
|
const isReady = ref<boolean>(false);
|
||||||
|
|
||||||
const getImageStyle = computed((): CSSProperties => {
|
const getImageStyle = computed((): CSSProperties => {
|
||||||
return {
|
return {
|
||||||
|
@ -2,19 +2,21 @@ import { defineComponent, ref } from "vue";
|
|||||||
import { propTypes } from "/@/utils/propTypes";
|
import { propTypes } from "/@/utils/propTypes";
|
||||||
import "./filpper.css";
|
import "./filpper.css";
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
// front paper text
|
||||||
|
// 前牌文字
|
||||||
|
frontText: propTypes.number.def(0),
|
||||||
|
// back paper text
|
||||||
|
// 后牌文字
|
||||||
|
backText: propTypes.number.def(1),
|
||||||
|
// flipping duration, please be consistent with the CSS animation-duration value.
|
||||||
|
// 翻牌动画时间,与CSS中设置的animation-duration保持一致
|
||||||
|
duration: propTypes.number.def(600)
|
||||||
|
};
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "Filpper",
|
name: "Filpper",
|
||||||
props: {
|
props,
|
||||||
// front paper text
|
|
||||||
// 前牌文字
|
|
||||||
frontText: propTypes.number.def(0),
|
|
||||||
// back paper text
|
|
||||||
// 后牌文字
|
|
||||||
backText: propTypes.number.def(1),
|
|
||||||
// flipping duration, please be consistent with the CSS animation-duration value.
|
|
||||||
// 翻牌动画时间,与CSS中设置的animation-duration保持一致
|
|
||||||
duration: propTypes.number.def(600)
|
|
||||||
},
|
|
||||||
setup(props) {
|
setup(props) {
|
||||||
// eslint-disable-next-line vue/no-setup-props-destructure
|
// eslint-disable-next-line vue/no-setup-props-destructure
|
||||||
const { frontText, backText, duration } = props;
|
const { frontText, backText, duration } = props;
|
||||||
|
@ -1,3 +1,109 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, unref, nextTick, onUnmounted } from "vue";
|
||||||
|
import { templateRef } from "@vueuse/core";
|
||||||
|
import flippers from "./Filpper";
|
||||||
|
|
||||||
|
let timer = ref(null);
|
||||||
|
let flipObjs = ref([]);
|
||||||
|
|
||||||
|
const flipperHour1 = templateRef<HTMLElement | null>("flipperHour1", null);
|
||||||
|
const flipperHour2 = templateRef<HTMLElement | null>("flipperHour2", null);
|
||||||
|
const flipperMinute1 = templateRef<HTMLElement | null>("flipperMinute1", null);
|
||||||
|
const flipperMinute2 = templateRef<HTMLElement | null>("flipperMinute2", null);
|
||||||
|
const flipperSecond1 = templateRef<HTMLElement | null>("flipperSecond1", null);
|
||||||
|
const flipperSecond2 = templateRef<HTMLElement | null>("flipperSecond2", null);
|
||||||
|
|
||||||
|
// 初始化数字
|
||||||
|
const init = () => {
|
||||||
|
let now = new Date();
|
||||||
|
let nowTimeStr = formatDate(new Date(now.getTime()), "hhiiss");
|
||||||
|
for (let i = 0; i < flipObjs.value.length; i++) {
|
||||||
|
flipObjs?.value[i]?.setFront(nowTimeStr[i]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 开始计时
|
||||||
|
const run = () => {
|
||||||
|
timer.value = setInterval(() => {
|
||||||
|
// 获取当前时间
|
||||||
|
let now = new Date();
|
||||||
|
let nowTimeStr = formatDate(new Date(now.getTime() - 1000), "hhiiss");
|
||||||
|
let nextTimeStr = formatDate(now, "hhiiss");
|
||||||
|
for (let i = 0; i < flipObjs.value.length; i++) {
|
||||||
|
if (nowTimeStr[i] === nextTimeStr[i]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
flipObjs?.value[i]?.flipDown(nowTimeStr[i], nextTimeStr[i]);
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 正则格式化日期
|
||||||
|
const formatDate = (date: Date, dateFormat: string) => {
|
||||||
|
/* 单独格式化年份,根据y的字符数量输出年份
|
||||||
|
* 例如:yyyy => 2019
|
||||||
|
yy => 19
|
||||||
|
y => 9
|
||||||
|
*/
|
||||||
|
if (/(y+)/.test(dateFormat)) {
|
||||||
|
dateFormat = dateFormat.replace(
|
||||||
|
RegExp.$1,
|
||||||
|
(date.getFullYear() + "").substr(4 - RegExp.$1.length)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// 格式化月、日、时、分、秒
|
||||||
|
let o = {
|
||||||
|
"m+": date.getMonth() + 1,
|
||||||
|
"d+": date.getDate(),
|
||||||
|
"h+": date.getHours(),
|
||||||
|
"i+": date.getMinutes(),
|
||||||
|
"s+": date.getSeconds()
|
||||||
|
};
|
||||||
|
for (let k in o) {
|
||||||
|
if (new RegExp(`(${k})`).test(dateFormat)) {
|
||||||
|
// 取出对应的值
|
||||||
|
let str = o[k] + "";
|
||||||
|
/* 根据设置的格式,输出对应的字符
|
||||||
|
* 例如: 早上8时,hh => 08,h => 8
|
||||||
|
* 但是,当数字>=10时,无论格式为一位还是多位,不做截取,这是与年份格式化不一致的地方
|
||||||
|
* 例如: 下午15时,hh => 15, h => 15
|
||||||
|
*/
|
||||||
|
dateFormat = dateFormat.replace(
|
||||||
|
RegExp.$1,
|
||||||
|
RegExp.$1.length === 1 ? str : padLeftZero(str)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dateFormat;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 日期时间补零
|
||||||
|
const padLeftZero = (str: string | any[]) => {
|
||||||
|
return ("00" + str).substr(str.length);
|
||||||
|
};
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
flipObjs.value = [
|
||||||
|
unref(flipperHour1),
|
||||||
|
unref(flipperHour2),
|
||||||
|
unref(flipperMinute1),
|
||||||
|
unref(flipperMinute2),
|
||||||
|
unref(flipperSecond1),
|
||||||
|
unref(flipperSecond2)
|
||||||
|
];
|
||||||
|
|
||||||
|
init();
|
||||||
|
run();
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (timer.value) {
|
||||||
|
clearInterval(timer.value);
|
||||||
|
timer.value = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flip-clock">
|
<div class="flip-clock">
|
||||||
<flippers ref="flipperHour1" />
|
<flippers ref="flipperHour1" />
|
||||||
@ -11,147 +117,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { ref, unref, nextTick, onUnmounted } from "vue";
|
|
||||||
import flippers from "./Filpper";
|
|
||||||
|
|
||||||
import { templateRef } from "@vueuse/core";
|
|
||||||
export default {
|
|
||||||
name: "Flop",
|
|
||||||
components: {
|
|
||||||
flippers
|
|
||||||
},
|
|
||||||
setup() {
|
|
||||||
let timer = ref(null);
|
|
||||||
let flipObjs = ref([]);
|
|
||||||
|
|
||||||
const flipperHour1 = templateRef<HTMLElement | null>("flipperHour1", null);
|
|
||||||
const flipperHour2 = templateRef<HTMLElement | null>("flipperHour2", null);
|
|
||||||
const flipperMinute1 = templateRef<HTMLElement | null>(
|
|
||||||
"flipperMinute1",
|
|
||||||
null
|
|
||||||
);
|
|
||||||
const flipperMinute2 = templateRef<HTMLElement | null>(
|
|
||||||
"flipperMinute2",
|
|
||||||
null
|
|
||||||
);
|
|
||||||
const flipperSecond1 = templateRef<HTMLElement | null>(
|
|
||||||
"flipperSecond1",
|
|
||||||
null
|
|
||||||
);
|
|
||||||
const flipperSecond2 = templateRef<HTMLElement | null>(
|
|
||||||
"flipperSecond2",
|
|
||||||
null
|
|
||||||
);
|
|
||||||
|
|
||||||
// 初始化数字
|
|
||||||
const init = () => {
|
|
||||||
let now = new Date();
|
|
||||||
let nowTimeStr = formatDate(new Date(now.getTime()), "hhiiss");
|
|
||||||
for (let i = 0; i < flipObjs.value.length; i++) {
|
|
||||||
flipObjs?.value[i]?.setFront(nowTimeStr[i]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 开始计时
|
|
||||||
const run = () => {
|
|
||||||
timer.value = setInterval(() => {
|
|
||||||
// 获取当前时间
|
|
||||||
let now = new Date();
|
|
||||||
let nowTimeStr = formatDate(new Date(now.getTime() - 1000), "hhiiss");
|
|
||||||
let nextTimeStr = formatDate(now, "hhiiss");
|
|
||||||
for (let i = 0; i < flipObjs.value.length; i++) {
|
|
||||||
if (nowTimeStr[i] === nextTimeStr[i]) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
flipObjs?.value[i]?.flipDown(nowTimeStr[i], nextTimeStr[i]);
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 正则格式化日期
|
|
||||||
const formatDate = (date: Date, dateFormat: string) => {
|
|
||||||
/* 单独格式化年份,根据y的字符数量输出年份
|
|
||||||
* 例如:yyyy => 2019
|
|
||||||
yy => 19
|
|
||||||
y => 9
|
|
||||||
*/
|
|
||||||
if (/(y+)/.test(dateFormat)) {
|
|
||||||
dateFormat = dateFormat.replace(
|
|
||||||
RegExp.$1,
|
|
||||||
(date.getFullYear() + "").substr(4 - RegExp.$1.length)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// 格式化月、日、时、分、秒
|
|
||||||
let o = {
|
|
||||||
"m+": date.getMonth() + 1,
|
|
||||||
"d+": date.getDate(),
|
|
||||||
"h+": date.getHours(),
|
|
||||||
"i+": date.getMinutes(),
|
|
||||||
"s+": date.getSeconds()
|
|
||||||
};
|
|
||||||
for (let k in o) {
|
|
||||||
if (new RegExp(`(${k})`).test(dateFormat)) {
|
|
||||||
// 取出对应的值
|
|
||||||
let str = o[k] + "";
|
|
||||||
/* 根据设置的格式,输出对应的字符
|
|
||||||
* 例如: 早上8时,hh => 08,h => 8
|
|
||||||
* 但是,当数字>=10时,无论格式为一位还是多位,不做截取,这是与年份格式化不一致的地方
|
|
||||||
* 例如: 下午15时,hh => 15, h => 15
|
|
||||||
*/
|
|
||||||
dateFormat = dateFormat.replace(
|
|
||||||
RegExp.$1,
|
|
||||||
RegExp.$1.length === 1 ? str : padLeftZero(str)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dateFormat;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 日期时间补零
|
|
||||||
const padLeftZero = (str: string | any[]) => {
|
|
||||||
return ("00" + str).substr(str.length);
|
|
||||||
};
|
|
||||||
|
|
||||||
nextTick(() => {
|
|
||||||
flipObjs.value = [
|
|
||||||
unref(flipperHour1),
|
|
||||||
unref(flipperHour2),
|
|
||||||
unref(flipperMinute1),
|
|
||||||
unref(flipperMinute2),
|
|
||||||
unref(flipperSecond1),
|
|
||||||
unref(flipperSecond2)
|
|
||||||
];
|
|
||||||
|
|
||||||
init();
|
|
||||||
run();
|
|
||||||
});
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
if (timer.value) {
|
|
||||||
clearInterval(timer.value);
|
|
||||||
timer.value = null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
timer,
|
|
||||||
flipObjs,
|
|
||||||
init,
|
|
||||||
run,
|
|
||||||
formatDate,
|
|
||||||
padLeftZero,
|
|
||||||
flipperHour1,
|
|
||||||
flipperHour2,
|
|
||||||
flipperMinute1,
|
|
||||||
flipperMinute2,
|
|
||||||
flipperSecond1,
|
|
||||||
flipperSecond2
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.flip-clock .m-flipper {
|
.flip-clock .m-flipper {
|
||||||
margin: 0 3px;
|
margin: 0 3px;
|
||||||
|
@ -1,3 +1,92 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, unref, onMounted } from "vue";
|
||||||
|
import { templateRef } from "@vueuse/core";
|
||||||
|
import { LogicFlow } from "@logicflow/core";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
lf: LogicFlow;
|
||||||
|
catTurboData?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
lf: null
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: "catData"): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const controlButton3 = templateRef<HTMLElement | any>("controlButton3", null);
|
||||||
|
const controlButton4 = templateRef<HTMLElement | any>("controlButton4", null);
|
||||||
|
|
||||||
|
let focusIndex = ref<Number>(-1);
|
||||||
|
let titleLists = ref([
|
||||||
|
{
|
||||||
|
icon: "icon-zoom-out-hs",
|
||||||
|
text: "缩小",
|
||||||
|
disabled: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: "icon-enlarge-hs",
|
||||||
|
text: "放大",
|
||||||
|
disabled: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: "icon-full-screen-hs",
|
||||||
|
text: "适应",
|
||||||
|
disabled: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: "icon-previous-hs",
|
||||||
|
text: "上一步",
|
||||||
|
disabled: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: "icon-next-step-hs",
|
||||||
|
text: "下一步",
|
||||||
|
disabled: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: "icon-download-hs",
|
||||||
|
text: "下载图片",
|
||||||
|
disabled: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: "icon-watch-hs",
|
||||||
|
text: "查看数据",
|
||||||
|
disabled: false
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
const onControl = (item, key) => {
|
||||||
|
["zoom", "zoom", "resetZoom", "undo", "redo", "getSnapshot"].forEach(
|
||||||
|
(v, i) => {
|
||||||
|
let domControl = props.lf;
|
||||||
|
if (key === 1) {
|
||||||
|
domControl.zoom(true);
|
||||||
|
}
|
||||||
|
if (key === 6) {
|
||||||
|
emit("catData");
|
||||||
|
}
|
||||||
|
if (key === i) {
|
||||||
|
domControl[v]();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onEnter = key => {
|
||||||
|
focusIndex.value = key;
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
props.lf.on("history:change", ({ data: { undoAble, redoAble } }) => {
|
||||||
|
unref(titleLists)[3].disabled = unref(controlButton3).disabled = !undoAble;
|
||||||
|
unref(titleLists)[4].disabled = unref(controlButton4).disabled = !redoAble;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="control-container">
|
<div class="control-container">
|
||||||
<!-- 功能按钮 -->
|
<!-- 功能按钮 -->
|
||||||
@ -26,106 +115,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { defineComponent, ref, unref, onMounted } from "vue";
|
|
||||||
import { templateRef } from "@vueuse/core";
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: "Control",
|
|
||||||
props: {
|
|
||||||
lf: null,
|
|
||||||
catTurboData: Boolean
|
|
||||||
},
|
|
||||||
emits: ["catData"],
|
|
||||||
setup(props, { emit }) {
|
|
||||||
const controlButton3 = templateRef<HTMLElement | any>(
|
|
||||||
"controlButton3",
|
|
||||||
null
|
|
||||||
);
|
|
||||||
const controlButton4 = templateRef<HTMLElement | any>(
|
|
||||||
"controlButton4",
|
|
||||||
null
|
|
||||||
);
|
|
||||||
|
|
||||||
let focusIndex = ref(-1);
|
|
||||||
let titleLists = ref([
|
|
||||||
{
|
|
||||||
icon: "icon-zoom-out-hs",
|
|
||||||
text: "缩小",
|
|
||||||
disabled: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: "icon-enlarge-hs",
|
|
||||||
text: "放大",
|
|
||||||
disabled: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: "icon-full-screen-hs",
|
|
||||||
text: "适应",
|
|
||||||
disabled: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: "icon-previous-hs",
|
|
||||||
text: "上一步",
|
|
||||||
disabled: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: "icon-next-step-hs",
|
|
||||||
text: "下一步",
|
|
||||||
disabled: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: "icon-download-hs",
|
|
||||||
text: "下载图片",
|
|
||||||
disabled: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: "icon-watch-hs",
|
|
||||||
text: "查看数据",
|
|
||||||
disabled: false
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
const onControl = (item, key) => {
|
|
||||||
["zoom", "zoom", "resetZoom", "undo", "redo", "getSnapshot"].forEach(
|
|
||||||
(v, i) => {
|
|
||||||
let domControl = props.lf;
|
|
||||||
if (key === 1) {
|
|
||||||
domControl.zoom(true);
|
|
||||||
}
|
|
||||||
if (key === 6) {
|
|
||||||
emit("catData");
|
|
||||||
}
|
|
||||||
if (key === i) {
|
|
||||||
domControl[v]();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onEnter = key => {
|
|
||||||
focusIndex.value = key;
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
props.lf.on("history:change", ({ data: { undoAble, redoAble } }) => {
|
|
||||||
unref(titleLists)[3].disabled = unref(controlButton3).disabled =
|
|
||||||
!undoAble;
|
|
||||||
unref(titleLists)[4].disabled = unref(controlButton4).disabled =
|
|
||||||
!redoAble;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
focusIndex,
|
|
||||||
titleLists,
|
|
||||||
onControl,
|
|
||||||
onEnter
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
@import "./assets/iconfont/iconfont.css";
|
@import "./assets/iconfont/iconfont.css";
|
||||||
|
|
||||||
|
@ -1,23 +1,17 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import VueJsonPretty from "vue-json-pretty";
|
||||||
|
import "vue-json-pretty/lib/styles.css";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
graphData: Object
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<vue-json-pretty
|
<vue-json-pretty
|
||||||
:path="'res'"
|
:path="'res'"
|
||||||
:deep="3"
|
:deep="3"
|
||||||
:showLength="true"
|
:showLength="true"
|
||||||
:data="graphData"
|
:data="props.graphData"
|
||||||
></vue-json-pretty>
|
></vue-json-pretty>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import VueJsonPretty from "vue-json-pretty";
|
|
||||||
import "vue-json-pretty/lib/styles.css";
|
|
||||||
import { defineComponent } from "vue";
|
|
||||||
export default defineComponent({
|
|
||||||
name: "DataDialog",
|
|
||||||
props: {
|
|
||||||
graphData: Object
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
VueJsonPretty
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
@ -1,9 +1,36 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, unref } from "vue";
|
||||||
|
import { LogicFlow } from "@logicflow/core";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
lf: LogicFlow;
|
||||||
|
nodeList: ForDataType<undefined>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
lf: null,
|
||||||
|
nodeList: null
|
||||||
|
});
|
||||||
|
|
||||||
|
let properties = ref({
|
||||||
|
a: "efrwe",
|
||||||
|
b: "wewe"
|
||||||
|
});
|
||||||
|
|
||||||
|
const nodeDragNode = item => {
|
||||||
|
props.lf.dnd.startDrag({
|
||||||
|
type: item.type,
|
||||||
|
properties: unref(properties)
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<!-- 左侧bpmn元素选择器 -->
|
<!-- 左侧bpmn元素选择器 -->
|
||||||
<div class="node-panel">
|
<div class="node-panel">
|
||||||
<div
|
<div
|
||||||
class="node-item"
|
class="node-item"
|
||||||
v-for="item in nodeList"
|
v-for="item in props.nodeList"
|
||||||
:key="item.text"
|
:key="item.text"
|
||||||
@mousedown="nodeDragNode(item)"
|
@mousedown="nodeDragNode(item)"
|
||||||
>
|
>
|
||||||
@ -18,43 +45,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { defineComponent, ref, unref } from "vue";
|
|
||||||
export default defineComponent({
|
|
||||||
name: "NodePanel",
|
|
||||||
props: {
|
|
||||||
lf: Object,
|
|
||||||
nodeList: Array
|
|
||||||
},
|
|
||||||
setup(props) {
|
|
||||||
let node = ref({
|
|
||||||
type: "rect",
|
|
||||||
property: {
|
|
||||||
a: "efrwe",
|
|
||||||
b: "wewe"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
let properties = ref({
|
|
||||||
a: "efrwe",
|
|
||||||
b: "wewe"
|
|
||||||
});
|
|
||||||
|
|
||||||
const nodeDragNode = item => {
|
|
||||||
props.lf.dnd.startDrag({
|
|
||||||
type: item.type,
|
|
||||||
properties: unref(properties)
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
node,
|
|
||||||
properties,
|
|
||||||
nodeDragNode
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.node-panel {
|
.node-panel {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -1,8 +1,25 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
export interface Props {
|
||||||
|
isActive: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
isActive: false
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: "toggleClick"): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const toggleClick = () => {
|
||||||
|
emit("toggleClick");
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div style="padding: 0 15px" @click="toggleClick">
|
<div :class="classes.container" @click="toggleClick">
|
||||||
<svg
|
<svg
|
||||||
:class="{ 'is-active': isActive }"
|
:class="['hamburger', props.isActive ? 'is-active' : '']"
|
||||||
class="hamburger"
|
|
||||||
viewBox="0 0 1024 1024"
|
viewBox="0 0 1024 1024"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="64"
|
width="64"
|
||||||
@ -15,26 +32,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<style module="classes" scoped>
|
||||||
import { defineComponent } from "vue";
|
.container {
|
||||||
export default defineComponent({
|
padding: 0 15px;
|
||||||
name: "HamBurger",
|
}
|
||||||
props: {
|
</style>
|
||||||
isActive: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
emits: ["toggleClick"],
|
|
||||||
setup(props, ctx) {
|
|
||||||
const toggleClick = () => {
|
|
||||||
ctx.emit("toggleClick");
|
|
||||||
};
|
|
||||||
|
|
||||||
return { toggleClick };
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.hamburger {
|
.hamburger {
|
||||||
@ -44,7 +46,7 @@ export default defineComponent({
|
|||||||
height: 20px;
|
height: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hamburger.is-active {
|
.is-active {
|
||||||
transform: rotate(180deg);
|
transform: rotate(180deg);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,3 +1,99 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, PropType, getCurrentInstance, watch, nextTick, toRef } from "vue";
|
||||||
|
import { useRouter, useRoute } from "vue-router";
|
||||||
|
import { initRouter } from "/@/router";
|
||||||
|
import { storageSession } from "/@/utils/storage";
|
||||||
|
|
||||||
|
export interface ContextProps {
|
||||||
|
userName: string;
|
||||||
|
passWord: string;
|
||||||
|
verify: number | null;
|
||||||
|
svg: any;
|
||||||
|
telephone?: number;
|
||||||
|
dynamicText?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
ruleForm: {
|
||||||
|
type: Object as PropType<ContextProps>
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: "onBehavior", evt: Object): void;
|
||||||
|
(e: "refreshVerify"): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const instance = getCurrentInstance();
|
||||||
|
|
||||||
|
const model = toRef(props, "ruleForm");
|
||||||
|
let tips = ref<string>("注册");
|
||||||
|
let tipsFalse = ref<string>("登录");
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
watch(
|
||||||
|
route,
|
||||||
|
async ({ path }): Promise<void> => {
|
||||||
|
await nextTick();
|
||||||
|
path.includes("register")
|
||||||
|
? (tips.value = "登录") && (tipsFalse.value = "注册")
|
||||||
|
: (tips.value = "注册") && (tipsFalse.value = "登录");
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
const rules: Object = ref({
|
||||||
|
userName: [{ required: true, message: "请输入用户名", trigger: "blur" }],
|
||||||
|
passWord: [
|
||||||
|
{ required: true, message: "请输入密码", trigger: "blur" },
|
||||||
|
{ min: 6, message: "密码长度必须不小于6位", trigger: "blur" }
|
||||||
|
],
|
||||||
|
verify: [
|
||||||
|
{ required: true, message: "请输入验证码", trigger: "blur" },
|
||||||
|
{ type: "number", message: "验证码必须是数字类型", trigger: "blur" }
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// 点击登录或注册
|
||||||
|
const onBehavior = (evt: Object): void => {
|
||||||
|
// @ts-expect-error
|
||||||
|
instance.refs.ruleForm.validate((valid: boolean) => {
|
||||||
|
if (valid) {
|
||||||
|
emit("onBehavior", evt);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 刷新验证码
|
||||||
|
const refreshVerify = (): void => {
|
||||||
|
emit("refreshVerify");
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表单重置
|
||||||
|
const resetForm = (): void => {
|
||||||
|
// @ts-expect-error
|
||||||
|
instance.refs.ruleForm.resetFields();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 登录、注册页面切换
|
||||||
|
const changPage = (): void => {
|
||||||
|
tips.value === "注册" ? router.push("/register") : router.push("/login");
|
||||||
|
};
|
||||||
|
|
||||||
|
const noSecret = (): void => {
|
||||||
|
storageSession.setItem("info", {
|
||||||
|
username: "admin",
|
||||||
|
accessToken: "eyJhbGciOiJIUzUxMiJ9.test"
|
||||||
|
});
|
||||||
|
initRouter("admin").then(() => {});
|
||||||
|
router.push("/");
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<el-form :model="model" :rules="rules" ref="ruleForm" class="rule-form">
|
<el-form :model="model" :rules="rules" ref="ruleForm" class="rule-form">
|
||||||
@ -47,123 +143,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import {
|
|
||||||
ref,
|
|
||||||
defineComponent,
|
|
||||||
PropType,
|
|
||||||
getCurrentInstance,
|
|
||||||
watch,
|
|
||||||
nextTick,
|
|
||||||
toRef
|
|
||||||
} from "vue";
|
|
||||||
import { storageSession } from "/@/utils/storage";
|
|
||||||
|
|
||||||
export interface ContextProps {
|
|
||||||
userName: string;
|
|
||||||
passWord: string;
|
|
||||||
verify: number | null;
|
|
||||||
svg: any;
|
|
||||||
telephone?: number;
|
|
||||||
dynamicText?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
import { useRouter, useRoute } from "vue-router";
|
|
||||||
|
|
||||||
import { initRouter } from "/@/router";
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: "Info",
|
|
||||||
props: {
|
|
||||||
ruleForm: {
|
|
||||||
type: Object as PropType<ContextProps>,
|
|
||||||
require: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
emits: ["onBehavior", "refreshVerify"],
|
|
||||||
setup(props, ctx) {
|
|
||||||
const instance = getCurrentInstance();
|
|
||||||
|
|
||||||
const model = toRef(props, "ruleForm");
|
|
||||||
let tips = ref("注册");
|
|
||||||
let tipsFalse = ref("登录");
|
|
||||||
|
|
||||||
const route = useRoute();
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
watch(
|
|
||||||
route,
|
|
||||||
async ({ path }): Promise<void> => {
|
|
||||||
await nextTick();
|
|
||||||
path.includes("register")
|
|
||||||
? (tips.value = "登录") && (tipsFalse.value = "注册")
|
|
||||||
: (tips.value = "注册") && (tipsFalse.value = "登录");
|
|
||||||
},
|
|
||||||
{ immediate: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
const rules: Object = ref({
|
|
||||||
userName: [{ required: true, message: "请输入用户名", trigger: "blur" }],
|
|
||||||
passWord: [
|
|
||||||
{ required: true, message: "请输入密码", trigger: "blur" },
|
|
||||||
{ min: 6, message: "密码长度必须不小于6位", trigger: "blur" }
|
|
||||||
],
|
|
||||||
verify: [
|
|
||||||
{ required: true, message: "请输入验证码", trigger: "blur" },
|
|
||||||
{ type: "number", message: "验证码必须是数字类型", trigger: "blur" }
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
// 点击登录或注册
|
|
||||||
const onBehavior = (evt: Object): void => {
|
|
||||||
instance.refs.ruleForm.validate((valid: boolean) => {
|
|
||||||
if (valid) {
|
|
||||||
ctx.emit("onBehavior", evt);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// 刷新验证码
|
|
||||||
const refreshVerify = (): void => {
|
|
||||||
ctx.emit("refreshVerify");
|
|
||||||
};
|
|
||||||
|
|
||||||
// 表单重置
|
|
||||||
const resetForm = (): void => {
|
|
||||||
instance.refs.ruleForm.resetFields();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 登录、注册页面切换
|
|
||||||
const changPage = (): void => {
|
|
||||||
tips.value === "注册" ? router.push("/register") : router.push("/login");
|
|
||||||
};
|
|
||||||
|
|
||||||
const noSecret = (): void => {
|
|
||||||
storageSession.setItem("info", {
|
|
||||||
username: "admin",
|
|
||||||
accessToken: "eyJhbGciOiJIUzUxMiJ9.test"
|
|
||||||
});
|
|
||||||
initRouter("admin").then(() => {});
|
|
||||||
router.push("/");
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
model,
|
|
||||||
rules,
|
|
||||||
tips,
|
|
||||||
tipsFalse,
|
|
||||||
resetForm,
|
|
||||||
onBehavior,
|
|
||||||
refreshVerify,
|
|
||||||
changPage,
|
|
||||||
noSecret
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.info {
|
.info {
|
||||||
width: 30vw;
|
width: 30vw;
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { App } from "vue";
|
import { App } from "vue";
|
||||||
import amap from "./src/Amap.vue";
|
import amap from "./src/Amap.vue";
|
||||||
import baiduMap from "./src/BaiduMap.vue";
|
|
||||||
|
|
||||||
export const Amap = Object.assign(amap, {
|
export const Amap = Object.assign(amap, {
|
||||||
install(app: App) {
|
install(app: App) {
|
||||||
@ -8,13 +7,6 @@ export const Amap = Object.assign(amap, {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export const BaiduMap = Object.assign(baiduMap, {
|
|
||||||
install(app: App) {
|
|
||||||
app.component(baiduMap.name, baiduMap);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
Amap,
|
Amap
|
||||||
BaiduMap
|
|
||||||
};
|
};
|
||||||
|
@ -1,45 +1,17 @@
|
|||||||
<template>
|
<script setup lang="ts">
|
||||||
<div
|
|
||||||
id="mapview"
|
|
||||||
ref="mapview"
|
|
||||||
v-loading="loading"
|
|
||||||
element-loading-text="地图加载中"
|
|
||||||
element-loading-spinner="el-icon-loading"
|
|
||||||
element-loading-background="rgba(0, 0, 0, 0.8)"
|
|
||||||
></div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import AMapLoader from "@amap/amap-jsapi-loader";
|
import AMapLoader from "@amap/amap-jsapi-loader";
|
||||||
import {
|
import { reactive, getCurrentInstance, onBeforeMount, onUnmounted } from "vue";
|
||||||
reactive,
|
|
||||||
toRefs,
|
|
||||||
defineComponent,
|
|
||||||
onBeforeMount,
|
|
||||||
getCurrentInstance
|
|
||||||
} from "vue";
|
|
||||||
|
|
||||||
import { mapJson } from "/@/api/mock";
|
import { mapJson } from "/@/api/mock";
|
||||||
import { deviceDetection } from "/@/utils/deviceDetection";
|
import { deviceDetection } from "/@/utils/deviceDetection";
|
||||||
|
|
||||||
import greenCar from "/@/assets/green.png";
|
import greenCar from "/@/assets/green.png";
|
||||||
|
|
||||||
let MarkerCluster;
|
|
||||||
|
|
||||||
export interface MapConfigureInter {
|
export interface MapConfigureInter {
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
on: Fn;
|
on: Fn;
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
destroy?: Fn;
|
destroy?: Fn;
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
clearEvents?: Fn;
|
clearEvents?: Fn;
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
addControl?: Fn;
|
addControl?: Fn;
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
setCenter?: Fn;
|
setCenter?: Fn;
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
setZoom?: Fn;
|
setZoom?: Fn;
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
plugin?: Fn;
|
plugin?: Fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,116 +19,119 @@ export interface mapInter {
|
|||||||
loading: boolean;
|
loading: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default defineComponent({
|
let MarkerCluster;
|
||||||
name: "Amap",
|
let map: MapConfigureInter;
|
||||||
setup() {
|
|
||||||
const instance = getCurrentInstance();
|
|
||||||
let map: MapConfigureInter;
|
|
||||||
|
|
||||||
const mapSet: mapInter = reactive({
|
const instance = getCurrentInstance();
|
||||||
loading: deviceDetection() ? false : true
|
|
||||||
|
const mapSet: mapInter = reactive({
|
||||||
|
loading: deviceDetection() ? false : true
|
||||||
|
});
|
||||||
|
|
||||||
|
// 地图创建完成(动画关闭)
|
||||||
|
const complete = (): void => {
|
||||||
|
if (map) {
|
||||||
|
map.on("complete", () => {
|
||||||
|
mapSet.loading = false;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 地图创建完成(动画关闭)
|
onBeforeMount(() => {
|
||||||
const complete = (): void => {
|
if (!instance) return;
|
||||||
if (map) {
|
let { MapConfigure } = instance.appContext.config.globalProperties.$config;
|
||||||
map.on("complete", () => {
|
let { options } = MapConfigure;
|
||||||
mapSet.loading = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 销毁地图实例
|
AMapLoader.load({
|
||||||
const destroyMap = (): void => {
|
key: MapConfigure.amapKey,
|
||||||
if (map) {
|
version: "2.0",
|
||||||
map.destroy() && map.clearEvents("click");
|
plugins: ["AMap.MarkerCluster"]
|
||||||
}
|
})
|
||||||
};
|
.then(AMap => {
|
||||||
|
// 创建地图实例
|
||||||
|
map = new AMap.Map(instance.refs.mapview, options);
|
||||||
|
|
||||||
onBeforeMount(() => {
|
//地图中添加地图操作ToolBar插件
|
||||||
if (!instance) return;
|
map.plugin(["AMap.ToolBar", "AMap.MapType"], () => {
|
||||||
let { MapConfigure } =
|
map.addControl(new AMap.ToolBar());
|
||||||
instance.appContext.config.globalProperties.$config;
|
//地图类型切换
|
||||||
let { options } = MapConfigure;
|
map.addControl(
|
||||||
|
new AMap.MapType({
|
||||||
|
defaultType: 0
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
AMapLoader.load({
|
MarkerCluster = new AMap.MarkerCluster(map, [], {
|
||||||
key: MapConfigure.amapKey,
|
// 聚合网格像素大小
|
||||||
version: "2.0",
|
gridSize: 80,
|
||||||
plugins: ["AMap.MarkerCluster"]
|
maxZoom: 14,
|
||||||
})
|
renderMarker(ctx) {
|
||||||
.then(AMap => {
|
let { marker, data } = ctx;
|
||||||
// 创建地图实例
|
if (Array.isArray(data) && data[0]) {
|
||||||
map = new AMap.Map(instance.refs.mapview, options);
|
var { driver, plateNumber, orientation } = data[0];
|
||||||
|
var content = `<img style="transform: scale(1) rotate(${
|
||||||
//地图中添加地图操作ToolBar插件
|
360 - Number(orientation)
|
||||||
map.plugin(["AMap.ToolBar", "AMap.MapType"], () => {
|
}deg);" src='${greenCar}' />`;
|
||||||
map.addControl(new AMap.ToolBar());
|
marker.setContent(content);
|
||||||
//地图类型切换
|
marker.setLabel({
|
||||||
map.addControl(
|
direction: "bottom",
|
||||||
new AMap.MapType({
|
//设置文本标注偏移量
|
||||||
defaultType: 0
|
offset: new AMap.Pixel(-4, 0),
|
||||||
})
|
//设置文本标注内容
|
||||||
);
|
content: `<div> ${plateNumber}(${driver})</div>`
|
||||||
});
|
|
||||||
|
|
||||||
MarkerCluster = new AMap.MarkerCluster(map, [], {
|
|
||||||
gridSize: 80, // 聚合网格像素大小
|
|
||||||
maxZoom: 14,
|
|
||||||
renderMarker(ctx) {
|
|
||||||
let { marker, data } = ctx;
|
|
||||||
if (Array.isArray(data) && data[0]) {
|
|
||||||
var { driver, plateNumber, orientation } = data[0];
|
|
||||||
var content = `<img style="transform: scale(1) rotate(${
|
|
||||||
360 - Number(orientation)
|
|
||||||
}deg);" src='${greenCar}' />`;
|
|
||||||
marker.setContent(content);
|
|
||||||
marker.setLabel({
|
|
||||||
direction: "bottom",
|
|
||||||
offset: new AMap.Pixel(-4, 0), //设置文本标注偏移量
|
|
||||||
content: `<div> ${plateNumber}(${driver})</div>` //设置文本标注内容
|
|
||||||
});
|
|
||||||
marker.setOffset(new AMap.Pixel(-18, -10));
|
|
||||||
marker.on("click", ({ lnglat }) => {
|
|
||||||
map.setZoom(13); //设置地图层级
|
|
||||||
map.setCenter(lnglat);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 获取模拟车辆信息
|
|
||||||
mapJson()
|
|
||||||
.then(res => {
|
|
||||||
let points: object = res.info.map((v: any) => {
|
|
||||||
return {
|
|
||||||
lnglat: [v.lng, v.lat],
|
|
||||||
...v
|
|
||||||
};
|
|
||||||
});
|
|
||||||
if (MarkerCluster) MarkerCluster.setData(points);
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.log("err:", err);
|
|
||||||
});
|
});
|
||||||
|
marker.setOffset(new AMap.Pixel(-18, -10));
|
||||||
|
marker.on("click", ({ lnglat }) => {
|
||||||
|
map.setZoom(13); //设置地图层级
|
||||||
|
map.setCenter(lnglat);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
complete();
|
// 获取模拟车辆信息
|
||||||
|
mapJson()
|
||||||
|
.then(res => {
|
||||||
|
let points: object = res.info.map((v: any) => {
|
||||||
|
return {
|
||||||
|
lnglat: [v.lng, v.lat],
|
||||||
|
...v
|
||||||
|
};
|
||||||
|
});
|
||||||
|
if (MarkerCluster) MarkerCluster.setData(points);
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(err => {
|
||||||
mapSet.loading = false;
|
console.log("err:", err);
|
||||||
throw "地图加载失败,请重新加载";
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
complete();
|
||||||
...toRefs(mapSet),
|
})
|
||||||
complete,
|
.catch(() => {
|
||||||
destroyMap,
|
mapSet.loading = false;
|
||||||
greenCar
|
throw "地图加载失败,请重新加载";
|
||||||
};
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (map) {
|
||||||
|
// 销毁地图实例
|
||||||
|
map.destroy() && map.clearEvents("click");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
id="mapview"
|
||||||
|
ref="mapview"
|
||||||
|
v-loading="mapSet.loading"
|
||||||
|
element-loading-text="地图加载中"
|
||||||
|
element-loading-spinner="el-icon-loading"
|
||||||
|
element-loading-background="rgba(0, 0, 0, 0.8)"
|
||||||
|
></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
#mapview {
|
#mapview {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div></div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
export default {
|
|
||||||
name: "BaiduMap",
|
|
||||||
setup() {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,7 @@
|
|||||||
* @desc AnimationFrame简单兼容hack
|
* @desc AnimationFrame简单兼容hack
|
||||||
*/
|
*/
|
||||||
export const animationFrame = () => {
|
export const animationFrame = () => {
|
||||||
window.cancelAnimationFrame = (function () {
|
window.cancelAnimationFrame = (() => {
|
||||||
return (
|
return (
|
||||||
window.cancelAnimationFrame ||
|
window.cancelAnimationFrame ||
|
||||||
window.webkitCancelAnimationFrame ||
|
window.webkitCancelAnimationFrame ||
|
||||||
|
@ -21,35 +21,37 @@ let overList = [];
|
|||||||
// 存放第一个选中的元素和最后一个选中元素,只能存放这两个元素
|
// 存放第一个选中的元素和最后一个选中元素,只能存放这两个元素
|
||||||
let selectedList = [];
|
let selectedList = [];
|
||||||
|
|
||||||
export default defineComponent({
|
const props = {
|
||||||
name: "Selector",
|
HsKey: {
|
||||||
props: {
|
type: Number || String,
|
||||||
HsKey: {
|
default: 0
|
||||||
type: Number || String,
|
},
|
||||||
default: 0
|
disabled: {
|
||||||
},
|
type: Boolean,
|
||||||
disabled: {
|
default: false
|
||||||
type: Boolean,
|
},
|
||||||
default: false
|
value: {
|
||||||
},
|
type: Number,
|
||||||
value: {
|
default: 0
|
||||||
type: Number,
|
},
|
||||||
default: 0
|
max: {
|
||||||
},
|
type: Array,
|
||||||
max: {
|
default() {
|
||||||
type: Array,
|
return [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||||
default() {
|
|
||||||
return [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 回显数据的索引,长度必须是2
|
|
||||||
echo: {
|
|
||||||
type: Array,
|
|
||||||
default() {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// 回显数据的索引,长度必须是2
|
||||||
|
echo: {
|
||||||
|
type: Array,
|
||||||
|
default() {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: "Selector",
|
||||||
|
props,
|
||||||
emits: ["selectedVal"],
|
emits: ["selectedVal"],
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const instance = getCurrentInstance();
|
const instance = getCurrentInstance();
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
let config: object = {};
|
let config: object = {};
|
||||||
|
|
||||||
const setConfig = (cfg?: any) => {
|
const setConfig = (cfg?: unknown) => {
|
||||||
config = Object.assign(config, cfg);
|
config = Object.assign(config, cfg);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { useFullscreen } from "@vueuse/core";
|
||||||
|
|
||||||
|
const { isFullscreen, toggle } = useFullscreen();
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="screen-full" @click="toggle">
|
<div class="screen-full" @click="toggle">
|
||||||
<i
|
<i
|
||||||
@ -15,23 +21,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
|
||||||
import { useFullscreen } from "@vueuse/core";
|
|
||||||
import { defineComponent } from "vue";
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: "screenfull",
|
|
||||||
setup() {
|
|
||||||
const { isFullscreen, toggle } = useFullscreen();
|
|
||||||
|
|
||||||
return {
|
|
||||||
isFullscreen,
|
|
||||||
toggle
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.screen-full {
|
.screen-full {
|
||||||
width: 40px;
|
width: 40px;
|
||||||
|
17
src/main.ts
17
src/main.ts
@ -1,19 +1,17 @@
|
|||||||
import { createApp, Directive } from "vue";
|
|
||||||
import App from "./App.vue";
|
import App from "./App.vue";
|
||||||
import router from "./router";
|
import router from "./router";
|
||||||
import { setupStore } from "/@/store";
|
import { setupStore } from "/@/store";
|
||||||
|
import { createApp, Directive } from "vue";
|
||||||
import { useElementPlus } from "../src/plugins/element-plus";
|
|
||||||
import { useTable } from "../src/plugins/vxe-table";
|
|
||||||
import { usI18n } from "../src/plugins/i18n";
|
import { usI18n } from "../src/plugins/i18n";
|
||||||
|
import { useTable } from "../src/plugins/vxe-table";
|
||||||
|
import { useElementPlus } from "../src/plugins/element-plus";
|
||||||
|
|
||||||
|
import "animate.css";
|
||||||
// 导入公共样式
|
// 导入公共样式
|
||||||
import "./style/index.scss";
|
import "./style/index.scss";
|
||||||
// 导入字体图标
|
// 导入字体图标
|
||||||
import "./assets/iconfont/iconfont.js";
|
import "./assets/iconfont/iconfont.js";
|
||||||
import "./assets/iconfont/iconfont.css";
|
import "./assets/iconfont/iconfont.css";
|
||||||
import "animate.css";
|
|
||||||
|
|
||||||
import "v-contextmenu/dist/themes/default.css";
|
import "v-contextmenu/dist/themes/default.css";
|
||||||
|
|
||||||
import { setConfig, getConfig } from "./config";
|
import { setConfig, getConfig } from "./config";
|
||||||
@ -25,7 +23,7 @@ app.config.globalProperties.$config = getConfig();
|
|||||||
|
|
||||||
// 响应式storage
|
// 响应式storage
|
||||||
import Storage from "responsive-storage";
|
import Storage from "responsive-storage";
|
||||||
|
// @ts-ignore
|
||||||
app.use(Storage, {
|
app.use(Storage, {
|
||||||
// 默认显示首页tag
|
// 默认显示首页tag
|
||||||
routesInStorage: {
|
routesInStorage: {
|
||||||
@ -58,7 +56,7 @@ Object.keys(directives).forEach(key => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 获取项目动态全局配置
|
// 获取项目动态全局配置
|
||||||
export const getServerConfig = async (): Promise<any> => {
|
export const getServerConfig = async (): Promise<undefined> => {
|
||||||
return axios({
|
return axios({
|
||||||
baseURL: "",
|
baseURL: "",
|
||||||
method: "get",
|
method: "get",
|
||||||
@ -87,10 +85,7 @@ export const getServerConfig = async (): Promise<any> => {
|
|||||||
|
|
||||||
getServerConfig().then(async () => {
|
getServerConfig().then(async () => {
|
||||||
setupStore(app);
|
setupStore(app);
|
||||||
|
|
||||||
app.use(router).use(useElementPlus).use(useTable).use(usI18n);
|
app.use(router).use(useElementPlus).use(useTable).use(usI18n);
|
||||||
|
|
||||||
await router.isReady();
|
await router.isReady();
|
||||||
|
|
||||||
app.mount("#app");
|
app.mount("#app");
|
||||||
});
|
});
|
||||||
|
@ -7,6 +7,7 @@ import enVxeTable from "vxe-table/lib/locale/lang/en-US";
|
|||||||
import enLocale from "element-plus/lib/locale/lang/en";
|
import enLocale from "element-plus/lib/locale/lang/en";
|
||||||
import zhLocale from "element-plus/lib/locale/lang/zh-cn";
|
import zhLocale from "element-plus/lib/locale/lang/zh-cn";
|
||||||
|
|
||||||
|
// 导航菜单配置
|
||||||
export const menusConfig = {
|
export const menusConfig = {
|
||||||
zh: {
|
zh: {
|
||||||
message: {
|
message: {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
import "xe-utils";
|
||||||
import { App } from "vue";
|
import { App } from "vue";
|
||||||
import { i18n } from "../i18n/index";
|
import { i18n } from "../i18n/index";
|
||||||
import "font-awesome/css/font-awesome.css";
|
import "font-awesome/css/font-awesome.css";
|
||||||
import "xe-utils";
|
|
||||||
import {
|
import {
|
||||||
// 核心
|
// 核心
|
||||||
VXETable,
|
VXETable,
|
||||||
@ -62,6 +62,7 @@ VXETable.setup({
|
|||||||
clearable: true
|
clearable: true
|
||||||
},
|
},
|
||||||
// 对组件内置的提示语进行国际化翻译
|
// 对组件内置的提示语进行国际化翻译
|
||||||
|
// @ts-ignore
|
||||||
i18n: (key, args) => i18n.global.t(key, args),
|
i18n: (key, args) => i18n.global.t(key, args),
|
||||||
// 可选,对参数中的列头、校验提示..等进行自动翻译(只对支持国际化的有效)
|
// 可选,对参数中的列头、校验提示..等进行自动翻译(只对支持国际化的有效)
|
||||||
translate(key, args) {
|
translate(key, args) {
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
import { createRouter, createWebHashHistory, Router } from "vue-router";
|
import {
|
||||||
|
createRouter,
|
||||||
|
createWebHashHistory,
|
||||||
|
Router,
|
||||||
|
RouteComponent
|
||||||
|
} from "vue-router";
|
||||||
|
|
||||||
|
import Layout from "/@/layout/index.vue";
|
||||||
import homeRouter from "./modules/home";
|
import homeRouter from "./modules/home";
|
||||||
import flowChartRouter from "./modules/flowchart";
|
import flowChartRouter from "./modules/flowchart";
|
||||||
import editorRouter from "./modules/editor";
|
import editorRouter from "./modules/editor";
|
||||||
@ -9,17 +15,15 @@ import errorRouter from "./modules/error";
|
|||||||
import externalLink from "./modules/externalLink";
|
import externalLink from "./modules/externalLink";
|
||||||
import remainingRouter from "./modules/remaining"; //静态路由
|
import remainingRouter from "./modules/remaining"; //静态路由
|
||||||
|
|
||||||
import { storageSession } from "../utils/storage";
|
|
||||||
import { i18n } from "/@/plugins/i18n";
|
import { i18n } from "/@/plugins/i18n";
|
||||||
|
import { getAsyncRoutes } from "/@/api/routes";
|
||||||
|
import { storageSession } from "../utils/storage";
|
||||||
import { usePermissionStoreHook } from "/@/store/modules/permission";
|
import { usePermissionStoreHook } from "/@/store/modules/permission";
|
||||||
|
|
||||||
import { getAsyncRoutes } from "/@/api/routes";
|
|
||||||
|
|
||||||
import Layout from "/@/layout/index.vue";
|
|
||||||
// https://cn.vitejs.dev/guide/features.html#glob-import
|
// https://cn.vitejs.dev/guide/features.html#glob-import
|
||||||
const modulesRoutes = import.meta.glob("/src/views/*/*/*.vue");
|
const modulesRoutes = import.meta.glob("/src/views/*/*/*.vue");
|
||||||
|
|
||||||
const constantRoutes: Array<any> = [
|
const constantRoutes: Array<RouteComponent> = [
|
||||||
homeRouter,
|
homeRouter,
|
||||||
flowChartRouter,
|
flowChartRouter,
|
||||||
editorRouter,
|
editorRouter,
|
||||||
@ -125,8 +129,10 @@ const whiteList = ["/login", "/register"];
|
|||||||
router.beforeEach((to, _from, next) => {
|
router.beforeEach((to, _from, next) => {
|
||||||
const name = storageSession.getItem("info");
|
const name = storageSession.getItem("info");
|
||||||
NProgress.start();
|
NProgress.start();
|
||||||
|
// @ts-ignore
|
||||||
const { t } = i18n.global;
|
const { t } = i18n.global;
|
||||||
to.meta.title ? (document.title = t(to.meta.title)) : ""; // 动态title
|
// @ts-ignore
|
||||||
|
to.meta.title ? (document.title = t(to.meta.title)) : "";
|
||||||
if (name) {
|
if (name) {
|
||||||
if (_from?.name) {
|
if (_from?.name) {
|
||||||
next();
|
next();
|
||||||
|
@ -10,7 +10,6 @@ class algorithmProxy implements ProxyAlgorithm {
|
|||||||
return Object.keys(val)
|
return Object.keys(val)
|
||||||
.map(v => {
|
.map(v => {
|
||||||
return {
|
return {
|
||||||
// @ts-ignore
|
|
||||||
...val[v],
|
...val[v],
|
||||||
key: v
|
key: v
|
||||||
};
|
};
|
||||||
|
@ -5,7 +5,8 @@ import { excludeProps } from "./utils";
|
|||||||
*/
|
*/
|
||||||
export const defaultConfig: AxiosRequestConfig = {
|
export const defaultConfig: AxiosRequestConfig = {
|
||||||
baseURL: "",
|
baseURL: "",
|
||||||
timeout: 10000, //10秒超时
|
//10秒超时
|
||||||
|
timeout: 10000,
|
||||||
headers: {
|
headers: {
|
||||||
Accept: "application/json, text/plain, */*",
|
Accept: "application/json, text/plain, */*",
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
export const hasClass = (ele: Element, cls: string): any => {
|
export const hasClass = (ele: RefType<any>, cls: string): any => {
|
||||||
return !!ele.className.match(new RegExp("(\\s|^)" + cls + "(\\s|$)"));
|
return !!ele.className.match(new RegExp("(\\s|^)" + cls + "(\\s|$)"));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const addClass = (ele: Element, cls: string, extracls?: string): any => {
|
export const addClass = (
|
||||||
|
ele: RefType<any>,
|
||||||
|
cls: string,
|
||||||
|
extracls?: string
|
||||||
|
): any => {
|
||||||
if (!hasClass(ele, cls)) ele.className += " " + cls;
|
if (!hasClass(ele, cls)) ele.className += " " + cls;
|
||||||
if (extracls) {
|
if (extracls) {
|
||||||
if (!hasClass(ele, extracls)) ele.className += " " + extracls;
|
if (!hasClass(ele, extracls)) ele.className += " " + extracls;
|
||||||
@ -10,7 +14,7 @@ export const addClass = (ele: Element, cls: string, extracls?: string): any => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const removeClass = (
|
export const removeClass = (
|
||||||
ele: Element,
|
ele: RefType<any>,
|
||||||
cls: string,
|
cls: string,
|
||||||
extracls?: string
|
extracls?: string
|
||||||
): any => {
|
): any => {
|
||||||
@ -29,7 +33,7 @@ export const removeClass = (
|
|||||||
export const toggleClass = (
|
export const toggleClass = (
|
||||||
flag: boolean,
|
flag: boolean,
|
||||||
clsName: string,
|
clsName: string,
|
||||||
target?: HTMLElement
|
target?: RefType<any>
|
||||||
): any => {
|
): any => {
|
||||||
const targetEl = target || document.body;
|
const targetEl = target || document.body;
|
||||||
let { className } = targetEl;
|
let { className } = targetEl;
|
||||||
|
@ -2,11 +2,16 @@ import NProgress from "nprogress";
|
|||||||
import "nprogress/nprogress.css";
|
import "nprogress/nprogress.css";
|
||||||
|
|
||||||
NProgress.configure({
|
NProgress.configure({
|
||||||
easing: "ease", // 动画方式
|
// 动画方式
|
||||||
speed: 500, // 递增进度条的速度
|
easing: "ease",
|
||||||
showSpinner: true, // 是否显示加载ico
|
// 递增进度条的速度
|
||||||
trickleSpeed: 200, // 自动递增间隔
|
speed: 500,
|
||||||
minimum: 0.3 // 初始化时的最小百分比
|
// 是否显示加载ico
|
||||||
|
showSpinner: true,
|
||||||
|
// 自动递增间隔
|
||||||
|
trickleSpeed: 200,
|
||||||
|
// 初始化时的最小百分比
|
||||||
|
minimum: 0.3
|
||||||
});
|
});
|
||||||
|
|
||||||
export default NProgress;
|
export default NProgress;
|
||||||
|
@ -30,4 +30,5 @@ propTypes.extend([
|
|||||||
type: undefined
|
type: undefined
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export { propTypes };
|
export { propTypes };
|
||||||
|
@ -1,24 +1,17 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue";
|
||||||
|
|
||||||
|
const url = ref(
|
||||||
|
process.env.NODE_ENV === "production"
|
||||||
|
? "/manages/html/button.html"
|
||||||
|
: "/html/button.html"
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<iframe :src="url" frameborder="0" class="iframe"></iframe>
|
<iframe :src="url" frameborder="0" class="iframe"></iframe>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { ref } from "vue";
|
|
||||||
export default {
|
|
||||||
name: "reButton",
|
|
||||||
setup() {
|
|
||||||
const url = ref(
|
|
||||||
process.env.NODE_ENV === "production"
|
|
||||||
? "/manages/html/button.html"
|
|
||||||
: "/html/button.html"
|
|
||||||
);
|
|
||||||
return {
|
|
||||||
url
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.iframe {
|
.iframe {
|
||||||
width: 98%;
|
width: 98%;
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import basic from "./basic.vue";
|
||||||
|
import menuGroup from "./menuGroup.vue";
|
||||||
|
import menuDynamic from "./menuDynamic.vue";
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div style="margin: 10px">
|
<div style="margin: 10px">
|
||||||
<el-row :gutter="24">
|
<el-row :gutter="24">
|
||||||
@ -16,20 +22,3 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import basic from "./basic.vue";
|
|
||||||
import menuGroup from "./menuGroup.vue";
|
|
||||||
import menuDynamic from "./menuDynamic.vue";
|
|
||||||
export default {
|
|
||||||
name: "reContextmenu",
|
|
||||||
components: {
|
|
||||||
basic,
|
|
||||||
menuGroup,
|
|
||||||
menuDynamic
|
|
||||||
},
|
|
||||||
setup() {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ReNormalCountTo, ReboundCountTo } from "/@/components/ReCountTo";
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div style="margin: 10px">
|
<div style="margin: 10px">
|
||||||
<el-row :gutter="24">
|
<el-row :gutter="24">
|
||||||
@ -30,21 +34,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { ReNormalCountTo, ReboundCountTo } from "/@/components/ReCountTo";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "reCountTo",
|
|
||||||
components: {
|
|
||||||
ReNormalCountTo,
|
|
||||||
ReboundCountTo
|
|
||||||
},
|
|
||||||
setup() {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.flex {
|
.flex {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -1,3 +1,29 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, nextTick, getCurrentInstance } from "vue";
|
||||||
|
import Cropper from "/@/components/ReCropper";
|
||||||
|
import img from "./picture.jpeg";
|
||||||
|
|
||||||
|
const instance = getCurrentInstance();
|
||||||
|
let info = ref<object>(null);
|
||||||
|
let cropperImg = ref<string>("");
|
||||||
|
|
||||||
|
const onCropper = (): void => {
|
||||||
|
nextTick(() => {
|
||||||
|
// @ts-expect-error
|
||||||
|
instance.refs.refCropper.cropper.getCroppedCanvas().toBlob(blob => {
|
||||||
|
let fileReader: FileReader = new FileReader();
|
||||||
|
fileReader.onloadend = (e: ProgressEvent) => {
|
||||||
|
// @ts-ignore
|
||||||
|
cropperImg.value = e.target.result;
|
||||||
|
// @ts-expect-error
|
||||||
|
info.value = instance.refs.refCropper.cropper.getData();
|
||||||
|
};
|
||||||
|
fileReader.readAsDataURL(blob);
|
||||||
|
}, "image/jpeg");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div style="margin: 10px">
|
<div style="margin: 10px">
|
||||||
<div class="cropper-container">
|
<div class="cropper-container">
|
||||||
@ -9,44 +35,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { ref, nextTick, getCurrentInstance } from "vue";
|
|
||||||
import Cropper from "/@/components/ReCropper";
|
|
||||||
import img from "./picture.jpeg";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "reCropping",
|
|
||||||
components: {
|
|
||||||
Cropper
|
|
||||||
},
|
|
||||||
setup() {
|
|
||||||
const instance = getCurrentInstance();
|
|
||||||
let info = ref("");
|
|
||||||
let cropperImg = ref("");
|
|
||||||
|
|
||||||
const onCropper = (): void => {
|
|
||||||
nextTick(() => {
|
|
||||||
instance.refs.refCropper.cropper.getCroppedCanvas().toBlob(blob => {
|
|
||||||
let fileReader: FileReader = new FileReader();
|
|
||||||
fileReader.onloadend = (e: any) => {
|
|
||||||
cropperImg.value = e.target.result;
|
|
||||||
info.value = instance.refs.refCropper.cropper.getData();
|
|
||||||
};
|
|
||||||
fileReader.readAsDataURL(blob);
|
|
||||||
}, "image/jpeg");
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
img,
|
|
||||||
info,
|
|
||||||
cropperImg,
|
|
||||||
onCropper
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.cropper-container {
|
.cropper-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -1,3 +1,51 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted } from "vue";
|
||||||
|
import draggable from "vuedraggable/src/vuedraggable";
|
||||||
|
|
||||||
|
let gridLists = ref<Array<Object>>([
|
||||||
|
{ grid: "cn", num: 1 },
|
||||||
|
{ grid: "cn", num: 2 },
|
||||||
|
{ grid: "cn", num: 3 },
|
||||||
|
{ grid: "cn", num: 4 },
|
||||||
|
{ grid: "cn", num: 5 },
|
||||||
|
{ grid: "cn", num: 6 },
|
||||||
|
{ grid: "cn", num: 7 },
|
||||||
|
{ grid: "cn", num: 8 },
|
||||||
|
{ grid: "cn", num: 9 }
|
||||||
|
]);
|
||||||
|
|
||||||
|
let lists = ref<Array<Object>>([
|
||||||
|
{ people: "cn", id: 1, name: "www.itxst.com" },
|
||||||
|
{ people: "cn", id: 2, name: "www.baidu.com" },
|
||||||
|
{ people: "cn", id: 3, name: "www.taobao.com" },
|
||||||
|
{ people: "cn", id: 4, name: "www.google.com" }
|
||||||
|
]);
|
||||||
|
|
||||||
|
let cutLists = ref<Array<Object>>([
|
||||||
|
{ people: "cn", id: 1, name: "cut1" },
|
||||||
|
{ people: "cn", id: 2, name: "cut2" },
|
||||||
|
{ people: "cn", id: 3, name: "cut3" },
|
||||||
|
{ people: "cn", id: 4, name: "cut4" }
|
||||||
|
]);
|
||||||
|
|
||||||
|
const change = (evt): void => {
|
||||||
|
console.log("evt: ", evt);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// 使用原生sortable实现元素位置切换
|
||||||
|
// @ts-ignore
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
new Sortable(document.querySelector(".cut-container"), {
|
||||||
|
swap: true,
|
||||||
|
forceFallback: true,
|
||||||
|
chosenClass: "chosen",
|
||||||
|
swapClass: "highlight",
|
||||||
|
animation: 300
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="drag-container">
|
<div class="drag-container">
|
||||||
<!-- grid列表拖拽 -->
|
<!-- grid列表拖拽 -->
|
||||||
@ -72,64 +120,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import draggable from "vuedraggable/src/vuedraggable";
|
|
||||||
import { reactive, toRefs, onMounted } from "vue";
|
|
||||||
export default {
|
|
||||||
name: "reDraggable",
|
|
||||||
components: { draggable },
|
|
||||||
setup() {
|
|
||||||
const myArray = reactive({
|
|
||||||
gridLists: [
|
|
||||||
{ grid: "cn", num: 1 },
|
|
||||||
{ grid: "cn", num: 2 },
|
|
||||||
{ grid: "cn", num: 3 },
|
|
||||||
{ grid: "cn", num: 4 },
|
|
||||||
{ grid: "cn", num: 5 },
|
|
||||||
{ grid: "cn", num: 6 },
|
|
||||||
{ grid: "cn", num: 7 },
|
|
||||||
{ grid: "cn", num: 8 },
|
|
||||||
{ grid: "cn", num: 9 }
|
|
||||||
],
|
|
||||||
lists: [
|
|
||||||
{ people: "cn", id: 1, name: "www.itxst.com" },
|
|
||||||
{ people: "cn", id: 2, name: "www.baidu.com" },
|
|
||||||
{ people: "cn", id: 3, name: "www.taobao.com" },
|
|
||||||
{ people: "cn", id: 4, name: "www.google.com" }
|
|
||||||
],
|
|
||||||
cutLists: [
|
|
||||||
{ people: "cn", id: 1, name: "cut1" },
|
|
||||||
{ people: "cn", id: 2, name: "cut2" },
|
|
||||||
{ people: "cn", id: 3, name: "cut3" },
|
|
||||||
{ people: "cn", id: 4, name: "cut4" }
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
const change = (evt): void => {
|
|
||||||
console.log("evt: ", evt);
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
// 使用原生sortable实现元素位置切换
|
|
||||||
// @ts-ignore
|
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
new Sortable(document.querySelector(".cut-container"), {
|
|
||||||
swap: true,
|
|
||||||
forceFallback: true,
|
|
||||||
chosenClass: "chosen",
|
|
||||||
swapClass: "highlight",
|
|
||||||
animation: 300
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
...toRefs(myArray),
|
|
||||||
change
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
/* grid列表拖拽 */
|
/* grid列表拖拽 */
|
||||||
.grid-container {
|
.grid-container {
|
||||||
|
@ -1,22 +1,13 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { Amap } from "/@/components/ReMap";
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="map">
|
<div class="map">
|
||||||
<Amap />
|
<Amap />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { Amap } from "/@/components/ReMap";
|
|
||||||
export default {
|
|
||||||
name: "reMap",
|
|
||||||
components: {
|
|
||||||
Amap
|
|
||||||
},
|
|
||||||
setup() {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.map {
|
.map {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -1,3 +1,51 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, unref } from "vue";
|
||||||
|
import { templateRef } from "@vueuse/core";
|
||||||
|
import SeamlessScroll from "/@/components/ReSeamlessScroll";
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
const scroll = templateRef<ElRef | null>("scroll", null);
|
||||||
|
|
||||||
|
let listData = ref<Array<Object>>([
|
||||||
|
{
|
||||||
|
title: "无缝滚动第一行无缝滚动第一行!!!!!!!!!!"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "无缝滚动第二行无缝滚动第二行!!!!!!!!!!"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "无缝滚动第三行无缝滚动第三行!!!!!!!!!!"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "无缝滚动第四行无缝滚动第四行!!!!!!!!!!"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "无缝滚动第五行无缝滚动第五行!!!!!!!!!!"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "无缝滚动第六行无缝滚动第六行!!!!!!!!!!"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "无缝滚动第七行无缝滚动第七行!!!!!!!!!!"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "无缝滚动第八行无缝滚动第八行!!!!!!!!!!"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "无缝滚动第九行无缝滚动第九行!!!!!!!!!!"
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
let classOption = ref<Object>({
|
||||||
|
direction: "top"
|
||||||
|
});
|
||||||
|
|
||||||
|
function changeDirection(val) {
|
||||||
|
unref(scroll).reset();
|
||||||
|
unref(classOption).direction = val;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<el-space wrap>
|
<el-space wrap>
|
||||||
<el-card class="box-card">
|
<el-card class="box-card">
|
||||||
@ -60,68 +108,6 @@
|
|||||||
</el-space>
|
</el-space>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { ref, unref } from "vue";
|
|
||||||
import { templateRef } from "@vueuse/core";
|
|
||||||
|
|
||||||
import SeamlessScroll from "/@/components/ReSeamlessScroll";
|
|
||||||
export default {
|
|
||||||
name: "reSeamlessScroll",
|
|
||||||
components: {
|
|
||||||
SeamlessScroll
|
|
||||||
},
|
|
||||||
setup() {
|
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
const scroll = templateRef<ElRef | null>("scroll", null);
|
|
||||||
|
|
||||||
let listData = ref([
|
|
||||||
{
|
|
||||||
title: "无缝滚动第一行无缝滚动第一行!!!!!!!!!!"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "无缝滚动第二行无缝滚动第二行!!!!!!!!!!"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "无缝滚动第三行无缝滚动第三行!!!!!!!!!!"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "无缝滚动第四行无缝滚动第四行!!!!!!!!!!"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "无缝滚动第五行无缝滚动第五行!!!!!!!!!!"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "无缝滚动第六行无缝滚动第六行!!!!!!!!!!"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "无缝滚动第七行无缝滚动第七行!!!!!!!!!!"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "无缝滚动第八行无缝滚动第八行!!!!!!!!!!"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "无缝滚动第九行无缝滚动第九行!!!!!!!!!!"
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
let classOption = ref({
|
|
||||||
direction: "top"
|
|
||||||
});
|
|
||||||
|
|
||||||
function changeDirection(val) {
|
|
||||||
unref(scroll).reset();
|
|
||||||
unref(classOption).direction = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
listData,
|
|
||||||
classOption,
|
|
||||||
changeDirection
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.box-card {
|
.box-card {
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
|
@ -1,3 +1,26 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue";
|
||||||
|
import Selector from "/@/components/ReSelector";
|
||||||
|
|
||||||
|
let selectRange = ref<string>("");
|
||||||
|
let dataLists = ref<Array<Object>>([
|
||||||
|
{
|
||||||
|
title: "基本使用",
|
||||||
|
echo: [],
|
||||||
|
disabled: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "回显模式",
|
||||||
|
echo: [2, 7],
|
||||||
|
disabled: true
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
const selectedVal = ({ left, right }): void => {
|
||||||
|
selectRange.value = `${left}-${right}`;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<el-card
|
<el-card
|
||||||
@ -21,38 +44,3 @@
|
|||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { ref } from "vue";
|
|
||||||
import Selector from "/@/components/ReSelector";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "reSelector",
|
|
||||||
components: { Selector },
|
|
||||||
setup() {
|
|
||||||
let selectRange = ref(null);
|
|
||||||
let dataLists = ref([
|
|
||||||
{
|
|
||||||
title: "基本使用",
|
|
||||||
echo: [],
|
|
||||||
disabled: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "回显模式",
|
|
||||||
echo: [2, 7],
|
|
||||||
disabled: true
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
const selectedVal = ({ left, right }) => {
|
|
||||||
selectRange.value = `${left}-${right}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
selectedVal,
|
|
||||||
selectRange,
|
|
||||||
dataLists
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
@ -1,3 +1,20 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import splitpane, { ContextProps } from "/@/components/ReSplitPane";
|
||||||
|
import { reactive } from "vue";
|
||||||
|
|
||||||
|
const settingLR: ContextProps = reactive({
|
||||||
|
minPercent: 20,
|
||||||
|
defaultPercent: 40,
|
||||||
|
split: "vertical"
|
||||||
|
});
|
||||||
|
|
||||||
|
const settingTB: ContextProps = reactive({
|
||||||
|
minPercent: 20,
|
||||||
|
defaultPercent: 40,
|
||||||
|
split: "horizontal"
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="split-pane">
|
<div class="split-pane">
|
||||||
<splitpane :splitSet="settingLR">
|
<splitpane :splitSet="settingLR">
|
||||||
@ -22,35 +39,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import splitpane, { ContextProps } from "/@/components/ReSplitPane";
|
|
||||||
import { reactive } from "vue";
|
|
||||||
export default {
|
|
||||||
name: "reSplitPane",
|
|
||||||
components: {
|
|
||||||
splitpane
|
|
||||||
},
|
|
||||||
setup() {
|
|
||||||
const settingLR: ContextProps = reactive({
|
|
||||||
minPercent: 20,
|
|
||||||
defaultPercent: 40,
|
|
||||||
split: "vertical"
|
|
||||||
});
|
|
||||||
|
|
||||||
const settingTB: ContextProps = reactive({
|
|
||||||
minPercent: 20,
|
|
||||||
defaultPercent: 40,
|
|
||||||
split: "horizontal"
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
settingLR,
|
|
||||||
settingTB
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
$W: 100%;
|
$W: 100%;
|
||||||
$H: 80vh;
|
$H: 80vh;
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
<template>
|
<script setup lang="ts">
|
||||||
<div id="mse"></div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { onMounted } from "vue";
|
import { onMounted } from "vue";
|
||||||
import Player from "xgplayer/dist/simple_player";
|
import Player from "xgplayer/dist/simple_player";
|
||||||
import volume from "xgplayer/dist/controls/volume";
|
import volume from "xgplayer/dist/controls/volume";
|
||||||
@ -10,28 +6,27 @@ import playbackRate from "xgplayer/dist/controls/playbackRate";
|
|||||||
import screenShot from "xgplayer/dist/controls/screenShot";
|
import screenShot from "xgplayer/dist/controls/screenShot";
|
||||||
import { deviceDetection } from "/@/utils/deviceDetection";
|
import { deviceDetection } from "/@/utils/deviceDetection";
|
||||||
|
|
||||||
export default {
|
onMounted(() => {
|
||||||
name: "reVideo",
|
new Player({
|
||||||
setup() {
|
id: "mse",
|
||||||
onMounted(() => {
|
autoplay: false,
|
||||||
new Player({
|
screenShot: true,
|
||||||
id: "mse",
|
url: "https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/mp4/xgplayer-demo-720p.mp4",
|
||||||
autoplay: false,
|
poster:
|
||||||
screenShot: true,
|
"https://s2.pstatp.com/cdn/expire-1-M/byted-player-videos/1.0.0/poster.jpg",
|
||||||
url: "https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/mp4/xgplayer-demo-720p.mp4",
|
fluid: deviceDetection(),
|
||||||
poster:
|
controlPlugins: [volume, playbackRate, screenShot],
|
||||||
"https://s2.pstatp.com/cdn/expire-1-M/byted-player-videos/1.0.0/poster.jpg",
|
//传入倍速可选数组
|
||||||
fluid: deviceDetection(),
|
playbackRate: [0.5, 0.75, 1, 1.5, 2]
|
||||||
controlPlugins: [volume, playbackRate, screenShot],
|
});
|
||||||
playbackRate: [0.5, 0.75, 1, 1.5, 2] //传入倍速可选数组
|
});
|
||||||
});
|
|
||||||
});
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<template>
|
||||||
|
<div id="mse"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
#mse {
|
#mse {
|
||||||
flex: auto;
|
flex: auto;
|
||||||
}
|
}
|
||||||
|
@ -1,47 +1,40 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: "reEditor"
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { onMounted, onBeforeUnmount, ref, unref } from "vue";
|
||||||
|
import WangEditor from "wangeditor";
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
const editor = ref(null);
|
||||||
|
const html = ref(null);
|
||||||
|
let instance: WangEditor;
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
instance = new WangEditor(unref(editor));
|
||||||
|
Object.assign(instance.config, {
|
||||||
|
onchange() {
|
||||||
|
html.value = instance.txt.html();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
instance.create();
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
instance.destroy();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div ref="editor"></div>
|
<div ref="editor"></div>
|
||||||
<div :innerHTML="content.html"></div>
|
<div :innerHTML="html"></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
|
||||||
import { onMounted, onBeforeUnmount, ref, reactive } from "vue";
|
|
||||||
import WangEditor from "wangeditor";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "reEditor",
|
|
||||||
setup() {
|
|
||||||
const editor = ref();
|
|
||||||
const content = reactive({
|
|
||||||
html: "",
|
|
||||||
text: ""
|
|
||||||
});
|
|
||||||
|
|
||||||
let instance;
|
|
||||||
onMounted(() => {
|
|
||||||
instance = new WangEditor(editor.value);
|
|
||||||
Object.assign(instance.config, {
|
|
||||||
onchange() {
|
|
||||||
content.html = instance.txt.html();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
instance.create();
|
|
||||||
});
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
instance.destroy();
|
|
||||||
instance = null;
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
editor,
|
|
||||||
content
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
:deep(.w-e-text-container) {
|
:deep(.w-e-text-container) {
|
||||||
z-index: 99 !important;
|
z-index: 99 !important;
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import imgs from "/@/assets/401.gif";
|
||||||
|
import { ref } from "vue";
|
||||||
|
|
||||||
|
const img = ref(`${imgs}?${new Date()}`);
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="errPage-container">
|
<div class="errPage-container">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<h1 class="text-jumbo text-ginormous">CURD Admin</h1>
|
<h1 class="text-jumbo text-ginormous">Pure Admin</h1>
|
||||||
<h2>你没有权限去该页面</h2>
|
<h2>你没有权限去该页面</h2>
|
||||||
<h6>如有不满请联系你领导</h6>
|
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<img
|
<img
|
||||||
@ -18,20 +24,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import imgs from "/@/assets/401.gif";
|
|
||||||
import { ref } from "vue";
|
|
||||||
export default {
|
|
||||||
name: "401",
|
|
||||||
setup() {
|
|
||||||
const img = ref(`${imgs}?${new Date()}`);
|
|
||||||
return {
|
|
||||||
img
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.errPage-container {
|
.errPage-container {
|
||||||
width: 800px;
|
width: 800px;
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { computed } from "vue";
|
||||||
|
import four from "/@/assets/404.png";
|
||||||
|
import four_cloud from "/@/assets/404_cloud.png";
|
||||||
|
|
||||||
|
const message = computed(() => {
|
||||||
|
return "The webmaster said that you can not enter this page...";
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="wscn-http404-container">
|
<div class="wscn-http404-container">
|
||||||
<div class="wscn-http404">
|
<div class="wscn-http404">
|
||||||
@ -8,7 +18,7 @@
|
|||||||
<img class="pic-404__child right" :src="four_cloud" alt="404" />
|
<img class="pic-404__child right" :src="four_cloud" alt="404" />
|
||||||
</div>
|
</div>
|
||||||
<div class="bullshit">
|
<div class="bullshit">
|
||||||
<div class="bullshit__oops">CURD Admin</div>
|
<div class="bullshit__oops">Pure Admin</div>
|
||||||
<div class="bullshit__headline">{{ message }}</div>
|
<div class="bullshit__headline">{{ message }}</div>
|
||||||
<div class="bullshit__info">
|
<div class="bullshit__info">
|
||||||
Please check that the URL you entered is correct, or click the button
|
Please check that the URL you entered is correct, or click the button
|
||||||
@ -20,26 +30,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
|
||||||
import { computed } from "vue";
|
|
||||||
import four from "/@/assets/404.png";
|
|
||||||
import four_cloud from "/@/assets/404_cloud.png";
|
|
||||||
export default {
|
|
||||||
name: "404",
|
|
||||||
setup() {
|
|
||||||
const message = computed(() => {
|
|
||||||
return "The webmaster said that you can not enter this page...";
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
message,
|
|
||||||
four,
|
|
||||||
four_cloud
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.wscn-http404-container {
|
.wscn-http404-container {
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
|
@ -1,3 +1,61 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, unref, onMounted } from "vue";
|
||||||
|
import LogicFlow from "@logicflow/core";
|
||||||
|
import { Snapshot, BpmnElement, Menu } from "@logicflow/extension";
|
||||||
|
import "@logicflow/core/dist/style/index.css";
|
||||||
|
import "@logicflow/extension/lib/style/index.css";
|
||||||
|
import { Control, NodePanel, DataDialog } from "/@/components/ReFlowChart";
|
||||||
|
import { toLogicflowData } from "/@/components/ReFlowChart/src/adpterForTurbo";
|
||||||
|
import { BpmnNode } from "/@/components/ReFlowChart/src/config";
|
||||||
|
import demoData from "./dataTurbo.json";
|
||||||
|
|
||||||
|
let lf = ref(null);
|
||||||
|
let graphData = ref(null);
|
||||||
|
let dataVisible = ref<boolean>(false);
|
||||||
|
let config = ref({
|
||||||
|
grid: true,
|
||||||
|
background: {
|
||||||
|
color: "#f7f9ff"
|
||||||
|
},
|
||||||
|
keyboard: {
|
||||||
|
enabled: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let nodeList = BpmnNode;
|
||||||
|
|
||||||
|
function initLf() {
|
||||||
|
// 画布配置
|
||||||
|
LogicFlow.use(Snapshot);
|
||||||
|
// 使用bpmn插件,引入bpmn元素,这些元素可以在turbo中转换后使用
|
||||||
|
LogicFlow.use(BpmnElement);
|
||||||
|
// 启动右键菜单
|
||||||
|
LogicFlow.use(Menu);
|
||||||
|
const domLf = new LogicFlow({
|
||||||
|
...unref(config),
|
||||||
|
container: document.querySelector("#LF-Turbo")
|
||||||
|
});
|
||||||
|
lf.value = domLf;
|
||||||
|
// 设置边类型bpmn:sequenceFlow为默认类型
|
||||||
|
unref(lf).setDefaultEdgeType("bpmn:sequenceFlow");
|
||||||
|
onRender();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onRender() {
|
||||||
|
// Turbo数据转换为LogicFlow内部识别的数据结构
|
||||||
|
const lFData = toLogicflowData(demoData);
|
||||||
|
lf.value.render(lFData);
|
||||||
|
}
|
||||||
|
|
||||||
|
function catData() {
|
||||||
|
graphData.value = unref(lf).getGraphData();
|
||||||
|
dataVisible.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
initLf();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="logic-flow-view">
|
<div class="logic-flow-view">
|
||||||
<!-- 辅助工具栏 -->
|
<!-- 辅助工具栏 -->
|
||||||
@ -19,80 +77,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { ref, unref, onMounted } from "vue";
|
|
||||||
import LogicFlow from "@logicflow/core";
|
|
||||||
import { Snapshot, BpmnElement, Menu } from "@logicflow/extension";
|
|
||||||
import "@logicflow/core/dist/style/index.css";
|
|
||||||
import "@logicflow/extension/lib/style/index.css";
|
|
||||||
import { Control, NodePanel, DataDialog } from "/@/components/ReFlowChart";
|
|
||||||
|
|
||||||
import { toLogicflowData } from "/@/components/ReFlowChart/src/adpterForTurbo";
|
|
||||||
import { BpmnNode } from "/@/components/ReFlowChart/src/config";
|
|
||||||
import demoData from "./dataTurbo.json";
|
|
||||||
export default {
|
|
||||||
name: "reFlowChart",
|
|
||||||
components: { NodePanel, Control, DataDialog },
|
|
||||||
setup() {
|
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
let lf = ref<ElRef>(null);
|
|
||||||
let graphData = ref(null);
|
|
||||||
let dataVisible = ref(false);
|
|
||||||
let config = ref({
|
|
||||||
grid: true,
|
|
||||||
background: {
|
|
||||||
color: "#f7f9ff"
|
|
||||||
},
|
|
||||||
keyboard: {
|
|
||||||
enabled: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
let nodeList = BpmnNode;
|
|
||||||
|
|
||||||
function initLf() {
|
|
||||||
// 画布配置
|
|
||||||
LogicFlow.use(Snapshot);
|
|
||||||
// 使用bpmn插件,引入bpmn元素,这些元素可以在turbo中转换后使用
|
|
||||||
LogicFlow.use(BpmnElement);
|
|
||||||
// 启动右键菜单
|
|
||||||
LogicFlow.use(Menu);
|
|
||||||
const domLf = new LogicFlow({
|
|
||||||
...unref(config),
|
|
||||||
container: document.querySelector("#LF-Turbo")
|
|
||||||
});
|
|
||||||
lf.value = domLf;
|
|
||||||
// 设置边类型bpmn:sequenceFlow为默认类型
|
|
||||||
unref(lf).setDefaultEdgeType("bpmn:sequenceFlow");
|
|
||||||
onRender();
|
|
||||||
}
|
|
||||||
|
|
||||||
function onRender() {
|
|
||||||
// Turbo数据转换为LogicFlow内部识别的数据结构
|
|
||||||
const lFData = toLogicflowData(demoData);
|
|
||||||
lf.value.render(lFData);
|
|
||||||
}
|
|
||||||
|
|
||||||
function catData() {
|
|
||||||
graphData.value = unref(lf).getGraphData();
|
|
||||||
dataVisible.value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
initLf();
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
lf,
|
|
||||||
graphData,
|
|
||||||
dataVisible,
|
|
||||||
config,
|
|
||||||
nodeList,
|
|
||||||
catData
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
#LF-Turbo {
|
#LF-Turbo {
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
|
@ -1,3 +1,57 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive, onBeforeMount } from "vue";
|
||||||
|
import info, { ContextProps } from "../components/ReInfo/index.vue";
|
||||||
|
import { getVerify, getLogin } from "/@/api/user";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { storageSession } from "/@/utils/storage";
|
||||||
|
import { warnMessage, successMessage } from "/@/utils/message";
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
// 刷新验证码
|
||||||
|
const refreshGetVerify = async () => {
|
||||||
|
let { svg } = await getVerify();
|
||||||
|
contextInfo.svg = svg;
|
||||||
|
};
|
||||||
|
|
||||||
|
const contextInfo: ContextProps = reactive({
|
||||||
|
userName: "",
|
||||||
|
passWord: "",
|
||||||
|
verify: null,
|
||||||
|
svg: null
|
||||||
|
});
|
||||||
|
|
||||||
|
const toPage = (info: Object): void => {
|
||||||
|
storageSession.setItem("info", info);
|
||||||
|
router.push("/");
|
||||||
|
};
|
||||||
|
|
||||||
|
// 登录
|
||||||
|
const onLogin = async () => {
|
||||||
|
let { userName, passWord, verify } = contextInfo;
|
||||||
|
let { code, info, accessToken } = await getLogin({
|
||||||
|
username: userName,
|
||||||
|
password: passWord,
|
||||||
|
verify: verify
|
||||||
|
});
|
||||||
|
code === 0
|
||||||
|
? successMessage(info) &&
|
||||||
|
toPage({
|
||||||
|
username: userName,
|
||||||
|
accessToken
|
||||||
|
})
|
||||||
|
: warnMessage(info);
|
||||||
|
};
|
||||||
|
|
||||||
|
const refreshVerify = (): void => {
|
||||||
|
refreshGetVerify();
|
||||||
|
};
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
// refreshGetVerify();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="login">
|
<div class="login">
|
||||||
<info
|
<info
|
||||||
@ -7,72 +61,3 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { reactive, onBeforeMount } from "vue";
|
|
||||||
import info, { ContextProps } from "../components/ReInfo/index.vue";
|
|
||||||
import { getVerify, getLogin } from "/@/api/user";
|
|
||||||
import { useRouter } from "vue-router";
|
|
||||||
import { storageSession } from "/@/utils/storage";
|
|
||||||
import { warnMessage, successMessage } from "/@/utils/message";
|
|
||||||
export default {
|
|
||||||
name: "login",
|
|
||||||
components: {
|
|
||||||
info
|
|
||||||
},
|
|
||||||
setup() {
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
// 刷新验证码
|
|
||||||
const refreshGetVerify = async () => {
|
|
||||||
let { svg } = await getVerify();
|
|
||||||
contextInfo.svg = svg;
|
|
||||||
};
|
|
||||||
|
|
||||||
const contextInfo: ContextProps = reactive({
|
|
||||||
userName: "",
|
|
||||||
passWord: "",
|
|
||||||
verify: null,
|
|
||||||
svg: null
|
|
||||||
});
|
|
||||||
|
|
||||||
const toPage = (info: Object): void => {
|
|
||||||
storageSession.setItem("info", info);
|
|
||||||
router.push("/");
|
|
||||||
};
|
|
||||||
|
|
||||||
// 登录
|
|
||||||
const onLogin = async () => {
|
|
||||||
let { userName, passWord, verify } = contextInfo;
|
|
||||||
let { code, info, accessToken } = await getLogin({
|
|
||||||
username: userName,
|
|
||||||
password: passWord,
|
|
||||||
verify: verify
|
|
||||||
});
|
|
||||||
code === 0
|
|
||||||
? successMessage(info) &&
|
|
||||||
toPage({
|
|
||||||
username: userName,
|
|
||||||
accessToken
|
|
||||||
})
|
|
||||||
: warnMessage(info);
|
|
||||||
};
|
|
||||||
|
|
||||||
const refreshVerify = (): void => {
|
|
||||||
refreshGetVerify();
|
|
||||||
};
|
|
||||||
|
|
||||||
onBeforeMount(() => {
|
|
||||||
// refreshGetVerify();
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
contextInfo,
|
|
||||||
onLogin,
|
|
||||||
router,
|
|
||||||
toPage,
|
|
||||||
refreshVerify
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
@ -1,3 +1,18 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue";
|
||||||
|
import { storageSession } from "/@/utils/storage";
|
||||||
|
|
||||||
|
const auth = ref<Boolean>(storageSession.getItem("info").username || "admin");
|
||||||
|
|
||||||
|
function changRole(value) {
|
||||||
|
storageSession.setItem("info", {
|
||||||
|
username: value,
|
||||||
|
accessToken: `eyJhbGciOiJIUzUxMiJ9.${value}`
|
||||||
|
});
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<el-radio-group v-model="auth" @change="changRole">
|
<el-radio-group v-model="auth" @change="changRole">
|
||||||
@ -8,30 +23,3 @@
|
|||||||
<p v-auth="'v-test'">只有test可看</p>
|
<p v-auth="'v-test'">只有test可看</p>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { ref } from "vue";
|
|
||||||
import { storageSession } from "/@/utils/storage";
|
|
||||||
export default {
|
|
||||||
name: "permissionButton",
|
|
||||||
setup() {
|
|
||||||
const auth = ref(storageSession.getItem("info").username || "admin");
|
|
||||||
|
|
||||||
function changRole(value) {
|
|
||||||
storageSession.setItem("info", {
|
|
||||||
username: value,
|
|
||||||
accessToken: `eyJhbGciOiJIUzUxMiJ9.${value}`
|
|
||||||
});
|
|
||||||
|
|
||||||
window.location.reload();
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
auth,
|
|
||||||
changRole
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
||||||
|
@ -1,3 +1,26 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, unref } from "vue";
|
||||||
|
import { storageSession } from "/@/utils/storage";
|
||||||
|
|
||||||
|
let purview = ref<string>(storageSession.getItem("info").username);
|
||||||
|
|
||||||
|
function changRole() {
|
||||||
|
if (unref(purview) === "admin") {
|
||||||
|
storageSession.setItem("info", {
|
||||||
|
username: "test",
|
||||||
|
accessToken: "eyJhbGciOiJIUzUxMiJ9.test"
|
||||||
|
});
|
||||||
|
window.location.reload();
|
||||||
|
} else {
|
||||||
|
storageSession.setItem("info", {
|
||||||
|
username: "admin",
|
||||||
|
accessToken: "eyJhbGciOiJIUzUxMiJ9.admin"
|
||||||
|
});
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<h4>
|
<h4>
|
||||||
@ -10,35 +33,3 @@
|
|||||||
<el-button type="primary" @click="changRole">切换角色</el-button>
|
<el-button type="primary" @click="changRole">切换角色</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { ref, unref } from "vue";
|
|
||||||
import { storageSession } from "/@/utils/storage";
|
|
||||||
export default {
|
|
||||||
name: "permissionPage",
|
|
||||||
setup() {
|
|
||||||
let purview: string = ref(storageSession.getItem("info").username);
|
|
||||||
|
|
||||||
function changRole() {
|
|
||||||
if (unref(purview) === "admin") {
|
|
||||||
storageSession.setItem("info", {
|
|
||||||
username: "test",
|
|
||||||
accessToken: "eyJhbGciOiJIUzUxMiJ9.test"
|
|
||||||
});
|
|
||||||
window.location.reload();
|
|
||||||
} else {
|
|
||||||
storageSession.setItem("info", {
|
|
||||||
username: "admin",
|
|
||||||
accessToken: "eyJhbGciOiJIUzUxMiJ9.admin"
|
|
||||||
});
|
|
||||||
window.location.reload();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
purview,
|
|
||||||
changRole
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
@ -1,26 +1,20 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { unref } from "vue";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
|
||||||
|
const { currentRoute, replace } = useRouter();
|
||||||
|
|
||||||
|
const { params, query } = unref(currentRoute);
|
||||||
|
const { path } = params;
|
||||||
|
|
||||||
|
const _path = Array.isArray(path) ? path.join("/") : path;
|
||||||
|
|
||||||
|
replace({
|
||||||
|
path: "/" + _path,
|
||||||
|
query
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div></div>
|
<div></div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
|
||||||
import { defineComponent, unref } from "vue";
|
|
||||||
import { useRouter } from "vue-router";
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: "redirect",
|
|
||||||
setup() {
|
|
||||||
const { currentRoute, replace } = useRouter();
|
|
||||||
|
|
||||||
const { params, query } = unref(currentRoute);
|
|
||||||
const { path } = params;
|
|
||||||
|
|
||||||
const _path = Array.isArray(path) ? path.join("/") : path;
|
|
||||||
|
|
||||||
replace({
|
|
||||||
path: "/" + _path,
|
|
||||||
query
|
|
||||||
});
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
@ -1,3 +1,47 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive, onBeforeMount } from "vue";
|
||||||
|
import info, { ContextProps } from "../components/ReInfo/index.vue";
|
||||||
|
import { getRegist, getVerify } from "/@/api/user";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { warnMessage, successMessage } from "/@/utils/message";
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
// 刷新验证码
|
||||||
|
const refreshGetVerify = async () => {
|
||||||
|
let { svg } = await getVerify();
|
||||||
|
contextInfo.svg = svg;
|
||||||
|
};
|
||||||
|
|
||||||
|
const contextInfo: ContextProps = reactive({
|
||||||
|
userName: "",
|
||||||
|
passWord: "",
|
||||||
|
verify: null,
|
||||||
|
svg: null
|
||||||
|
});
|
||||||
|
|
||||||
|
// 注册
|
||||||
|
const onRegist = async () => {
|
||||||
|
let { userName, passWord, verify } = contextInfo;
|
||||||
|
let { code, info } = await getRegist({
|
||||||
|
username: userName,
|
||||||
|
password: passWord,
|
||||||
|
verify: verify
|
||||||
|
});
|
||||||
|
code === 0
|
||||||
|
? successMessage(info) && router.push("/login")
|
||||||
|
: warnMessage(info);
|
||||||
|
};
|
||||||
|
|
||||||
|
const refreshVerify = (): void => {
|
||||||
|
refreshGetVerify();
|
||||||
|
};
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
// refreshGetVerify();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="register">
|
<div class="register">
|
||||||
<info
|
<info
|
||||||
@ -7,61 +51,3 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { reactive, onBeforeMount } from "vue";
|
|
||||||
import info, { ContextProps } from "../components/ReInfo/index.vue";
|
|
||||||
import { getRegist, getVerify } from "/@/api/user";
|
|
||||||
import { useRouter } from "vue-router";
|
|
||||||
import { warnMessage, successMessage } from "/@/utils/message";
|
|
||||||
export default {
|
|
||||||
name: "register",
|
|
||||||
components: {
|
|
||||||
info
|
|
||||||
},
|
|
||||||
setup() {
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
// 刷新验证码
|
|
||||||
const refreshGetVerify = async () => {
|
|
||||||
let { svg } = await getVerify();
|
|
||||||
contextInfo.svg = svg;
|
|
||||||
};
|
|
||||||
|
|
||||||
const contextInfo: ContextProps = reactive({
|
|
||||||
userName: "",
|
|
||||||
passWord: "",
|
|
||||||
verify: null,
|
|
||||||
svg: null
|
|
||||||
});
|
|
||||||
|
|
||||||
// 注册
|
|
||||||
const onRegist = async () => {
|
|
||||||
let { userName, passWord, verify } = contextInfo;
|
|
||||||
let { code, info } = await getRegist({
|
|
||||||
username: userName,
|
|
||||||
password: passWord,
|
|
||||||
verify: verify
|
|
||||||
});
|
|
||||||
code === 0
|
|
||||||
? successMessage(info) && router.push("/login")
|
|
||||||
: warnMessage(info);
|
|
||||||
};
|
|
||||||
|
|
||||||
const refreshVerify = (): void => {
|
|
||||||
refreshGetVerify();
|
|
||||||
};
|
|
||||||
|
|
||||||
onBeforeMount(() => {
|
|
||||||
// refreshGetVerify();
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
contextInfo,
|
|
||||||
onRegist,
|
|
||||||
router,
|
|
||||||
refreshVerify
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
@ -1,3 +1,79 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive } from "vue";
|
||||||
|
import { VxeTableEvents } from "vxe-table";
|
||||||
|
import { templateRef } from "@vueuse/core";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
drawer: boolean;
|
||||||
|
drawTitle?: string;
|
||||||
|
direction?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
withDefaults(defineProps<Props>(), {
|
||||||
|
drawer: false,
|
||||||
|
drawTitle: "",
|
||||||
|
direction: "rtl"
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: "handleClose"): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const xTable = templateRef<any>("xTable", null);
|
||||||
|
|
||||||
|
const configData = reactive({
|
||||||
|
tableData: [
|
||||||
|
{
|
||||||
|
name: "禁用",
|
||||||
|
dataval: "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "启用",
|
||||||
|
dataval: "1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
isAllChecked: false,
|
||||||
|
isIndeterminate: false,
|
||||||
|
selectRecords: [] as any[],
|
||||||
|
tablePage: {
|
||||||
|
total: 0,
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 10
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 抽屉关闭
|
||||||
|
function handleClose() {
|
||||||
|
configData.isAllChecked = false;
|
||||||
|
configData.isIndeterminate = false;
|
||||||
|
emit("handleClose");
|
||||||
|
}
|
||||||
|
|
||||||
|
function editConfig(row) {
|
||||||
|
console.log("editConfig", row);
|
||||||
|
}
|
||||||
|
|
||||||
|
function delConfig(row) {
|
||||||
|
console.log("delConfig", row);
|
||||||
|
}
|
||||||
|
|
||||||
|
const changeAllEvent = () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
console.log(xTable);
|
||||||
|
}, 1000);
|
||||||
|
const $table = xTable.value;
|
||||||
|
$table.setAllCheckboxRow(configData.isAllChecked);
|
||||||
|
configData.selectRecords = $table.getCheckboxRecords();
|
||||||
|
};
|
||||||
|
|
||||||
|
const checkboxChangeEvent: VxeTableEvents.CheckboxChange = ({ records }) => {
|
||||||
|
const $table = xTable.value;
|
||||||
|
configData.isAllChecked = $table.isAllCheckboxChecked();
|
||||||
|
configData.isIndeterminate = $table.isCheckboxIndeterminate();
|
||||||
|
configData.selectRecords = records;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="config">
|
<div class="config">
|
||||||
<el-drawer
|
<el-drawer
|
||||||
@ -14,7 +90,7 @@
|
|||||||
<vxe-table
|
<vxe-table
|
||||||
ref="xTable"
|
ref="xTable"
|
||||||
border
|
border
|
||||||
:data="tableData"
|
:data="configData.tableData"
|
||||||
@checkbox-change="checkboxChangeEvent"
|
@checkbox-change="checkboxChangeEvent"
|
||||||
@checkbox-all="checkboxChangeEvent"
|
@checkbox-all="checkboxChangeEvent"
|
||||||
>
|
>
|
||||||
@ -40,9 +116,9 @@
|
|||||||
</vxe-table>
|
</vxe-table>
|
||||||
<vxe-pager
|
<vxe-pager
|
||||||
perfect
|
perfect
|
||||||
v-model:current-page="tablePage.currentPage"
|
v-model:current-page="configData.tablePage.currentPage"
|
||||||
v-model:page-size="tablePage.pageSize"
|
v-model:page-size="configData.tablePage.pageSize"
|
||||||
:total="tablePage.total"
|
:total="configData.tablePage.total"
|
||||||
:layouts="[
|
:layouts="[
|
||||||
'PrevJump',
|
'PrevJump',
|
||||||
'PrevPage',
|
'PrevPage',
|
||||||
@ -57,12 +133,12 @@
|
|||||||
<template #left>
|
<template #left>
|
||||||
<span class="page-left">
|
<span class="page-left">
|
||||||
<vxe-checkbox
|
<vxe-checkbox
|
||||||
v-model="isAllChecked"
|
v-model="configData.isAllChecked"
|
||||||
:indeterminate="isIndeterminate"
|
:indeterminate="configData.isIndeterminate"
|
||||||
@change="changeAllEvent"
|
@change="changeAllEvent"
|
||||||
></vxe-checkbox>
|
></vxe-checkbox>
|
||||||
<span class="select-count"
|
<span class="select-count"
|
||||||
>已选中{{ selectRecords.length }}条</span
|
>已选中{{ configData.selectRecords.length }}条</span
|
||||||
>
|
>
|
||||||
<vxe-button size="small">{{ $t("message.hsdelete") }}</vxe-button>
|
<vxe-button size="small">{{ $t("message.hsdelete") }}</vxe-button>
|
||||||
</span>
|
</span>
|
||||||
@ -73,98 +149,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { defineComponent, reactive, toRefs } from "vue";
|
|
||||||
import { propTypes } from "/@/utils/propTypes";
|
|
||||||
import { VxeTableEvents } from "vxe-table";
|
|
||||||
import { templateRef } from "@vueuse/core";
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
props: {
|
|
||||||
drawer: propTypes.bool.def(false),
|
|
||||||
drawTitle: propTypes.string.def(""),
|
|
||||||
direction: propTypes.string.def("rtl")
|
|
||||||
},
|
|
||||||
emits: ["handleClose"],
|
|
||||||
setup(props, ctx) {
|
|
||||||
const { emit } = ctx;
|
|
||||||
|
|
||||||
const xTable = templateRef<any>("xTable", null);
|
|
||||||
|
|
||||||
const configData = reactive({
|
|
||||||
tableData: [
|
|
||||||
{
|
|
||||||
name: "禁用",
|
|
||||||
dataval: "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "启用",
|
|
||||||
dataval: "1"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
isAllChecked: false,
|
|
||||||
isIndeterminate: false,
|
|
||||||
selectRecords: [] as any[],
|
|
||||||
tablePage: {
|
|
||||||
total: 0,
|
|
||||||
currentPage: 1,
|
|
||||||
pageSize: 10
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 抽屉关闭
|
|
||||||
function handleClose() {
|
|
||||||
configData.isAllChecked = false;
|
|
||||||
configData.isIndeterminate = false;
|
|
||||||
emit("handleClose");
|
|
||||||
}
|
|
||||||
|
|
||||||
function editConfig(row) {
|
|
||||||
console.log(
|
|
||||||
"%crow===>>>: ",
|
|
||||||
"color: MidnightBlue; background: Aquamarine; font-size: 20px;",
|
|
||||||
row
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function delConfig(row) {
|
|
||||||
console.log(
|
|
||||||
"%crow===>>>: ",
|
|
||||||
"color: MidnightBlue; background: Aquamarine; font-size: 20px;",
|
|
||||||
row
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const changeAllEvent = () => {
|
|
||||||
setTimeout(() => {
|
|
||||||
console.log(xTable);
|
|
||||||
}, 1000);
|
|
||||||
const $table = xTable.value;
|
|
||||||
$table.setAllCheckboxRow(configData.isAllChecked);
|
|
||||||
configData.selectRecords = $table.getCheckboxRecords();
|
|
||||||
};
|
|
||||||
|
|
||||||
const checkboxChangeEvent: VxeTableEvents.CheckboxChange = ({
|
|
||||||
records
|
|
||||||
}) => {
|
|
||||||
const $table = xTable.value;
|
|
||||||
configData.isAllChecked = $table.isAllCheckboxChecked();
|
|
||||||
configData.isIndeterminate = $table.isCheckboxIndeterminate();
|
|
||||||
configData.selectRecords = records;
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
...toRefs(configData),
|
|
||||||
handleClose,
|
|
||||||
editConfig,
|
|
||||||
delConfig,
|
|
||||||
changeAllEvent,
|
|
||||||
checkboxChangeEvent
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.list {
|
.list {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
@ -1,10 +1,208 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import Config from "./config.vue";
|
||||||
|
import { reactive, ref, unref, nextTick } from "vue";
|
||||||
|
import XEUtils from "xe-utils";
|
||||||
|
import { cloneDeep } from "lodash-es";
|
||||||
|
import { templateRef } from "@vueuse/core";
|
||||||
|
import { useCopyToClipboard } from "/@/utils/useCopyToClipboard";
|
||||||
|
import {
|
||||||
|
VXETable,
|
||||||
|
VxeTableInstance,
|
||||||
|
VxeTableEvents,
|
||||||
|
VxeFormPropTypes
|
||||||
|
} from "vxe-table";
|
||||||
|
type onEditNRow = {
|
||||||
|
name: string;
|
||||||
|
model: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const dictData = reactive({
|
||||||
|
submitLoading: false,
|
||||||
|
showEdit: false,
|
||||||
|
selectRow: null,
|
||||||
|
filterName: "",
|
||||||
|
tableData: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "状态",
|
||||||
|
model: "",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: "1-1",
|
||||||
|
name: "服务状态",
|
||||||
|
model: "serviceStatus"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "1-2",
|
||||||
|
name: "在线状态",
|
||||||
|
model: "onlienStatus"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ id: 2, name: "操作系统", model: "operatingSystem" }
|
||||||
|
],
|
||||||
|
formData: {
|
||||||
|
name: "",
|
||||||
|
model: ""
|
||||||
|
},
|
||||||
|
formItems: [
|
||||||
|
{
|
||||||
|
field: "name",
|
||||||
|
title: "字典名称",
|
||||||
|
span: 24,
|
||||||
|
itemRender: {
|
||||||
|
name: "$input",
|
||||||
|
props: { placeholder: "请输入字典名称" }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: "model",
|
||||||
|
title: "字典类型",
|
||||||
|
span: 24,
|
||||||
|
itemRender: {
|
||||||
|
name: "$input",
|
||||||
|
props: {
|
||||||
|
placeholder: "请输入字典类型",
|
||||||
|
//这里vxe-table文档并没有提到,可以配置所选组件的所有属性,比如这里可以配置关于vxe-input的所有属性
|
||||||
|
disabled: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: "right",
|
||||||
|
span: 24,
|
||||||
|
itemRender: {
|
||||||
|
name: "$buttons",
|
||||||
|
children: [
|
||||||
|
{ props: { type: "submit", content: "提交", status: "primary" } },
|
||||||
|
{ props: { type: "reset", content: "重置" } }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
] as VxeFormPropTypes.Items
|
||||||
|
});
|
||||||
|
|
||||||
|
let originData = cloneDeep(dictData.tableData);
|
||||||
|
|
||||||
|
const xTree = templateRef<HTMLElement | any>("xTree", null);
|
||||||
|
|
||||||
|
const handleSearch = () => {
|
||||||
|
const filterName = XEUtils.toValueString(dictData.filterName).trim();
|
||||||
|
|
||||||
|
if (filterName) {
|
||||||
|
const options = { children: "children" };
|
||||||
|
const searchProps = ["name"];
|
||||||
|
|
||||||
|
dictData.tableData = XEUtils.searchTree(
|
||||||
|
originData,
|
||||||
|
item =>
|
||||||
|
searchProps.some(
|
||||||
|
key => XEUtils.toValueString(item[key]).indexOf(filterName) > -1
|
||||||
|
),
|
||||||
|
options
|
||||||
|
);
|
||||||
|
|
||||||
|
// 搜索之后默认展开所有子节点
|
||||||
|
nextTick(() => {
|
||||||
|
const $table = xTree.value;
|
||||||
|
$table.setAllTreeExpand(true);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
dictData.tableData = originData;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 创建一个防防抖函数,调用频率间隔 100 毫秒
|
||||||
|
const searchEvent = XEUtils.debounce(
|
||||||
|
function () {
|
||||||
|
handleSearch();
|
||||||
|
},
|
||||||
|
100,
|
||||||
|
{ leading: false, trailing: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
const confirmEvent = async () => {
|
||||||
|
const type = await VXETable.modal.confirm("您确定要删除吗?");
|
||||||
|
(await type) === "confirm" &&
|
||||||
|
VXETable.modal.message({
|
||||||
|
content: "测试数据,不可删除",
|
||||||
|
status: "error"
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function commonFn(value, disabled) {
|
||||||
|
dictData.selectRow = value;
|
||||||
|
dictData.showEdit = true;
|
||||||
|
dictData.formItems[1].itemRender.props.disabled = disabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增
|
||||||
|
function onAdd() {
|
||||||
|
commonFn(null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增子类型
|
||||||
|
function onAddChild(row?: object) {
|
||||||
|
console.log("onAddChild", row);
|
||||||
|
commonFn(null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑
|
||||||
|
function onEdit(row?: onEditNRow) {
|
||||||
|
dictData.formData = {
|
||||||
|
name: row.name,
|
||||||
|
model: row.model ? row.model : "暂无字典类型"
|
||||||
|
};
|
||||||
|
commonFn(row, true);
|
||||||
|
// VXETable.modal.message({
|
||||||
|
// content: "测试数据,不可编辑",
|
||||||
|
// status: "error"
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 拷贝当前列表项的数据(字典类型)
|
||||||
|
const { clipboardRef } = useCopyToClipboard();
|
||||||
|
const cellDBLClickEvent: VxeTableEvents.CellDblclick = ({ row }) => {
|
||||||
|
clipboardRef.value = unref(row).model;
|
||||||
|
};
|
||||||
|
|
||||||
|
const xTable = ref({} as VxeTableInstance);
|
||||||
|
|
||||||
|
const submitEvent = () => {
|
||||||
|
dictData.submitLoading = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
const $table = xTable.value;
|
||||||
|
dictData.submitLoading = false;
|
||||||
|
dictData.showEdit = false;
|
||||||
|
if (dictData.selectRow) {
|
||||||
|
VXETable.modal.message({ content: "保存成功", status: "success" });
|
||||||
|
Object.assign(dictData.selectRow, dictData.formData);
|
||||||
|
} else {
|
||||||
|
VXETable.modal.message({ content: "新增成功", status: "success" });
|
||||||
|
$table.insert(dictData.formData);
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
};
|
||||||
|
|
||||||
|
let drawer = ref(false);
|
||||||
|
|
||||||
|
function onDeploy(value?: object) {
|
||||||
|
console.log("onDeploy", value);
|
||||||
|
drawer.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleClose() {
|
||||||
|
drawer.value = false;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="dict-container">
|
<div class="dict-container">
|
||||||
<!-- 工具栏 -->
|
<!-- 工具栏 -->
|
||||||
<vxe-toolbar>
|
<vxe-toolbar>
|
||||||
<template #buttons>
|
<template #buttons>
|
||||||
<vxe-input
|
<vxe-input
|
||||||
v-model="filterName"
|
v-model="dictData.filterName"
|
||||||
:placeholder="$t('message.hssearch')"
|
:placeholder="$t('message.hssearch')"
|
||||||
@keyup="searchEvent"
|
@keyup="searchEvent"
|
||||||
></vxe-input>
|
></vxe-input>
|
||||||
@ -41,7 +239,7 @@
|
|||||||
iconOpen: 'fa fa-minus-square-o',
|
iconOpen: 'fa fa-minus-square-o',
|
||||||
iconClose: 'fa fa-plus-square-o'
|
iconClose: 'fa fa-plus-square-o'
|
||||||
}"
|
}"
|
||||||
:data="tableData"
|
:data="dictData.tableData"
|
||||||
@cell-dblclick="cellDBLClickEvent"
|
@cell-dblclick="cellDBLClickEvent"
|
||||||
>
|
>
|
||||||
<vxe-table-column
|
<vxe-table-column
|
||||||
@ -89,16 +287,16 @@
|
|||||||
<vxe-modal
|
<vxe-modal
|
||||||
resize
|
resize
|
||||||
width="450"
|
width="450"
|
||||||
v-model="showEdit"
|
v-model="dictData.showEdit"
|
||||||
:title="selectRow ? '编辑' : '新增'"
|
:title="dictData.selectRow ? '编辑' : '新增'"
|
||||||
:loading="submitLoading"
|
:loading="dictData.submitLoading"
|
||||||
@hide="$refs.xForm.reset()"
|
@hide="$refs.xForm.reset()"
|
||||||
>
|
>
|
||||||
<template #default>
|
<template #default>
|
||||||
<vxe-form
|
<vxe-form
|
||||||
ref="xForm"
|
ref="xForm"
|
||||||
:data="formData"
|
:data="dictData.formData"
|
||||||
:items="formItems"
|
:items="dictData.formItems"
|
||||||
title-align="right"
|
title-align="right"
|
||||||
title-width="100"
|
title-width="100"
|
||||||
@submit="submitEvent"
|
@submit="submitEvent"
|
||||||
@ -109,229 +307,7 @@
|
|||||||
<Config :drawer="drawer" drawTitle="字典列表" @handleClose="handleClose" />
|
<Config :drawer="drawer" drawTitle="字典列表" @handleClose="handleClose" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
|
||||||
import { reactive, ref, unref, nextTick, toRefs } from "vue";
|
|
||||||
import XEUtils from "xe-utils";
|
|
||||||
import { cloneDeep } from "lodash-es";
|
|
||||||
import { templateRef } from "@vueuse/core";
|
|
||||||
import { useCopyToClipboard } from "/@/utils/useCopyToClipboard";
|
|
||||||
import {
|
|
||||||
VXETable,
|
|
||||||
VxeTableInstance,
|
|
||||||
VxeTableEvents,
|
|
||||||
VxeFormPropTypes
|
|
||||||
} from "vxe-table";
|
|
||||||
import Config from "./config.vue";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "dict",
|
|
||||||
components: {
|
|
||||||
Config
|
|
||||||
},
|
|
||||||
setup() {
|
|
||||||
const dictData = reactive({
|
|
||||||
submitLoading: false,
|
|
||||||
showEdit: false,
|
|
||||||
selectRow: null,
|
|
||||||
filterName: "",
|
|
||||||
tableData: [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: "状态",
|
|
||||||
model: "",
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
id: "1-1",
|
|
||||||
name: "服务状态",
|
|
||||||
model: "serviceStatus"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "1-2",
|
|
||||||
name: "在线状态",
|
|
||||||
model: "onlienStatus"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{ id: 2, name: "操作系统", model: "operatingSystem" }
|
|
||||||
],
|
|
||||||
formData: {
|
|
||||||
name: "",
|
|
||||||
model: ""
|
|
||||||
},
|
|
||||||
formItems: [
|
|
||||||
{
|
|
||||||
field: "name",
|
|
||||||
title: "字典名称",
|
|
||||||
span: 24,
|
|
||||||
itemRender: {
|
|
||||||
name: "$input",
|
|
||||||
props: { placeholder: "请输入字典名称" }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: "model",
|
|
||||||
title: "字典类型",
|
|
||||||
span: 24,
|
|
||||||
itemRender: {
|
|
||||||
name: "$input",
|
|
||||||
props: {
|
|
||||||
placeholder: "请输入字典类型",
|
|
||||||
//这里vxe-table文档并没有提到,可以配置所选组件的所有属性,比如这里可以配置关于vxe-input的所有属性
|
|
||||||
disabled: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
align: "right",
|
|
||||||
span: 24,
|
|
||||||
itemRender: {
|
|
||||||
name: "$buttons",
|
|
||||||
children: [
|
|
||||||
{ props: { type: "submit", content: "提交", status: "primary" } },
|
|
||||||
{ props: { type: "reset", content: "重置" } }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
] as VxeFormPropTypes.Items
|
|
||||||
});
|
|
||||||
|
|
||||||
let originData = cloneDeep(dictData.tableData);
|
|
||||||
|
|
||||||
const xTree = templateRef<HTMLElement | any>("xTree", null);
|
|
||||||
|
|
||||||
const formatDate = (value: any) => {
|
|
||||||
return XEUtils.toDateString(value, "yyyy-MM-dd HH:mm:ss.S");
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSearch = () => {
|
|
||||||
const filterName = XEUtils.toValueString(dictData.filterName).trim();
|
|
||||||
|
|
||||||
if (filterName) {
|
|
||||||
const options = { children: "children" };
|
|
||||||
const searchProps = ["name"];
|
|
||||||
|
|
||||||
dictData.tableData = XEUtils.searchTree(
|
|
||||||
originData,
|
|
||||||
item =>
|
|
||||||
searchProps.some(
|
|
||||||
key => XEUtils.toValueString(item[key]).indexOf(filterName) > -1
|
|
||||||
),
|
|
||||||
options
|
|
||||||
);
|
|
||||||
|
|
||||||
// 搜索之后默认展开所有子节点
|
|
||||||
nextTick(() => {
|
|
||||||
const $table = xTree.value;
|
|
||||||
$table.setAllTreeExpand(true);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
dictData.tableData = originData;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 创建一个防防抖函数,调用频率间隔 100 毫秒
|
|
||||||
const searchEvent = XEUtils.debounce(
|
|
||||||
function () {
|
|
||||||
handleSearch();
|
|
||||||
},
|
|
||||||
100,
|
|
||||||
{ leading: false, trailing: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
const confirmEvent = async () => {
|
|
||||||
const type = await VXETable.modal.confirm("您确定要删除吗?");
|
|
||||||
(await type) === "confirm" &&
|
|
||||||
VXETable.modal.message({
|
|
||||||
content: "测试数据,不可删除",
|
|
||||||
status: "error"
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
function commonFn(value, disabled) {
|
|
||||||
dictData.selectRow = value;
|
|
||||||
dictData.showEdit = true;
|
|
||||||
dictData.formItems[1].itemRender.props.disabled = disabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 新增
|
|
||||||
function onAdd() {
|
|
||||||
commonFn(null, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 新增子类型
|
|
||||||
function onAddChild(row: any) {
|
|
||||||
console.log(
|
|
||||||
"%crow===>>>: ",
|
|
||||||
"color: MidnightBlue; background: Aquamarine; font-size: 20px;",
|
|
||||||
row
|
|
||||||
);
|
|
||||||
commonFn(null, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 编辑
|
|
||||||
function onEdit(row: any) {
|
|
||||||
dictData.formData = {
|
|
||||||
name: row.name,
|
|
||||||
model: row.model ? row.model : "暂无字典类型"
|
|
||||||
};
|
|
||||||
commonFn(row, true);
|
|
||||||
// VXETable.modal.message({
|
|
||||||
// content: "测试数据,不可编辑",
|
|
||||||
// status: "error"
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
|
|
||||||
// 拷贝当前列表项的数据(字典类型)
|
|
||||||
const { clipboardRef } = useCopyToClipboard();
|
|
||||||
const cellDBLClickEvent: VxeTableEvents.CellDblclick = ({ row }) => {
|
|
||||||
clipboardRef.value = unref(row).model;
|
|
||||||
};
|
|
||||||
|
|
||||||
const xTable = ref({} as VxeTableInstance);
|
|
||||||
|
|
||||||
const submitEvent = () => {
|
|
||||||
dictData.submitLoading = true;
|
|
||||||
setTimeout(() => {
|
|
||||||
const $table = xTable.value;
|
|
||||||
dictData.submitLoading = false;
|
|
||||||
dictData.showEdit = false;
|
|
||||||
if (dictData.selectRow) {
|
|
||||||
VXETable.modal.message({ content: "保存成功", status: "success" });
|
|
||||||
Object.assign(dictData.selectRow, dictData.formData);
|
|
||||||
} else {
|
|
||||||
VXETable.modal.message({ content: "新增成功", status: "success" });
|
|
||||||
$table.insert(dictData.formData);
|
|
||||||
}
|
|
||||||
}, 500);
|
|
||||||
};
|
|
||||||
|
|
||||||
let drawer = ref(false);
|
|
||||||
|
|
||||||
function onDeploy() {
|
|
||||||
drawer.value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleClose() {
|
|
||||||
drawer.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
...toRefs(dictData),
|
|
||||||
formatDate,
|
|
||||||
searchEvent,
|
|
||||||
confirmEvent,
|
|
||||||
cellDBLClickEvent,
|
|
||||||
submitEvent,
|
|
||||||
onEdit,
|
|
||||||
onAddChild,
|
|
||||||
onAdd,
|
|
||||||
onDeploy,
|
|
||||||
drawer,
|
|
||||||
handleClose
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.dict-container {
|
.dict-container {
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
|
@ -1,252 +1,242 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive } from "vue";
|
||||||
|
import { VxeGridProps } from "vxe-table";
|
||||||
|
|
||||||
|
const gridOptions = reactive({
|
||||||
|
border: true,
|
||||||
|
resizable: true,
|
||||||
|
keepSource: true,
|
||||||
|
height: 500,
|
||||||
|
printConfig: {},
|
||||||
|
importConfig: {},
|
||||||
|
exportConfig: {},
|
||||||
|
pagerConfig: {
|
||||||
|
perfect: true,
|
||||||
|
pageSize: 15
|
||||||
|
},
|
||||||
|
editConfig: {
|
||||||
|
trigger: "click",
|
||||||
|
mode: "row",
|
||||||
|
showStatus: true
|
||||||
|
},
|
||||||
|
toolbarConfig: {
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
code: "insert_actived",
|
||||||
|
name: "message.hsadd",
|
||||||
|
status: "perfect",
|
||||||
|
icon: "fa fa-plus"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: "mark_cancel",
|
||||||
|
name: "message.hsmark",
|
||||||
|
status: "perfect",
|
||||||
|
icon: "fa fa-trash-o"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: "save",
|
||||||
|
name: "message.hssave",
|
||||||
|
status: "perfect",
|
||||||
|
icon: "fa fa-save"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
perfect: true,
|
||||||
|
refresh: {
|
||||||
|
icon: "fa fa-refresh",
|
||||||
|
iconLoading: "fa fa-spinner fa-spin"
|
||||||
|
},
|
||||||
|
import: {
|
||||||
|
icon: "fa fa-upload"
|
||||||
|
},
|
||||||
|
export: {
|
||||||
|
icon: "fa fa-download"
|
||||||
|
},
|
||||||
|
print: {
|
||||||
|
icon: "fa fa-print"
|
||||||
|
},
|
||||||
|
zoom: {
|
||||||
|
iconIn: "fa fa-arrows-alt",
|
||||||
|
iconOut: "fa fa-expand"
|
||||||
|
},
|
||||||
|
custom: {
|
||||||
|
icon: "fa fa-cog"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
proxyConfig: {
|
||||||
|
props: {
|
||||||
|
result: "result",
|
||||||
|
total: "page.total"
|
||||||
|
},
|
||||||
|
ajax: {
|
||||||
|
// 接收 Promise
|
||||||
|
query: ({ page }) => {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
setTimeout(() => {
|
||||||
|
const list = [
|
||||||
|
{
|
||||||
|
id: 10001,
|
||||||
|
name: "Test1",
|
||||||
|
nickname: "T1",
|
||||||
|
role: "Develop",
|
||||||
|
sex: "Man",
|
||||||
|
age: 28,
|
||||||
|
address: "Shenzhen"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 10002,
|
||||||
|
name: "Test2",
|
||||||
|
nickname: "T2",
|
||||||
|
role: "Test",
|
||||||
|
sex: "Women",
|
||||||
|
age: 22,
|
||||||
|
address: "Guangzhou"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 10003,
|
||||||
|
name: "Test3",
|
||||||
|
nickname: "T3",
|
||||||
|
role: "PM",
|
||||||
|
sex: "Man",
|
||||||
|
age: 32,
|
||||||
|
address: "Shanghai"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 10004,
|
||||||
|
name: "Test4",
|
||||||
|
nickname: "T4",
|
||||||
|
role: "Designer",
|
||||||
|
sex: "Women ",
|
||||||
|
age: 23,
|
||||||
|
address: "Shenzhen"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 10005,
|
||||||
|
name: "Test5",
|
||||||
|
nickname: "T5",
|
||||||
|
role: "Develop",
|
||||||
|
sex: "Women ",
|
||||||
|
age: 30,
|
||||||
|
address: "Shanghai"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 10006,
|
||||||
|
name: "Test6",
|
||||||
|
nickname: "T6",
|
||||||
|
role: "Designer",
|
||||||
|
sex: "Women ",
|
||||||
|
age: 21,
|
||||||
|
address: "Shenzhen"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 10007,
|
||||||
|
name: "Test7",
|
||||||
|
nickname: "T7",
|
||||||
|
role: "Test",
|
||||||
|
sex: "Man ",
|
||||||
|
age: 29,
|
||||||
|
address: "vxe-table 从入门到放弃"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 10008,
|
||||||
|
name: "Test8",
|
||||||
|
nickname: "T8",
|
||||||
|
role: "Develop",
|
||||||
|
sex: "Man ",
|
||||||
|
age: 35,
|
||||||
|
address: "Shenzhen"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 10009,
|
||||||
|
name: "Test9",
|
||||||
|
nickname: "T9",
|
||||||
|
role: "Develop",
|
||||||
|
sex: "Man ",
|
||||||
|
age: 35,
|
||||||
|
address: "Shenzhen"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 100010,
|
||||||
|
name: "Test10",
|
||||||
|
nickname: "T10",
|
||||||
|
role: "Develop",
|
||||||
|
sex: "Man ",
|
||||||
|
age: 35,
|
||||||
|
address: "Guangzhou"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 100011,
|
||||||
|
name: "Test11",
|
||||||
|
nickname: "T11",
|
||||||
|
role: "Test",
|
||||||
|
sex: "Women ",
|
||||||
|
age: 26,
|
||||||
|
address: "vxe-table 从入门到放弃"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 100012,
|
||||||
|
name: "Test12",
|
||||||
|
nickname: "T12",
|
||||||
|
role: "Develop",
|
||||||
|
sex: "Man ",
|
||||||
|
age: 34,
|
||||||
|
address: "Guangzhou"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 100013,
|
||||||
|
name: "Test13",
|
||||||
|
nickname: "T13",
|
||||||
|
role: "Test",
|
||||||
|
sex: "Women ",
|
||||||
|
age: 22,
|
||||||
|
address: "Shenzhen"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
resolve({
|
||||||
|
page: {
|
||||||
|
total: list.length
|
||||||
|
},
|
||||||
|
result: list.slice(
|
||||||
|
(page.currentPage - 1) * page.pageSize,
|
||||||
|
page.currentPage * page.pageSize
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// body 对象: { removeRecords }
|
||||||
|
delete: () => {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
setTimeout(() => {
|
||||||
|
resolve({});
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// body 对象: { insertRecords, updateRecords, removeRecords, pendingRecords }
|
||||||
|
save: () => {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
setTimeout(() => {
|
||||||
|
resolve({});
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
columns: [
|
||||||
|
{ type: "checkbox", width: 50 },
|
||||||
|
{ type: "seq", width: 60 },
|
||||||
|
{ field: "name", title: "Name", editRender: { name: "input" } },
|
||||||
|
{ field: "nickname", title: "Nickname", editRender: { name: "input" } },
|
||||||
|
{ field: "role", title: "Role", editRender: { name: "input" } },
|
||||||
|
{
|
||||||
|
field: "address",
|
||||||
|
title: "Address",
|
||||||
|
showOverflow: true,
|
||||||
|
editRender: { name: "input" }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
} as VxeGridProps);
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<vxe-grid v-bind="gridOptions" style="width: 98%"></vxe-grid>
|
<vxe-grid v-bind="gridOptions" style="width: 98%"></vxe-grid>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { reactive } from "vue";
|
|
||||||
import { VxeGridProps } from "vxe-table";
|
|
||||||
export default {
|
|
||||||
name: "user",
|
|
||||||
setup() {
|
|
||||||
const gridOptions = reactive({
|
|
||||||
border: true,
|
|
||||||
resizable: true,
|
|
||||||
keepSource: true,
|
|
||||||
height: 500,
|
|
||||||
printConfig: {},
|
|
||||||
importConfig: {},
|
|
||||||
exportConfig: {},
|
|
||||||
pagerConfig: {
|
|
||||||
perfect: true,
|
|
||||||
pageSize: 15
|
|
||||||
},
|
|
||||||
editConfig: {
|
|
||||||
trigger: "click",
|
|
||||||
mode: "row",
|
|
||||||
showStatus: true
|
|
||||||
},
|
|
||||||
toolbarConfig: {
|
|
||||||
buttons: [
|
|
||||||
{
|
|
||||||
code: "insert_actived",
|
|
||||||
name: "message.hsadd",
|
|
||||||
status: "perfect",
|
|
||||||
icon: "fa fa-plus"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: "mark_cancel",
|
|
||||||
name: "message.hsmark",
|
|
||||||
status: "perfect",
|
|
||||||
icon: "fa fa-trash-o"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: "save",
|
|
||||||
name: "message.hssave",
|
|
||||||
status: "perfect",
|
|
||||||
icon: "fa fa-save"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
perfect: true,
|
|
||||||
refresh: {
|
|
||||||
icon: "fa fa-refresh",
|
|
||||||
iconLoading: "fa fa-spinner fa-spin"
|
|
||||||
},
|
|
||||||
import: {
|
|
||||||
icon: "fa fa-upload"
|
|
||||||
},
|
|
||||||
export: {
|
|
||||||
icon: "fa fa-download"
|
|
||||||
},
|
|
||||||
print: {
|
|
||||||
icon: "fa fa-print"
|
|
||||||
},
|
|
||||||
zoom: {
|
|
||||||
iconIn: "fa fa-arrows-alt",
|
|
||||||
iconOut: "fa fa-expand"
|
|
||||||
},
|
|
||||||
custom: {
|
|
||||||
icon: "fa fa-cog"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
proxyConfig: {
|
|
||||||
props: {
|
|
||||||
result: "result",
|
|
||||||
total: "page.total"
|
|
||||||
},
|
|
||||||
ajax: {
|
|
||||||
// 接收 Promise
|
|
||||||
query: ({ page }) => {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
setTimeout(() => {
|
|
||||||
const list = [
|
|
||||||
{
|
|
||||||
id: 10001,
|
|
||||||
name: "Test1",
|
|
||||||
nickname: "T1",
|
|
||||||
role: "Develop",
|
|
||||||
sex: "Man",
|
|
||||||
age: 28,
|
|
||||||
address: "Shenzhen"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 10002,
|
|
||||||
name: "Test2",
|
|
||||||
nickname: "T2",
|
|
||||||
role: "Test",
|
|
||||||
sex: "Women",
|
|
||||||
age: 22,
|
|
||||||
address: "Guangzhou"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 10003,
|
|
||||||
name: "Test3",
|
|
||||||
nickname: "T3",
|
|
||||||
role: "PM",
|
|
||||||
sex: "Man",
|
|
||||||
age: 32,
|
|
||||||
address: "Shanghai"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 10004,
|
|
||||||
name: "Test4",
|
|
||||||
nickname: "T4",
|
|
||||||
role: "Designer",
|
|
||||||
sex: "Women ",
|
|
||||||
age: 23,
|
|
||||||
address: "Shenzhen"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 10005,
|
|
||||||
name: "Test5",
|
|
||||||
nickname: "T5",
|
|
||||||
role: "Develop",
|
|
||||||
sex: "Women ",
|
|
||||||
age: 30,
|
|
||||||
address: "Shanghai"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 10006,
|
|
||||||
name: "Test6",
|
|
||||||
nickname: "T6",
|
|
||||||
role: "Designer",
|
|
||||||
sex: "Women ",
|
|
||||||
age: 21,
|
|
||||||
address: "Shenzhen"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 10007,
|
|
||||||
name: "Test7",
|
|
||||||
nickname: "T7",
|
|
||||||
role: "Test",
|
|
||||||
sex: "Man ",
|
|
||||||
age: 29,
|
|
||||||
address: "vxe-table 从入门到放弃"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 10008,
|
|
||||||
name: "Test8",
|
|
||||||
nickname: "T8",
|
|
||||||
role: "Develop",
|
|
||||||
sex: "Man ",
|
|
||||||
age: 35,
|
|
||||||
address: "Shenzhen"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 10009,
|
|
||||||
name: "Test9",
|
|
||||||
nickname: "T9",
|
|
||||||
role: "Develop",
|
|
||||||
sex: "Man ",
|
|
||||||
age: 35,
|
|
||||||
address: "Shenzhen"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 100010,
|
|
||||||
name: "Test10",
|
|
||||||
nickname: "T10",
|
|
||||||
role: "Develop",
|
|
||||||
sex: "Man ",
|
|
||||||
age: 35,
|
|
||||||
address: "Guangzhou"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 100011,
|
|
||||||
name: "Test11",
|
|
||||||
nickname: "T11",
|
|
||||||
role: "Test",
|
|
||||||
sex: "Women ",
|
|
||||||
age: 26,
|
|
||||||
address: "vxe-table 从入门到放弃"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 100012,
|
|
||||||
name: "Test12",
|
|
||||||
nickname: "T12",
|
|
||||||
role: "Develop",
|
|
||||||
sex: "Man ",
|
|
||||||
age: 34,
|
|
||||||
address: "Guangzhou"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 100013,
|
|
||||||
name: "Test13",
|
|
||||||
nickname: "T13",
|
|
||||||
role: "Test",
|
|
||||||
sex: "Women ",
|
|
||||||
age: 22,
|
|
||||||
address: "Shenzhen"
|
|
||||||
}
|
|
||||||
];
|
|
||||||
resolve({
|
|
||||||
page: {
|
|
||||||
total: list.length
|
|
||||||
},
|
|
||||||
result: list.slice(
|
|
||||||
(page.currentPage - 1) * page.pageSize,
|
|
||||||
page.currentPage * page.pageSize
|
|
||||||
)
|
|
||||||
});
|
|
||||||
}, 100);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
// body 对象: { removeRecords }
|
|
||||||
delete: () => {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
setTimeout(() => {
|
|
||||||
resolve({});
|
|
||||||
}, 100);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
// body 对象: { insertRecords, updateRecords, removeRecords, pendingRecords }
|
|
||||||
save: () => {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
setTimeout(() => {
|
|
||||||
resolve({});
|
|
||||||
}, 100);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
columns: [
|
|
||||||
{ type: "checkbox", width: 50 },
|
|
||||||
{ type: "seq", width: 60 },
|
|
||||||
{ field: "name", title: "Name", editRender: { name: "input" } },
|
|
||||||
{ field: "nickname", title: "Nickname", editRender: { name: "input" } },
|
|
||||||
{ field: "role", title: "Role", editRender: { name: "input" } },
|
|
||||||
{
|
|
||||||
field: "address",
|
|
||||||
title: "Address",
|
|
||||||
showOverflow: true,
|
|
||||||
editRender: { name: "input" }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
} as VxeGridProps);
|
|
||||||
|
|
||||||
return {
|
|
||||||
gridOptions
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
||||||
|
@ -1,3 +1,170 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import Flop from "/@/components/ReFlop";
|
||||||
|
import { ref, computed, onMounted, nextTick } from "vue";
|
||||||
|
import { deviceDetection } from "/@/utils/deviceDetection";
|
||||||
|
import { useEventListener, tryOnUnmounted, useTimeoutFn } from "@vueuse/core";
|
||||||
|
import { echartsJson } from "/@/api/mock";
|
||||||
|
import echarts from "/@/plugins/echarts";
|
||||||
|
import { ECharts } from "echarts";
|
||||||
|
|
||||||
|
//折线图实例
|
||||||
|
let brokenLine: ECharts;
|
||||||
|
let mobile = ref<boolean>(deviceDetection());
|
||||||
|
let date: Date = new Date();
|
||||||
|
let loading = ref<boolean>(true);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
loading.value = !loading.value;
|
||||||
|
nextTick(() => {
|
||||||
|
initbrokenLine();
|
||||||
|
});
|
||||||
|
}, 500);
|
||||||
|
|
||||||
|
let greetings = computed(() => {
|
||||||
|
if (date.getHours() >= 0 && date.getHours() < 12) {
|
||||||
|
return "上午阳光明媚,祝你薪水翻倍🌞!";
|
||||||
|
} else if (date.getHours() >= 12 && date.getHours() < 18) {
|
||||||
|
return "下午小风娇好,愿你青春不老😃!";
|
||||||
|
} else {
|
||||||
|
return "折一根天使羽毛,愿拂去您的疲惫烦恼忧伤🌛!";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function initbrokenLine() {
|
||||||
|
const lineRefDom = document.getElementById("brokenLine");
|
||||||
|
if (!lineRefDom) return;
|
||||||
|
// @ts-ignore
|
||||||
|
brokenLine = echarts.init(lineRefDom);
|
||||||
|
brokenLine.clear(); //清除旧画布 重新渲染
|
||||||
|
|
||||||
|
echartsJson().then(({ info }) => {
|
||||||
|
brokenLine.setOption({
|
||||||
|
title: {
|
||||||
|
text: "上海 空气质量指数",
|
||||||
|
left: "1%"
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: "axis"
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: "5%",
|
||||||
|
right: "15%",
|
||||||
|
bottom: "10%"
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
data: info.map(function (item) {
|
||||||
|
return item[0];
|
||||||
|
})
|
||||||
|
},
|
||||||
|
yAxis: {},
|
||||||
|
toolbox: {
|
||||||
|
right: 10,
|
||||||
|
feature: {
|
||||||
|
saveAsImage: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dataZoom: [
|
||||||
|
{
|
||||||
|
startValue: "2014-06-01"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "inside"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
visualMap: {
|
||||||
|
top: 50,
|
||||||
|
right: 10,
|
||||||
|
pieces: [
|
||||||
|
{
|
||||||
|
gt: 0,
|
||||||
|
lte: 50,
|
||||||
|
color: "#93CE07"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
gt: 50,
|
||||||
|
lte: 100,
|
||||||
|
color: "#FBDB0F"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
gt: 100,
|
||||||
|
lte: 150,
|
||||||
|
color: "#FC7D02"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
gt: 150,
|
||||||
|
lte: 200,
|
||||||
|
color: "#FD0100"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
gt: 200,
|
||||||
|
lte: 300,
|
||||||
|
color: "#AA069F"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
gt: 300,
|
||||||
|
color: "#AC3B2A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
outOfRange: {
|
||||||
|
color: "#999"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
series: {
|
||||||
|
name: "上海 空气质量指数",
|
||||||
|
type: "line",
|
||||||
|
data: info.map(function (item) {
|
||||||
|
return item[1];
|
||||||
|
}),
|
||||||
|
markLine: {
|
||||||
|
silent: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: "#333"
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
yAxis: 50
|
||||||
|
},
|
||||||
|
{
|
||||||
|
yAxis: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
yAxis: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
yAxis: 200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
yAxis: 300
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const openDepot = (): void => {
|
||||||
|
window.open("https://github.com/xiaoxian521/vue-pure-admin");
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
nextTick(() => {
|
||||||
|
useEventListener("resize", () => {
|
||||||
|
if (!brokenLine) return;
|
||||||
|
useTimeoutFn(() => {
|
||||||
|
brokenLine.resize();
|
||||||
|
}, 180);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
tryOnUnmounted(() => {
|
||||||
|
if (!brokenLine) return;
|
||||||
|
brokenLine.dispose();
|
||||||
|
brokenLine = null;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="welcome">
|
<div class="welcome">
|
||||||
<el-affix>
|
<el-affix>
|
||||||
@ -26,185 +193,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import Flop from "/@/components/ReFlop";
|
|
||||||
import { ref, computed, onMounted, nextTick } from "vue";
|
|
||||||
import { deviceDetection } from "/@/utils/deviceDetection";
|
|
||||||
import { useEventListener, tryOnUnmounted, useTimeoutFn } from "@vueuse/core";
|
|
||||||
import { echartsJson } from "/@/api/mock";
|
|
||||||
import echarts from "/@/plugins/echarts";
|
|
||||||
|
|
||||||
let brokenLine: any = null; //折线图实例
|
|
||||||
export default {
|
|
||||||
name: "welcome",
|
|
||||||
components: {
|
|
||||||
Flop
|
|
||||||
},
|
|
||||||
setup() {
|
|
||||||
let mobile = ref(deviceDetection());
|
|
||||||
let date: Date = new Date();
|
|
||||||
let loading = ref(true);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
loading.value = !loading.value;
|
|
||||||
nextTick(() => {
|
|
||||||
initbrokenLine();
|
|
||||||
});
|
|
||||||
}, 500);
|
|
||||||
|
|
||||||
let greetings = computed(() => {
|
|
||||||
if (date.getHours() >= 0 && date.getHours() < 12) {
|
|
||||||
return "上午阳光明媚,祝你薪水翻倍🌞!";
|
|
||||||
} else if (date.getHours() >= 12 && date.getHours() < 18) {
|
|
||||||
return "下午小风娇好,愿你青春不老😃!";
|
|
||||||
} else {
|
|
||||||
return "折一根天使羽毛,愿拂去您的疲惫烦恼忧伤🌛!";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function initbrokenLine() {
|
|
||||||
const lineRefDom = document.getElementById("brokenLine");
|
|
||||||
if (!lineRefDom) return;
|
|
||||||
brokenLine = echarts.init(lineRefDom);
|
|
||||||
brokenLine.clear(); //清除旧画布 重新渲染
|
|
||||||
|
|
||||||
echartsJson().then(({ info }) => {
|
|
||||||
brokenLine.setOption({
|
|
||||||
title: {
|
|
||||||
text: "上海 空气质量指数",
|
|
||||||
left: "1%"
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
trigger: "axis"
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
left: "5%",
|
|
||||||
right: "15%",
|
|
||||||
bottom: "10%"
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
data: info.map(function (item) {
|
|
||||||
return item[0];
|
|
||||||
})
|
|
||||||
},
|
|
||||||
yAxis: {},
|
|
||||||
toolbox: {
|
|
||||||
right: 10,
|
|
||||||
feature: {
|
|
||||||
saveAsImage: {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dataZoom: [
|
|
||||||
{
|
|
||||||
startValue: "2014-06-01"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "inside"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
visualMap: {
|
|
||||||
top: 50,
|
|
||||||
right: 10,
|
|
||||||
pieces: [
|
|
||||||
{
|
|
||||||
gt: 0,
|
|
||||||
lte: 50,
|
|
||||||
color: "#93CE07"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
gt: 50,
|
|
||||||
lte: 100,
|
|
||||||
color: "#FBDB0F"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
gt: 100,
|
|
||||||
lte: 150,
|
|
||||||
color: "#FC7D02"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
gt: 150,
|
|
||||||
lte: 200,
|
|
||||||
color: "#FD0100"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
gt: 200,
|
|
||||||
lte: 300,
|
|
||||||
color: "#AA069F"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
gt: 300,
|
|
||||||
color: "#AC3B2A"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
outOfRange: {
|
|
||||||
color: "#999"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
series: {
|
|
||||||
name: "上海 空气质量指数",
|
|
||||||
type: "line",
|
|
||||||
data: info.map(function (item) {
|
|
||||||
return item[1];
|
|
||||||
}),
|
|
||||||
markLine: {
|
|
||||||
silent: true,
|
|
||||||
lineStyle: {
|
|
||||||
color: "#333"
|
|
||||||
},
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
yAxis: 50
|
|
||||||
},
|
|
||||||
{
|
|
||||||
yAxis: 100
|
|
||||||
},
|
|
||||||
{
|
|
||||||
yAxis: 150
|
|
||||||
},
|
|
||||||
{
|
|
||||||
yAxis: 200
|
|
||||||
},
|
|
||||||
{
|
|
||||||
yAxis: 300
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const openDepot = (): void => {
|
|
||||||
window.open("https://github.com/xiaoxian521/vue-pure-admin");
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
nextTick(() => {
|
|
||||||
useEventListener("resize", () => {
|
|
||||||
if (!brokenLine) return;
|
|
||||||
useTimeoutFn(() => {
|
|
||||||
brokenLine.resize();
|
|
||||||
}, 180);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
tryOnUnmounted(() => {
|
|
||||||
if (!brokenLine) return;
|
|
||||||
brokenLine.dispose();
|
|
||||||
brokenLine = null;
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
greetings,
|
|
||||||
mobile,
|
|
||||||
loading,
|
|
||||||
openDepot
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.welcome {
|
.welcome {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -2,11 +2,12 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "esnext",
|
"target": "esnext",
|
||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
|
"moduleResolution": "node",
|
||||||
"strict": false,
|
"strict": false,
|
||||||
"jsx": "preserve",
|
"jsx": "preserve",
|
||||||
"importHelpers": true,
|
"importHelpers": true,
|
||||||
"moduleResolution": "node",
|
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
|
"strictFunctionTypes": false,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
@ -16,27 +17,14 @@
|
|||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"allowJs": false,
|
"allowJs": false,
|
||||||
"resolveJsonModule": true, // 包含导入的模块。json的扩展
|
"resolveJsonModule": true, // 包含导入的模块。json的扩展
|
||||||
"lib": [
|
"lib": ["dom", "esnext"],
|
||||||
"dom",
|
|
||||||
"esnext"
|
|
||||||
],
|
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
"paths": {
|
"paths": {
|
||||||
"/@/*": [
|
"/@/*": ["src/*"],
|
||||||
"src/*"
|
"/#/*": ["types/*"]
|
||||||
],
|
|
||||||
"/#/*": [
|
|
||||||
"types/*"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"types": [
|
"types": ["node", "vite/client"],
|
||||||
"node",
|
"typeRoots": ["./node_modules/@types/", "./types"]
|
||||||
"vite/client"
|
|
||||||
],
|
|
||||||
"typeRoots": [
|
|
||||||
"./node_modules/@types/",
|
|
||||||
"./types"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"src/**/*.ts",
|
"src/**/*.ts",
|
||||||
@ -46,9 +34,5 @@
|
|||||||
"mock/*.ts",
|
"mock/*.ts",
|
||||||
"vite.config.ts"
|
"vite.config.ts"
|
||||||
],
|
],
|
||||||
"exclude": [
|
"exclude": ["node_modules", "dist", "**/*.js"]
|
||||||
"node_modules",
|
}
|
||||||
"dist",
|
|
||||||
"**/*.js"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
49
types/global.d.ts
vendored
49
types/global.d.ts
vendored
@ -16,53 +16,54 @@ declare global {
|
|||||||
};
|
};
|
||||||
lastBuildTime: string;
|
lastBuildTime: string;
|
||||||
};
|
};
|
||||||
declare interface Window {
|
interface Window {
|
||||||
// Global vue app instance
|
// Global vue app instance
|
||||||
__APP__: App<Element>;
|
__APP__: App<Element>;
|
||||||
webkitCancelAnimationFrame: (id?: any) => any;
|
webkitCancelAnimationFrame: (handle: number) => void;
|
||||||
webkitRequestAnimationFrame: (id?: any) => any;
|
mozCancelAnimationFrame: (handle: number) => void;
|
||||||
mozCancelAnimationFrame: (id?: any) => any;
|
oCancelAnimationFrame: (handle: number) => void;
|
||||||
oCancelAnimationFrame: (id?: any) => any;
|
msCancelAnimationFrame: (handle: number) => void;
|
||||||
msCancelAnimationFrame: (id?: any) => any;
|
|
||||||
mozRequestAnimationFrame: (id?: any) => any;
|
webkitRequestAnimationFrame: (callback: FrameRequestCallback) => number;
|
||||||
oRequestAnimationFrame: (id?: any) => any;
|
mozRequestAnimationFrame: (callback: FrameRequestCallback) => number;
|
||||||
msRequestAnimationFrame: (id?: any) => any;
|
oRequestAnimationFrame: (callback: FrameRequestCallback) => number;
|
||||||
|
msRequestAnimationFrame: (callback: FrameRequestCallback) => number;
|
||||||
}
|
}
|
||||||
|
|
||||||
// vue
|
// vue
|
||||||
declare type PropType<T> = VuePropType<T>;
|
type PropType<T> = VuePropType<T>;
|
||||||
|
|
||||||
export type Writable<T> = {
|
type Writable<T> = {
|
||||||
-readonly [P in keyof T]: T[P];
|
-readonly [P in keyof T]: T[P];
|
||||||
};
|
};
|
||||||
|
|
||||||
declare type Nullable<T> = T | null;
|
type Nullable<T> = T | null;
|
||||||
declare type NonNullable<T> = T extends null | undefined ? never : T;
|
type NonNullable<T> = T extends null | undefined ? never : T;
|
||||||
declare type Recordable<T = any> = Record<string, T>;
|
type Recordable<T = any> = Record<string, T>;
|
||||||
declare type ReadonlyRecordable<T = any> = {
|
type ReadonlyRecordable<T = any> = {
|
||||||
readonly [key: string]: T;
|
readonly [key: string]: T;
|
||||||
};
|
};
|
||||||
declare type Indexable<T = any> = {
|
type Indexable<T = any> = {
|
||||||
[key: string]: T;
|
[key: string]: T;
|
||||||
};
|
};
|
||||||
declare type DeepPartial<T> = {
|
type DeepPartial<T> = {
|
||||||
[P in keyof T]?: DeepPartial<T[P]>;
|
[P in keyof T]?: DeepPartial<T[P]>;
|
||||||
};
|
};
|
||||||
declare type TimeoutHandle = ReturnType<typeof setTimeout>;
|
type TimeoutHandle = ReturnType<typeof setTimeout>;
|
||||||
declare type IntervalHandle = ReturnType<typeof setInterval>;
|
type IntervalHandle = ReturnType<typeof setInterval>;
|
||||||
|
|
||||||
declare interface ChangeEvent extends Event {
|
interface ChangeEvent extends Event {
|
||||||
target: HTMLInputElement;
|
target: HTMLInputElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare interface WheelEvent {
|
interface WheelEvent {
|
||||||
path?: EventTarget[];
|
path?: EventTarget[];
|
||||||
}
|
}
|
||||||
interface ImportMetaEnv extends ViteEnv {
|
interface ImportMetaEnv extends ViteEnv {
|
||||||
__: unknown;
|
__: unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare interface ViteEnv {
|
interface ViteEnv {
|
||||||
VITE_PORT: number;
|
VITE_PORT: number;
|
||||||
VITE_USE_MOCK: boolean;
|
VITE_USE_MOCK: boolean;
|
||||||
VITE_USE_PWA: boolean;
|
VITE_USE_PWA: boolean;
|
||||||
@ -79,9 +80,9 @@ declare global {
|
|||||||
VITE_GENERATE_UI: string;
|
VITE_GENERATE_UI: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare function parseInt(s: string | number, radix?: number): number;
|
function parseInt(s: string | number, radix?: number): number;
|
||||||
|
|
||||||
declare function parseFloat(string: string | number): number;
|
function parseFloat(string: string | number): number;
|
||||||
|
|
||||||
namespace JSX {
|
namespace JSX {
|
||||||
// tslint:disable no-empty-interface
|
// tslint:disable no-empty-interface
|
||||||
|
4
types/index.d.ts
vendored
4
types/index.d.ts
vendored
@ -25,3 +25,7 @@ declare type ComponentRef<T extends HTMLElement = HTMLDivElement> =
|
|||||||
ComponentElRef<T> | null;
|
ComponentElRef<T> | null;
|
||||||
|
|
||||||
declare type ElRef<T extends HTMLElement = HTMLDivElement> = Nullable<T>;
|
declare type ElRef<T extends HTMLElement = HTMLDivElement> = Nullable<T>;
|
||||||
|
|
||||||
|
declare type ForDataType<T> = {
|
||||||
|
[P in T]?: ForDataType<T[P]>;
|
||||||
|
};
|
||||||
|
29
yarn.lock
29
yarn.lock
@ -794,7 +794,7 @@
|
|||||||
"@vue/compiler-core" "3.2.11"
|
"@vue/compiler-core" "3.2.11"
|
||||||
"@vue/shared" "3.2.11"
|
"@vue/shared" "3.2.11"
|
||||||
|
|
||||||
"@vue/compiler-sfc@^3.0.11", "@vue/compiler-sfc@^3.2.11":
|
"@vue/compiler-sfc@3.2.11", "@vue/compiler-sfc@^3.0.11":
|
||||||
version "3.2.11"
|
version "3.2.11"
|
||||||
resolved "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.11.tgz#628fa12238760d9b9b339ac2e125a759224fadbf"
|
resolved "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.11.tgz#628fa12238760d9b9b339ac2e125a759224fadbf"
|
||||||
integrity sha512-cUIaS8mgJrQ6yucj2AupWAwBRITK3W/a8wCOn9g5fJGtOl8h4APY8vN3lzP8HIJDyEeRF3I8SfRhL+oX97kSnw==
|
integrity sha512-cUIaS8mgJrQ6yucj2AupWAwBRITK3W/a8wCOn9g5fJGtOl8h4APY8vN3lzP8HIJDyEeRF3I8SfRhL+oX97kSnw==
|
||||||
@ -885,12 +885,12 @@
|
|||||||
resolved "https://registry.npmjs.org/@vue/shared/-/shared-3.2.11.tgz#01899f54949caf1ac241de397bd17069632574de"
|
resolved "https://registry.npmjs.org/@vue/shared/-/shared-3.2.11.tgz#01899f54949caf1ac241de397bd17069632574de"
|
||||||
integrity sha512-ovfXAsSsCvV9JVceWjkqC/7OF5HbgLOtCWjCIosmPGG8lxbPuavhIxRH1dTx4Dg9xLgRTNLvI3pVxG4ItQZekg==
|
integrity sha512-ovfXAsSsCvV9JVceWjkqC/7OF5HbgLOtCWjCIosmPGG8lxbPuavhIxRH1dTx4Dg9xLgRTNLvI3pVxG4ItQZekg==
|
||||||
|
|
||||||
"@vueuse/core@^6.0.0":
|
"@vueuse/core@^6.4.1":
|
||||||
version "6.3.3"
|
version "6.4.1"
|
||||||
resolved "https://registry.npmjs.org/@vueuse/core/-/core-6.3.3.tgz#0682c01b50d28e91d3d76f27278600ee1692fa24"
|
resolved "https://registry.npmjs.org/@vueuse/core/-/core-6.4.1.tgz#21416997a23bfb4924a5082ed6fa959027f80d04"
|
||||||
integrity sha512-qa/0WYqcvqFKQmlkgsLGlXBrYcQeUi3fzHMIaxsD/lO/zm0IWBSN8CTFu91LwER5qNYs4DGhU5pu7jOdrTzAIQ==
|
integrity sha512-FRFeEPVq77gcMZP0mCloJY+lyHJaUQmUMaPp5fBds3fs/BbkAt7HTMMizFKHWDVjbmA20vBOjmC9tTnfD+DdEA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vueuse/shared" "6.3.3"
|
"@vueuse/shared" "6.4.1"
|
||||||
vue-demi "*"
|
vue-demi "*"
|
||||||
|
|
||||||
"@vueuse/core@~6.1.0":
|
"@vueuse/core@~6.1.0":
|
||||||
@ -908,10 +908,10 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
vue-demi "*"
|
vue-demi "*"
|
||||||
|
|
||||||
"@vueuse/shared@6.3.3":
|
"@vueuse/shared@6.4.1":
|
||||||
version "6.3.3"
|
version "6.4.1"
|
||||||
resolved "https://registry.npmjs.org/@vueuse/shared/-/shared-6.3.3.tgz#4e5c600ad1ed5bf2a8630ad0bd38edb1f4269f37"
|
resolved "https://registry.npmjs.org/@vueuse/shared/-/shared-6.4.1.tgz#5bc84be107cead84e11c21d2c57b1e9f2c376975"
|
||||||
integrity sha512-2+YPRhFNUXEhhvKNTWBtNU6hGkft9+mfYSVjI4hZu2U8KDbNNKF/215lBPzMYI2twScDtPsAssQ+vu5t9PBy0g==
|
integrity sha512-zsaYxxZwACQbMmGg+UBjPUVemi325sDdnnB0mn+PNizE0fVC57B+vbLgdj45NBmr6P4nw6a0Y2rMupebwDWsdw==
|
||||||
dependencies:
|
dependencies:
|
||||||
vue-demi "*"
|
vue-demi "*"
|
||||||
|
|
||||||
@ -3865,6 +3865,11 @@ snake-case@^3.0.4:
|
|||||||
dot-case "^3.0.4"
|
dot-case "^3.0.4"
|
||||||
tslib "^2.0.3"
|
tslib "^2.0.3"
|
||||||
|
|
||||||
|
sortablejs@1.13.0:
|
||||||
|
version "1.13.0"
|
||||||
|
resolved "https://registry.npmjs.org/sortablejs/-/sortablejs-1.13.0.tgz#3ab2473f8c69ca63569e80b1cd1b5669b51269e9"
|
||||||
|
integrity sha512-RBJirPY0spWCrU5yCmWM1eFs/XgX2J5c6b275/YyxFRgnzPhKl/TDeU2hNR8Dt7ITq66NRPM4UlOt+e5O4CFHg==
|
||||||
|
|
||||||
sortablejs@1.14.0:
|
sortablejs@1.14.0:
|
||||||
version "1.14.0"
|
version "1.14.0"
|
||||||
resolved "https://registry.npmjs.org/sortablejs/-/sortablejs-1.14.0.tgz#6d2e17ccbdb25f464734df621d4f35d4ab35b3d8"
|
resolved "https://registry.npmjs.org/sortablejs/-/sortablejs-1.14.0.tgz#6d2e17ccbdb25f464734df621d4f35d4ab35b3d8"
|
||||||
@ -4493,14 +4498,14 @@ vue-router@^4.0.11:
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@vue/devtools-api" "^6.0.0-beta.14"
|
"@vue/devtools-api" "^6.0.0-beta.14"
|
||||||
|
|
||||||
vue-types@^4.0.3:
|
vue-types@^4.1.0:
|
||||||
version "4.1.0"
|
version "4.1.0"
|
||||||
resolved "https://registry.npmjs.org/vue-types/-/vue-types-4.1.0.tgz#8dcbbaccf9d5c3815449ac7cb8ae5864454cfff0"
|
resolved "https://registry.npmjs.org/vue-types/-/vue-types-4.1.0.tgz#8dcbbaccf9d5c3815449ac7cb8ae5864454cfff0"
|
||||||
integrity sha512-oPAeKKx5vY5Q8c7lMQPQyrBIbmWQGael5XEHqO1f+Y3V/RUZNuISz7KxI4woGjh79Vy/gDDaPX9j9zKYpaaA2g==
|
integrity sha512-oPAeKKx5vY5Q8c7lMQPQyrBIbmWQGael5XEHqO1f+Y3V/RUZNuISz7KxI4woGjh79Vy/gDDaPX9j9zKYpaaA2g==
|
||||||
dependencies:
|
dependencies:
|
||||||
is-plain-object "5.0.0"
|
is-plain-object "5.0.0"
|
||||||
|
|
||||||
vue@^3.1.1, vue@^3.2.11:
|
vue@3.2.11, vue@^3.1.1:
|
||||||
version "3.2.11"
|
version "3.2.11"
|
||||||
resolved "https://registry.npmjs.org/vue/-/vue-3.2.11.tgz#6b92295048df705ddac558fd3e3ed553e55e57c8"
|
resolved "https://registry.npmjs.org/vue/-/vue-3.2.11.tgz#6b92295048df705ddac558fd3e3ed553e55e57c8"
|
||||||
integrity sha512-JkI3/eIgfk4E0f/p319TD3EZgOwBQfftgnkRsXlT7OrRyyiyoyUXn6embPGZXSBxD3LoZ9SWhJoxLhFh5AleeA==
|
integrity sha512-JkI3/eIgfk4E0f/p319TD3EZgOwBQfftgnkRsXlT7OrRyyiyoyUXn6embPGZXSBxD3LoZ9SWhJoxLhFh5AleeA==
|
||||||
|
Loading…
x
Reference in New Issue
Block a user