Merge pull request #38 from xiaoxian521/refactor/setup

Refactor/setup
This commit is contained in:
啝裳 2021-09-19 15:41:33 +08:00 committed by GitHub
commit dd8cc8508e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
59 changed files with 5006 additions and 2826 deletions

View File

@ -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",

View File

@ -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>

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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() {
switch (this.$storage.locale?.locale) {
case "zh": case "zh":
return zhCn; return zhCn;
case "en": case "en":
return en; return en;
} }
}
}
}; };
</script> </script>
<template>
<el-config-provider :locale="currentLocale()">
<router-view />
</el-config-provider>
</template>

View File

@ -1,27 +1,7 @@
<template> <script setup lang="ts">
<el-breadcrumb class="app-breadcrumb" separator="/"> import { ref, watch, Ref } from "vue";
<transition-group appear name="breadcrumb">
<el-breadcrumb-item v-for="(item, index) in levelList" :key="item.path">
<span
v-if="item.redirect === 'noRedirect' || index == levelList.length - 1"
class="no-redirect"
>{{ $t(item.meta.title) }}</span
>
<a v-else @click.prevent="handleLink(item)">
{{ $t(item.meta.title) }}
</a>
</el-breadcrumb-item>
</transition-group>
</el-breadcrumb>
</template>
<script lang="ts">
import { ref, defineComponent, watch, Ref } from "vue";
import { useRoute, useRouter, RouteLocationMatched } from "vue-router"; import { useRoute, useRouter, RouteLocationMatched } from "vue-router";
export default defineComponent({
name: "ReBreadCrumb",
setup() {
const levelList: Ref<RouteLocationMatched[]> = ref([]); const levelList: Ref<RouteLocationMatched[]> = ref([]);
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
@ -65,12 +45,25 @@ export default defineComponent({
} }
router.push(path); router.push(path);
}; };
return { levelList, handleLink };
}
});
</script> </script>
<template>
<el-breadcrumb class="app-breadcrumb" separator="/">
<transition-group appear name="breadcrumb">
<el-breadcrumb-item v-for="(item, index) in levelList" :key="item.path">
<span
v-if="item.redirect === 'noRedirect' || index == levelList.length - 1"
class="no-redirect"
>{{ $t(item.meta.title) }}</span
>
<a v-else @click.prevent="handleLink(item)">
{{ $t(item.meta.title) }}
</a>
</el-breadcrumb-item>
</transition-group>
</el-breadcrumb>
</template>
<style lang="scss" scoped> <style lang="scss" scoped>
.app-breadcrumb.el-breadcrumb { .app-breadcrumb.el-breadcrumb {
display: inline-block; display: inline-block;

View File

@ -1,5 +1,4 @@
import type { CSSProperties } from "vue"; import type { CSSProperties } from "vue";
import { import {
defineComponent, defineComponent,
onBeforeMount, onBeforeMount,
@ -40,9 +39,7 @@ const defaultOptions: Cropper.Options = {
rotatable: true rotatable: true
}; };
export default defineComponent({ const props = {
name: "Cropper",
props: {
src: { src: {
type: String, type: String,
required: true required: true
@ -74,12 +71,16 @@ export default defineComponent({
return {}; 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 {

View File

@ -2,9 +2,7 @@ import { defineComponent, ref } from "vue";
import { propTypes } from "/@/utils/propTypes"; import { propTypes } from "/@/utils/propTypes";
import "./filpper.css"; import "./filpper.css";
export default defineComponent({ const props = {
name: "Filpper",
props: {
// front paper text // front paper text
// 前牌文字 // 前牌文字
frontText: propTypes.number.def(0), frontText: propTypes.number.def(0),
@ -14,7 +12,11 @@ export default defineComponent({
// flipping duration, please be consistent with the CSS animation-duration value. // flipping duration, please be consistent with the CSS animation-duration value.
// 翻牌动画时间与CSS中设置的animation-duration保持一致 // 翻牌动画时间与CSS中设置的animation-duration保持一致
duration: propTypes.number.def(600) duration: propTypes.number.def(600)
}, };
export default defineComponent({
name: "Filpper",
props,
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;

View File

@ -1,48 +1,17 @@
<template> <script setup lang="ts">
<div class="flip-clock">
<flippers ref="flipperHour1" />
<flippers ref="flipperHour2" />
<em>:</em>
<flippers ref="flipperMinute1" />
<flippers ref="flipperMinute2" />
<em>:</em>
<flippers ref="flipperSecond1" />
<flippers ref="flipperSecond2" />
</div>
</template>
<script lang="ts">
import { ref, unref, nextTick, onUnmounted } from "vue"; import { ref, unref, nextTick, onUnmounted } from "vue";
import { templateRef } from "@vueuse/core";
import flippers from "./Filpper"; import flippers from "./Filpper";
import { templateRef } from "@vueuse/core";
export default {
name: "Flop",
components: {
flippers
},
setup() {
let timer = ref(null); let timer = ref(null);
let flipObjs = ref([]); let flipObjs = ref([]);
const flipperHour1 = templateRef<HTMLElement | null>("flipperHour1", null); const flipperHour1 = templateRef<HTMLElement | null>("flipperHour1", null);
const flipperHour2 = templateRef<HTMLElement | null>("flipperHour2", null); const flipperHour2 = templateRef<HTMLElement | null>("flipperHour2", null);
const flipperMinute1 = templateRef<HTMLElement | null>( const flipperMinute1 = templateRef<HTMLElement | null>("flipperMinute1", null);
"flipperMinute1", const flipperMinute2 = templateRef<HTMLElement | null>("flipperMinute2", null);
null const flipperSecond1 = templateRef<HTMLElement | null>("flipperSecond1", null);
); const flipperSecond2 = templateRef<HTMLElement | null>("flipperSecond2", null);
const flipperMinute2 = templateRef<HTMLElement | null>(
"flipperMinute2",
null
);
const flipperSecond1 = templateRef<HTMLElement | null>(
"flipperSecond1",
null
);
const flipperSecond2 = templateRef<HTMLElement | null>(
"flipperSecond2",
null
);
// //
const init = () => { const init = () => {
@ -133,25 +102,21 @@ export default {
timer.value = null; timer.value = null;
} }
}); });
return {
timer,
flipObjs,
init,
run,
formatDate,
padLeftZero,
flipperHour1,
flipperHour2,
flipperMinute1,
flipperMinute2,
flipperSecond1,
flipperSecond2
};
}
};
</script> </script>
<template>
<div class="flip-clock">
<flippers ref="flipperHour1" />
<flippers ref="flipperHour2" />
<em>:</em>
<flippers ref="flipperMinute1" />
<flippers ref="flipperMinute2" />
<em>:</em>
<flippers ref="flipperSecond1" />
<flippers ref="flipperSecond2" />
</div>
</template>
<style> <style>
.flip-clock .m-flipper { .flip-clock .m-flipper {
margin: 0 3px; margin: 0 3px;

View File

@ -1,53 +1,25 @@
<template> <script setup lang="ts">
<div class="control-container"> import { ref, unref, onMounted } from "vue";
<!-- 功能按钮 -->
<ul>
<li
v-for="(item, key) in titleLists"
:key="key"
:title="item.text"
:style="{ background: focusIndex === key ? '#ccc' : '' }"
@mouseenter.prevent="onEnter(key)"
@mouseleave.prevent="focusIndex = -1"
>
<button
:ref="'controlButton' + key"
:disabled="item.disabled"
:style="{
cursor: item.disabled === false ? 'pointer' : 'not-allowed'
}"
@click="onControl(item, key)"
>
<span :class="'iconfont ' + item.icon"></span>
<p>{{ item.text }}</p>
</button>
</li>
</ul>
</div>
</template>
<script lang="ts">
import { defineComponent, ref, unref, onMounted } from "vue";
import { templateRef } from "@vueuse/core"; import { templateRef } from "@vueuse/core";
import { LogicFlow } from "@logicflow/core";
export default defineComponent({ interface Props {
name: "Control", lf: LogicFlow;
props: { catTurboData?: boolean;
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); 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([ let titleLists = ref([
{ {
icon: "icon-zoom-out-hs", icon: "icon-zoom-out-hs",
@ -109,23 +81,40 @@ export default defineComponent({
onMounted(() => { onMounted(() => {
props.lf.on("history:change", ({ data: { undoAble, redoAble } }) => { props.lf.on("history:change", ({ data: { undoAble, redoAble } }) => {
unref(titleLists)[3].disabled = unref(controlButton3).disabled = unref(titleLists)[3].disabled = unref(controlButton3).disabled = !undoAble;
!undoAble; unref(titleLists)[4].disabled = unref(controlButton4).disabled = !redoAble;
unref(titleLists)[4].disabled = unref(controlButton4).disabled =
!redoAble;
}); });
}); });
return {
focusIndex,
titleLists,
onControl,
onEnter
};
}
});
</script> </script>
<template>
<div class="control-container">
<!-- 功能按钮 -->
<ul>
<li
v-for="(item, key) in titleLists"
:key="key"
:title="item.text"
:style="{ background: focusIndex === key ? '#ccc' : '' }"
@mouseenter.prevent="onEnter(key)"
@mouseleave.prevent="focusIndex = -1"
>
<button
:ref="'controlButton' + key"
:disabled="item.disabled"
:style="{
cursor: item.disabled === false ? 'pointer' : 'not-allowed'
}"
@click="onControl(item, key)"
>
<span :class="'iconfont ' + item.icon"></span>
<p>{{ item.text }}</p>
</button>
</li>
</ul>
</div>
</template>
<style scoped> <style scoped>
@import "./assets/iconfont/iconfont.css"; @import "./assets/iconfont/iconfont.css";

View File

@ -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>

View File

@ -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;

View File

@ -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: {
isActive: {
type: Boolean,
default: false
} }
}, </style>
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>

View File

@ -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;

View File

@ -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
}; };

View File

@ -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,12 +19,11 @@ export interface mapInter {
loading: boolean; loading: boolean;
} }
export default defineComponent({ let MarkerCluster;
name: "Amap",
setup() {
const instance = getCurrentInstance();
let map: MapConfigureInter; let map: MapConfigureInter;
const instance = getCurrentInstance();
const mapSet: mapInter = reactive({ const mapSet: mapInter = reactive({
loading: deviceDetection() ? false : true loading: deviceDetection() ? false : true
}); });
@ -66,17 +37,9 @@ export default defineComponent({
} }
}; };
//
const destroyMap = (): void => {
if (map) {
map.destroy() && map.clearEvents("click");
}
};
onBeforeMount(() => { onBeforeMount(() => {
if (!instance) return; if (!instance) return;
let { MapConfigure } = let { MapConfigure } = instance.appContext.config.globalProperties.$config;
instance.appContext.config.globalProperties.$config;
let { options } = MapConfigure; let { options } = MapConfigure;
AMapLoader.load({ AMapLoader.load({
@ -100,7 +63,8 @@ export default defineComponent({
}); });
MarkerCluster = new AMap.MarkerCluster(map, [], { MarkerCluster = new AMap.MarkerCluster(map, [], {
gridSize: 80, // //
gridSize: 80,
maxZoom: 14, maxZoom: 14,
renderMarker(ctx) { renderMarker(ctx) {
let { marker, data } = ctx; let { marker, data } = ctx;
@ -112,8 +76,10 @@ export default defineComponent({
marker.setContent(content); marker.setContent(content);
marker.setLabel({ marker.setLabel({
direction: "bottom", direction: "bottom",
offset: new AMap.Pixel(-4, 0), // //
content: `<div> ${plateNumber}(${driver})</div>` // offset: new AMap.Pixel(-4, 0),
//
content: `<div> ${plateNumber}(${driver})</div>`
}); });
marker.setOffset(new AMap.Pixel(-18, -10)); marker.setOffset(new AMap.Pixel(-18, -10));
marker.on("click", ({ lnglat }) => { marker.on("click", ({ lnglat }) => {
@ -147,16 +113,25 @@ export default defineComponent({
}); });
}); });
return { onUnmounted(() => {
...toRefs(mapSet), if (map) {
complete, //
destroyMap, map.destroy() && map.clearEvents("click");
greenCar
};
} }
}); });
</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%;

View File

@ -1,14 +0,0 @@
<template>
<div></div>
</template>
<script lang="ts">
export default {
name: "BaiduMap",
setup() {
return {};
}
};
</script>
<style scoped></style>

View File

@ -1,41 +1,6 @@
<template> <script setup lang="ts">
<div :ref="'wrap' + classOption['key']"> import { computed, ref, unref, nextTick } from "vue";
<div import type { CSSProperties, PropType } from "vue";
:style="leftSwitch"
v-if="navigation"
:class="leftSwitchClass"
@click="leftSwitchClick"
>
<slot name="left-switch"></slot>
</div>
<div
:style="rightSwitch"
v-if="navigation"
:class="rightSwitchClass"
@click="rightSwitchClick"
>
<slot name="right-switch"></slot>
</div>
<div
:ref="'realBox' + classOption['key']"
:style="pos"
@mouseenter="enter"
@mouseleave="leave"
@touchstart="touchStart"
@touchmove="touchMove"
@touchend="touchEnd"
@mousewheel="wheel"
>
<div :ref="'slotList' + classOption['key']" :style="float">
<slot></slot>
</div>
<div v-html="copyHtml" :style="float"></div>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, computed, ref, unref, nextTick } from "vue";
import { import {
tryOnMounted, tryOnMounted,
tryOnUnmounted, tryOnUnmounted,
@ -46,35 +11,29 @@ import * as utilsMethods from "./utils";
const { animationFrame, copyObj } = utilsMethods; const { animationFrame, copyObj } = utilsMethods;
animationFrame(); animationFrame();
export default defineComponent({ const props = defineProps({
name: "SeamlessScroll",
props: {
data: { data: {
type: Array, type: Array as PropType<unknown>
default: () => {
return [];
}
}, },
classOption: { classOption: {
type: Object, type: Object as PropType<unknown>
default: () => {
return {};
} }
} });
},
emits: ["ScrollEnd"],
setup(props, { emit }) {
let xPos = ref(0);
let yPos = ref(0);
let delay = ref(0);
let copyHtml = ref("");
let height = ref(0);
//
let width = ref(0);
//
let realBoxWidth = ref(0);
let realBoxHeight = ref(0);
const emit = defineEmits<{
(e: "scrollEnd"): void;
}>();
let xPos = ref<number>(0);
let yPos = ref<number>(0);
let delay = ref<number>(0);
let height = ref<number>(0);
//
let width = ref<number>(0);
//
let realBoxWidth = ref<number>(0);
let realBoxHeight = ref<number>(0);
let copyHtml = ref("");
// single // single
let singleWaitTime = null; let singleWaitTime = null;
// moveanimationFrame // moveanimationFrame
@ -95,10 +54,7 @@ export default defineComponent({
classOption["key"] = 0; classOption["key"] = 0;
} }
const wrap = templateRef<HTMLElement | null>( const wrap = templateRef<HTMLElement | null>(`wrap${classOption["key"]}`, null);
`wrap${classOption["key"]}`,
null
);
const slotList = templateRef<HTMLElement | null>( const slotList = templateRef<HTMLElement | null>(
`slotList${classOption["key"]}`, `slotList${classOption["key"]}`,
null null
@ -150,7 +106,7 @@ export default defineComponent({
return copyObj({}, unref(defaultOption), classOption); return copyObj({}, unref(defaultOption), classOption);
}); });
let leftSwitchClass = computed(() => { const leftSwitchClass = computed(() => {
return unref(leftSwitchState) ? "" : unref(options).switchDisabledClass; return unref(leftSwitchState) ? "" : unref(options).switchDisabledClass;
}); });
@ -158,7 +114,7 @@ export default defineComponent({
return unref(rightSwitchState) ? "" : unref(options).switchDisabledClass; return unref(rightSwitchState) ? "" : unref(options).switchDisabledClass;
}); });
let leftSwitch = computed(() => { let leftSwitch = computed((): CSSProperties => {
return { return {
position: "absolute", position: "absolute",
margin: `${unref(height) / 2}px 0 0 -${unref(options).switchOffset}px`, margin: `${unref(height) / 2}px 0 0 -${unref(options).switchOffset}px`,
@ -166,7 +122,7 @@ export default defineComponent({
}; };
}); });
let rightSwitch = computed(() => { let rightSwitch = computed((): CSSProperties => {
return { return {
position: "absolute", position: "absolute",
margin: `${unref(height) / 2}px 0 0 ${ margin: `${unref(height) / 2}px 0 0 ${
@ -178,12 +134,11 @@ export default defineComponent({
let isHorizontal = computed(() => { let isHorizontal = computed(() => {
return ( return (
unref(options).direction !== "bottom" && unref(options).direction !== "bottom" && unref(options).direction !== "top"
unref(options).direction !== "top"
); );
}); });
let float = computed(() => { let float = computed((): CSSProperties => {
return unref(isHorizontal) return unref(isHorizontal)
? { float: "left", overflow: "hidden" } ? { float: "left", overflow: "hidden" }
: { overflow: "hidden" }; : { overflow: "hidden" };
@ -221,9 +176,7 @@ export default defineComponent({
let baseFontSize = computed(() => { let baseFontSize = computed(() => {
return unref(options).isSingleRemUnit return unref(options).isSingleRemUnit
? parseInt( ? parseInt(window.getComputedStyle(document.documentElement, null).fontSize)
window.getComputedStyle(document.documentElement, null).fontSize
)
: 1; : 1;
}); });
@ -386,28 +339,28 @@ export default defineComponent({
if (direction === "top") { if (direction === "top") {
// //
if (Math.abs(unref(yPos)) >= h) { if (Math.abs(unref(yPos)) >= h) {
emit("ScrollEnd"); emit("scrollEnd");
yPos.value = 0; yPos.value = 0;
} }
yPos.value -= step.value; yPos.value -= step.value;
} else if (direction === "bottom") { } else if (direction === "bottom") {
// //
if (unref(yPos) >= 0) { if (unref(yPos) >= 0) {
emit("ScrollEnd"); emit("scrollEnd");
yPos.value = h * -1; yPos.value = h * -1;
} }
yPos.value += step.value; yPos.value += step.value;
} else if (direction === "left") { } else if (direction === "left") {
// //
if (Math.abs(unref(xPos)) >= w) { if (Math.abs(unref(xPos)) >= w) {
emit("ScrollEnd"); emit("scrollEnd");
xPos.value = 0; xPos.value = 0;
} }
xPos.value -= step.value; xPos.value -= step.value;
} else if (direction === "right") { } else if (direction === "right") {
// //
if (unref(xPos) >= 0) { if (unref(xPos) >= 0) {
emit("ScrollEnd"); emit("scrollEnd");
xPos.value = w * -1; xPos.value = w * -1;
} }
xPos.value += step.value; xPos.value += step.value;
@ -415,10 +368,7 @@ export default defineComponent({
if (singleWaitTime) clearTimeout(singleWaitTime); if (singleWaitTime) clearTimeout(singleWaitTime);
if (unref(realSingleStopHeight)) { if (unref(realSingleStopHeight)) {
// //
if ( if (Math.abs(unref(yPos)) % unref(realSingleStopHeight) < unref(step)) {
Math.abs(unref(yPos)) % unref(realSingleStopHeight) <
unref(step)
) {
// waitTime // waitTime
singleWaitTime = setTimeout(() => { singleWaitTime = setTimeout(() => {
scrollMove(); scrollMove();
@ -427,10 +377,7 @@ export default defineComponent({
scrollMove(); scrollMove();
} }
} else if (unref(realSingleStopWidth)) { } else if (unref(realSingleStopWidth)) {
if ( if (Math.abs(unref(xPos)) % unref(realSingleStopWidth) < unref(step)) {
Math.abs(unref(xPos)) % unref(realSingleStopWidth) <
unref(step)
) {
// waitTime // waitTime
singleWaitTime = setTimeout(() => { singleWaitTime = setTimeout(() => {
scrollMove(); scrollMove();
@ -501,6 +448,19 @@ export default defineComponent({
scrollCancle(); scrollCancle();
} }
//
function wheel(e) {
e.preventDefault();
if (
unref(options).direction === "left" ||
unref(options).direction === "right"
)
return;
useDebounceFn(() => {
e.deltaY > 0 ? (yPos.value -= step.value) : (yPos.value += step.value);
}, 50)();
}
// watchEffect(() => { // watchEffect(() => {
// const watchData = data; // const watchData = data;
// if (!watchData) return; // if (!watchData) return;
@ -516,19 +476,6 @@ export default defineComponent({
// } // }
// }); // });
//
function wheel(e) {
e.preventDefault();
if (
unref(options).direction === "left" ||
unref(options).direction === "right"
)
return;
useDebounceFn(() => {
e.deltaY > 0 ? (yPos.value -= step.value) : (yPos.value += step.value);
}, 50)();
}
tryOnMounted(() => { tryOnMounted(() => {
scrollInitMove(); scrollInitMove();
}); });
@ -538,48 +485,43 @@ export default defineComponent({
clearTimeout(singleWaitTime); clearTimeout(singleWaitTime);
}); });
return { defineExpose({
xPos, reset
yPos,
delay,
copyHtml,
height,
width,
realBoxWidth,
leftSwitchState,
rightSwitchState,
options,
leftSwitchClass,
rightSwitchClass,
leftSwitch,
rightSwitch,
isHorizontal,
float,
pos,
navigation,
autoPlay,
scrollSwitch,
hoverStopSwitch,
canTouchScroll,
baseFontSize,
realSingleStopWidth,
realSingleStopHeight,
step,
reset,
leftSwitchClick,
rightSwitchClick,
scrollCancle,
touchStart,
touchMove,
touchEnd,
enter,
leave,
scrollMove,
scrollInitMove,
scrollStartMove,
scrollStopMove,
wheel
};
}
}); });
</script> </script>
<template>
<div :ref="'wrap' + classOption['key']">
<div
:style="leftSwitch"
v-if="navigation"
:class="leftSwitchClass"
@click="leftSwitchClick"
>
<slot name="left-switch"></slot>
</div>
<div
:style="rightSwitch"
v-if="navigation"
:class="rightSwitchClass"
@click="rightSwitchClick"
>
<slot name="right-switch"></slot>
</div>
<div
:ref="'realBox' + classOption['key']"
:style="pos"
@mouseenter="enter"
@mouseleave="leave"
@touchstart="touchStart"
@touchmove="touchMove"
@touchend="touchEnd"
@mousewheel="wheel"
>
<div :ref="'slotList' + classOption['key']" :style="float">
<slot></slot>
</div>
<div v-html="copyHtml" :style="float"></div>
</div>
</div>
</template>

View File

@ -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 ||

View File

@ -21,9 +21,7 @@ let overList = [];
// 存放第一个选中的元素和最后一个选中元素,只能存放这两个元素 // 存放第一个选中的元素和最后一个选中元素,只能存放这两个元素
let selectedList = []; let selectedList = [];
export default defineComponent({ const props = {
name: "Selector",
props: {
HsKey: { HsKey: {
type: Number || String, type: Number || String,
default: 0 default: 0
@ -49,7 +47,11 @@ export default defineComponent({
return []; return [];
} }
} }
}, };
export default defineComponent({
name: "Selector",
props,
emits: ["selectedVal"], emits: ["selectedVal"],
setup(props, { emit }) { setup(props, { emit }) {
const instance = getCurrentInstance(); const instance = getCurrentInstance();

View File

@ -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);
}; };

View File

@ -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;

View File

@ -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");
}); });

View File

@ -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: {

View File

@ -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) {

View File

@ -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();

View File

@ -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
}; };

View File

@ -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",

View File

@ -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;

View File

@ -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;

View File

@ -30,4 +30,5 @@ propTypes.extend([
type: undefined type: undefined
} }
]); ]);
export { propTypes }; export { propTypes };

View File

@ -1,24 +1,17 @@
<template> <script setup lang="ts">
<iframe :src="url" frameborder="0" class="iframe"></iframe>
</template>
<script lang="ts">
import { ref } from "vue"; import { ref } from "vue";
export default {
name: "reButton",
setup() {
const url = ref( const url = ref(
process.env.NODE_ENV === "production" process.env.NODE_ENV === "production"
? "/manages/html/button.html" ? "/manages/html/button.html"
: "/html/button.html" : "/html/button.html"
); );
return {
url
};
}
};
</script> </script>
<template>
<iframe :src="url" frameborder="0" class="iframe"></iframe>
</template>
<style scoped> <style scoped>
.iframe { .iframe {
width: 98%; width: 98%;

View File

@ -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>

View File

@ -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;

View File

@ -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;

View File

@ -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 {

View File

@ -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%;

View File

@ -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;

View File

@ -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>

View File

@ -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;

View File

@ -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,9 +6,6 @@ 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 {
name: "reVideo",
setup() {
onMounted(() => { onMounted(() => {
new Player({ new Player({
id: "mse", id: "mse",
@ -23,15 +16,17 @@ export default {
"https://s2.pstatp.com/cdn/expire-1-M/byted-player-videos/1.0.0/poster.jpg", "https://s2.pstatp.com/cdn/expire-1-M/byted-player-videos/1.0.0/poster.jpg",
fluid: deviceDetection(), fluid: deviceDetection(),
controlPlugins: [volume, playbackRate, screenShot], controlPlugins: [volume, playbackRate, screenShot],
playbackRate: [0.5, 0.75, 1, 1.5, 2] // //
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;
} }

View File

@ -1,29 +1,23 @@
<template> <script lang="ts">
<div> export default {
<div ref="editor"></div> name: "reEditor"
<div :innerHTML="content.html"></div> };
</div> </script>
</template>
<script> <script setup lang="ts">
import { onMounted, onBeforeUnmount, ref, reactive } from "vue"; import { onMounted, onBeforeUnmount, ref, unref } from "vue";
import WangEditor from "wangeditor"; import WangEditor from "wangeditor";
export default { // eslint-disable-next-line no-undef
name: "reEditor", const editor = ref(null);
setup() { const html = ref(null);
const editor = ref(); let instance: WangEditor;
const content = reactive({
html: "",
text: ""
});
let instance;
onMounted(() => { onMounted(() => {
instance = new WangEditor(editor.value); instance = new WangEditor(unref(editor));
Object.assign(instance.config, { Object.assign(instance.config, {
onchange() { onchange() {
content.html = instance.txt.html(); html.value = instance.txt.html();
} }
}); });
instance.create(); instance.create();
@ -31,17 +25,16 @@ export default {
onBeforeUnmount(() => { onBeforeUnmount(() => {
instance.destroy(); instance.destroy();
instance = null;
}); });
return {
editor,
content
};
}
};
</script> </script>
<template>
<div>
<div ref="editor"></div>
<div :innerHTML="html"></div>
</div>
</template>
<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;

View File

@ -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;

View File

@ -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%);

View File

@ -1,43 +1,17 @@
<template> <script setup lang="ts">
<div class="logic-flow-view">
<!-- 辅助工具栏 -->
<Control
class="demo-control"
v-if="lf"
:lf="lf"
:catTurboData="false"
@catData="catData"
></Control>
<!-- 节点面板 -->
<NodePanel :lf="lf" :nodeList="nodeList"></NodePanel>
<!-- 画布 -->
<div id="LF-Turbo"></div>
<!-- 数据查看面板 -->
<el-dialog title="数据" v-model="dataVisible" width="50%">
<DataDialog :graphData="graphData"></DataDialog>
</el-dialog>
</div>
</template>
<script lang="ts">
import { ref, unref, onMounted } from "vue"; import { ref, unref, onMounted } from "vue";
import LogicFlow from "@logicflow/core"; import LogicFlow from "@logicflow/core";
import { Snapshot, BpmnElement, Menu } from "@logicflow/extension"; import { Snapshot, BpmnElement, Menu } from "@logicflow/extension";
import "@logicflow/core/dist/style/index.css"; import "@logicflow/core/dist/style/index.css";
import "@logicflow/extension/lib/style/index.css"; import "@logicflow/extension/lib/style/index.css";
import { Control, NodePanel, DataDialog } from "/@/components/ReFlowChart"; import { Control, NodePanel, DataDialog } from "/@/components/ReFlowChart";
import { toLogicflowData } from "/@/components/ReFlowChart/src/adpterForTurbo"; import { toLogicflowData } from "/@/components/ReFlowChart/src/adpterForTurbo";
import { BpmnNode } from "/@/components/ReFlowChart/src/config"; import { BpmnNode } from "/@/components/ReFlowChart/src/config";
import demoData from "./dataTurbo.json"; import demoData from "./dataTurbo.json";
export default {
name: "reFlowChart", let lf = ref(null);
components: { NodePanel, Control, DataDialog },
setup() {
// eslint-disable-next-line no-undef
let lf = ref<ElRef>(null);
let graphData = ref(null); let graphData = ref(null);
let dataVisible = ref(false); let dataVisible = ref<boolean>(false);
let config = ref({ let config = ref({
grid: true, grid: true,
background: { background: {
@ -80,19 +54,29 @@ export default {
onMounted(() => { onMounted(() => {
initLf(); initLf();
}); });
return {
lf,
graphData,
dataVisible,
config,
nodeList,
catData
};
}
};
</script> </script>
<template>
<div class="logic-flow-view">
<!-- 辅助工具栏 -->
<Control
class="demo-control"
v-if="lf"
:lf="lf"
:catTurboData="false"
@catData="catData"
></Control>
<!-- 节点面板 -->
<NodePanel :lf="lf" :nodeList="nodeList"></NodePanel>
<!-- 画布 -->
<div id="LF-Turbo"></div>
<!-- 数据查看面板 -->
<el-dialog title="数据" v-model="dataVisible" width="50%">
<DataDialog :graphData="graphData"></DataDialog>
</el-dialog>
</div>
</template>
<style scoped> <style scoped>
#LF-Turbo { #LF-Turbo {
width: 100vw; width: 100vw;

View File

@ -1,26 +1,11 @@
<template> <script setup lang="ts">
<div class="login">
<info
:ruleForm="contextInfo"
@on-behavior="onLogin"
@refreshVerify="refreshVerify"
/>
</div>
</template>
<script lang="ts">
import { reactive, onBeforeMount } from "vue"; import { reactive, onBeforeMount } from "vue";
import info, { ContextProps } from "../components/ReInfo/index.vue"; import info, { ContextProps } from "../components/ReInfo/index.vue";
import { getVerify, getLogin } from "/@/api/user"; import { getVerify, getLogin } from "/@/api/user";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import { storageSession } from "/@/utils/storage"; import { storageSession } from "/@/utils/storage";
import { warnMessage, successMessage } from "/@/utils/message"; import { warnMessage, successMessage } from "/@/utils/message";
export default {
name: "login",
components: {
info
},
setup() {
const router = useRouter(); const router = useRouter();
// //
@ -65,14 +50,14 @@ export default {
onBeforeMount(() => { onBeforeMount(() => {
// refreshGetVerify(); // refreshGetVerify();
}); });
return {
contextInfo,
onLogin,
router,
toPage,
refreshVerify
};
}
};
</script> </script>
<template>
<div class="login">
<info
:ruleForm="contextInfo"
@on-behavior="onLogin"
@refreshVerify="refreshVerify"
/>
</div>
</template>

View File

@ -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>

View File

@ -1,23 +1,8 @@
<template> <script setup lang="ts">
<div class="app-container">
<h4>
当前角色
<span style="font-size: 26px">{{ purview }}</span>
<p style="color: #ffa500">
查看左侧菜单变化(系统管理)模拟后台根据不同角色返回对应路由
</p>
</h4>
<el-button type="primary" @click="changRole">切换角色</el-button>
</div>
</template>
<script lang="ts">
import { ref, unref } from "vue"; import { ref, unref } from "vue";
import { storageSession } from "/@/utils/storage"; import { storageSession } from "/@/utils/storage";
export default {
name: "permissionPage", let purview = ref<string>(storageSession.getItem("info").username);
setup() {
let purview: string = ref(storageSession.getItem("info").username);
function changRole() { function changRole() {
if (unref(purview) === "admin") { if (unref(purview) === "admin") {
@ -34,11 +19,17 @@ export default {
window.location.reload(); window.location.reload();
} }
} }
return {
purview,
changRole
};
}
};
</script> </script>
<template>
<div class="app-container">
<h4>
当前角色
<span style="font-size: 26px">{{ purview }}</span>
<p style="color: #ffa500">
查看左侧菜单变化(系统管理)模拟后台根据不同角色返回对应路由
</p>
</h4>
<el-button type="primary" @click="changRole">切换角色</el-button>
</div>
</template>

View File

@ -1,13 +1,7 @@
<template> <script setup lang="ts">
<div></div> import { unref } from "vue";
</template>
<script lang="ts">
import { defineComponent, unref } from "vue";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
export default defineComponent({
name: "redirect",
setup() {
const { currentRoute, replace } = useRouter(); const { currentRoute, replace } = useRouter();
const { params, query } = unref(currentRoute); const { params, query } = unref(currentRoute);
@ -19,8 +13,8 @@ export default defineComponent({
path: "/" + _path, path: "/" + _path,
query query
}); });
return {};
}
});
</script> </script>
<template>
<div></div>
</template>

View File

@ -1,25 +1,10 @@
<template> <script setup lang="ts">
<div class="register">
<info
:ruleForm="contextInfo"
@on-behavior="onRegist"
@refreshVerify="refreshVerify"
/>
</div>
</template>
<script lang="ts">
import { reactive, onBeforeMount } from "vue"; import { reactive, onBeforeMount } from "vue";
import info, { ContextProps } from "../components/ReInfo/index.vue"; import info, { ContextProps } from "../components/ReInfo/index.vue";
import { getRegist, getVerify } from "/@/api/user"; import { getRegist, getVerify } from "/@/api/user";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import { warnMessage, successMessage } from "/@/utils/message"; import { warnMessage, successMessage } from "/@/utils/message";
export default {
name: "register",
components: {
info
},
setup() {
const router = useRouter(); const router = useRouter();
// //
@ -55,13 +40,14 @@ export default {
onBeforeMount(() => { onBeforeMount(() => {
// refreshGetVerify(); // refreshGetVerify();
}); });
return {
contextInfo,
onRegist,
router,
refreshVerify
};
}
};
</script> </script>
<template>
<div class="register">
<info
:ruleForm="contextInfo"
@on-behavior="onRegist"
@refreshVerify="refreshVerify"
/>
</div>
</template>

View File

@ -1,93 +1,23 @@
<template> <script setup lang="ts">
<div class="config"> import { reactive } from "vue";
<el-drawer
:model-value="drawer"
:title="drawTitle"
:direction="direction"
:before-close="handleClose"
destroy-on-close
size="640px"
>
<el-divider></el-divider>
<!-- 列表 -->
<div class="list">
<vxe-table
ref="xTable"
border
:data="tableData"
@checkbox-change="checkboxChangeEvent"
@checkbox-all="checkboxChangeEvent"
>
<vxe-table-column type="checkbox" width="60"></vxe-table-column>
<vxe-table-column field="name" title="名称"></vxe-table-column>
<vxe-table-column field="dataval" title="数据值"></vxe-table-column>
<vxe-table-column title="操作" fixed="right">
<template #default="{ row }">
<vxe-button
type="text"
icon="el-icon-edit"
@click="editConfig(row)"
>编辑</vxe-button
>
<vxe-button
type="text"
icon="el-icon-delete"
@click="delConfig(row)"
>删除</vxe-button
>
</template>
</vxe-table-column>
</vxe-table>
<vxe-pager
perfect
v-model:current-page="tablePage.currentPage"
v-model:page-size="tablePage.pageSize"
:total="tablePage.total"
:layouts="[
'PrevJump',
'PrevPage',
'Number',
'NextPage',
'NextJump',
'Sizes',
'FullJump',
'Total'
]"
>
<template #left>
<span class="page-left">
<vxe-checkbox
v-model="isAllChecked"
:indeterminate="isIndeterminate"
@change="changeAllEvent"
></vxe-checkbox>
<span class="select-count"
>已选中{{ selectRecords.length }}</span
>
<vxe-button size="small">{{ $t("message.hsdelete") }}</vxe-button>
</span>
</template>
</vxe-pager>
</div>
</el-drawer>
</div>
</template>
<script lang="ts">
import { defineComponent, reactive, toRefs } from "vue";
import { propTypes } from "/@/utils/propTypes";
import { VxeTableEvents } from "vxe-table"; import { VxeTableEvents } from "vxe-table";
import { templateRef } from "@vueuse/core"; import { templateRef } from "@vueuse/core";
export default defineComponent({ interface Props {
props: { drawer: boolean;
drawer: propTypes.bool.def(false), drawTitle?: string;
drawTitle: propTypes.string.def(""), direction?: string;
direction: propTypes.string.def("rtl") }
},
emits: ["handleClose"], withDefaults(defineProps<Props>(), {
setup(props, ctx) { drawer: false,
const { emit } = ctx; drawTitle: "",
direction: "rtl"
});
const emit = defineEmits<{
(e: "handleClose"): void;
}>();
const xTable = templateRef<any>("xTable", null); const xTable = templateRef<any>("xTable", null);
@ -120,19 +50,11 @@ export default defineComponent({
} }
function editConfig(row) { function editConfig(row) {
console.log( console.log("editConfig", row);
"%crow===>>>: ",
"color: MidnightBlue; background: Aquamarine; font-size: 20px;",
row
);
} }
function delConfig(row) { function delConfig(row) {
console.log( console.log("delConfig", row);
"%crow===>>>: ",
"color: MidnightBlue; background: Aquamarine; font-size: 20px;",
row
);
} }
const changeAllEvent = () => { const changeAllEvent = () => {
@ -144,27 +66,89 @@ export default defineComponent({
configData.selectRecords = $table.getCheckboxRecords(); configData.selectRecords = $table.getCheckboxRecords();
}; };
const checkboxChangeEvent: VxeTableEvents.CheckboxChange = ({ const checkboxChangeEvent: VxeTableEvents.CheckboxChange = ({ records }) => {
records
}) => {
const $table = xTable.value; const $table = xTable.value;
configData.isAllChecked = $table.isAllCheckboxChecked(); configData.isAllChecked = $table.isAllCheckboxChecked();
configData.isIndeterminate = $table.isCheckboxIndeterminate(); configData.isIndeterminate = $table.isCheckboxIndeterminate();
configData.selectRecords = records; configData.selectRecords = records;
}; };
return {
...toRefs(configData),
handleClose,
editConfig,
delConfig,
changeAllEvent,
checkboxChangeEvent
};
}
});
</script> </script>
<template>
<div class="config">
<el-drawer
:model-value="drawer"
:title="drawTitle"
:direction="direction"
:before-close="handleClose"
destroy-on-close
size="640px"
>
<el-divider></el-divider>
<!-- 列表 -->
<div class="list">
<vxe-table
ref="xTable"
border
:data="configData.tableData"
@checkbox-change="checkboxChangeEvent"
@checkbox-all="checkboxChangeEvent"
>
<vxe-table-column type="checkbox" width="60"></vxe-table-column>
<vxe-table-column field="name" title="名称"></vxe-table-column>
<vxe-table-column field="dataval" title="数据值"></vxe-table-column>
<vxe-table-column title="操作" fixed="right">
<template #default="{ row }">
<vxe-button
type="text"
icon="el-icon-edit"
@click="editConfig(row)"
>编辑</vxe-button
>
<vxe-button
type="text"
icon="el-icon-delete"
@click="delConfig(row)"
>删除</vxe-button
>
</template>
</vxe-table-column>
</vxe-table>
<vxe-pager
perfect
v-model:current-page="configData.tablePage.currentPage"
v-model:page-size="configData.tablePage.pageSize"
:total="configData.tablePage.total"
:layouts="[
'PrevJump',
'PrevPage',
'Number',
'NextPage',
'NextJump',
'Sizes',
'FullJump',
'Total'
]"
>
<template #left>
<span class="page-left">
<vxe-checkbox
v-model="configData.isAllChecked"
:indeterminate="configData.isIndeterminate"
@change="changeAllEvent"
></vxe-checkbox>
<span class="select-count"
>已选中{{ configData.selectRecords.length }}</span
>
<vxe-button size="small">{{ $t("message.hsdelete") }}</vxe-button>
</span>
</template>
</vxe-pager>
</div>
</el-drawer>
</div>
</template>
<style lang="scss" scoped> <style lang="scss" scoped>
.list { .list {
padding: 10px; padding: 10px;

View File

@ -1,116 +1,6 @@
<template> <script setup lang="ts">
<div class="dict-container"> import Config from "./config.vue";
<!-- 工具栏 --> import { reactive, ref, unref, nextTick } from "vue";
<vxe-toolbar>
<template #buttons>
<vxe-input
v-model="filterName"
:placeholder="$t('message.hssearch')"
@keyup="searchEvent"
></vxe-input>
</template>
<template #tools>
<vxe-button
icon="el-icon-circle-plus-outline"
status="primary"
@click="onAdd"
>{{ $t("message.hsadd") }}</vxe-button
>
<vxe-button
icon="el-icon-folder-opened"
status="primary"
@click="$refs.xTree.setAllTreeExpand(true)"
>{{ $t("message.hsexpendAll") }}</vxe-button
>
<vxe-button
icon="el-icon-folder"
status="primary"
@click="$refs.xTree.clearTreeExpand()"
>{{ $t("message.hscollapseAll") }}</vxe-button
>
</template>
</vxe-toolbar>
<!-- 列表 -->
<vxe-table
ref="xTree"
border
resizable
:tree-config="{
children: 'children',
iconOpen: 'fa fa-minus-square-o',
iconClose: 'fa fa-plus-square-o'
}"
:data="tableData"
@cell-dblclick="cellDBLClickEvent"
>
<vxe-table-column
tree-node
field="name"
title="字典名称"
></vxe-table-column>
<vxe-table-column title="字典类型">
<template #default="{ row }">
<el-tooltip
effect="dark"
:content="'双击复制:' + row.model"
placement="right"
>
<span class="text-model">{{ row.model }}</span>
</el-tooltip>
</template>
</vxe-table-column>
<vxe-table-column title="操作" width="330" fixed="right">
<template #default="{ row }">
<vxe-button type="text" icon="el-icon-edit" @click="onEdit(row)"
>编辑</vxe-button
>
<vxe-button
type="text"
icon="el-icon-circle-plus-outline"
@click="onAddChild(row)"
>新增子类型</vxe-button
>
<vxe-button
v-show="row.model"
type="text"
icon="el-icon-setting"
@click="onDeploy(row)"
>字典配置</vxe-button
>
<vxe-button type="text" icon="el-icon-delete" @click="confirmEvent"
>删除</vxe-button
>
</template>
</vxe-table-column>
</vxe-table>
<!-- 修改添加弹框 -->
<vxe-modal
resize
width="450"
v-model="showEdit"
:title="selectRow ? '编辑' : '新增'"
:loading="submitLoading"
@hide="$refs.xForm.reset()"
>
<template #default>
<vxe-form
ref="xForm"
:data="formData"
:items="formItems"
title-align="right"
title-width="100"
@submit="submitEvent"
></vxe-form>
</template>
</vxe-modal>
<Config :drawer="drawer" drawTitle="字典列表" @handleClose="handleClose" />
</div>
</template>
<script lang="ts">
import { reactive, ref, unref, nextTick, toRefs } from "vue";
import XEUtils from "xe-utils"; import XEUtils from "xe-utils";
import { cloneDeep } from "lodash-es"; import { cloneDeep } from "lodash-es";
import { templateRef } from "@vueuse/core"; import { templateRef } from "@vueuse/core";
@ -121,14 +11,11 @@ import {
VxeTableEvents, VxeTableEvents,
VxeFormPropTypes VxeFormPropTypes
} from "vxe-table"; } from "vxe-table";
import Config from "./config.vue"; type onEditNRow = {
name: string;
model: string;
};
export default {
name: "dict",
components: {
Config
},
setup() {
const dictData = reactive({ const dictData = reactive({
submitLoading: false, submitLoading: false,
showEdit: false, showEdit: false,
@ -199,10 +86,6 @@ export default {
const xTree = templateRef<HTMLElement | any>("xTree", null); 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 handleSearch = () => {
const filterName = XEUtils.toValueString(dictData.filterName).trim(); const filterName = XEUtils.toValueString(dictData.filterName).trim();
@ -259,17 +142,13 @@ export default {
} }
// //
function onAddChild(row: any) { function onAddChild(row?: object) {
console.log( console.log("onAddChild", row);
"%crow===>>>: ",
"color: MidnightBlue; background: Aquamarine; font-size: 20px;",
row
);
commonFn(null, false); commonFn(null, false);
} }
// //
function onEdit(row: any) { function onEdit(row?: onEditNRow) {
dictData.formData = { dictData.formData = {
name: row.name, name: row.name,
model: row.model ? row.model : "暂无字典类型" model: row.model ? row.model : "暂无字典类型"
@ -307,31 +186,128 @@ export default {
let drawer = ref(false); let drawer = ref(false);
function onDeploy() { function onDeploy(value?: object) {
console.log("onDeploy", value);
drawer.value = true; drawer.value = true;
} }
function handleClose() { function handleClose() {
drawer.value = false; drawer.value = false;
} }
return {
...toRefs(dictData),
formatDate,
searchEvent,
confirmEvent,
cellDBLClickEvent,
submitEvent,
onEdit,
onAddChild,
onAdd,
onDeploy,
drawer,
handleClose
};
}
};
</script> </script>
<template>
<div class="dict-container">
<!-- 工具栏 -->
<vxe-toolbar>
<template #buttons>
<vxe-input
v-model="dictData.filterName"
:placeholder="$t('message.hssearch')"
@keyup="searchEvent"
></vxe-input>
</template>
<template #tools>
<vxe-button
icon="el-icon-circle-plus-outline"
status="primary"
@click="onAdd"
>{{ $t("message.hsadd") }}</vxe-button
>
<vxe-button
icon="el-icon-folder-opened"
status="primary"
@click="$refs.xTree.setAllTreeExpand(true)"
>{{ $t("message.hsexpendAll") }}</vxe-button
>
<vxe-button
icon="el-icon-folder"
status="primary"
@click="$refs.xTree.clearTreeExpand()"
>{{ $t("message.hscollapseAll") }}</vxe-button
>
</template>
</vxe-toolbar>
<!-- 列表 -->
<vxe-table
ref="xTree"
border
resizable
:tree-config="{
children: 'children',
iconOpen: 'fa fa-minus-square-o',
iconClose: 'fa fa-plus-square-o'
}"
:data="dictData.tableData"
@cell-dblclick="cellDBLClickEvent"
>
<vxe-table-column
tree-node
field="name"
title="字典名称"
></vxe-table-column>
<vxe-table-column title="字典类型">
<template #default="{ row }">
<el-tooltip
effect="dark"
:content="'双击复制:' + row.model"
placement="right"
>
<span class="text-model">{{ row.model }}</span>
</el-tooltip>
</template>
</vxe-table-column>
<vxe-table-column title="操作" width="330" fixed="right">
<template #default="{ row }">
<vxe-button type="text" icon="el-icon-edit" @click="onEdit(row)"
>编辑</vxe-button
>
<vxe-button
type="text"
icon="el-icon-circle-plus-outline"
@click="onAddChild(row)"
>新增子类型</vxe-button
>
<vxe-button
v-show="row.model"
type="text"
icon="el-icon-setting"
@click="onDeploy(row)"
>字典配置</vxe-button
>
<vxe-button type="text" icon="el-icon-delete" @click="confirmEvent"
>删除</vxe-button
>
</template>
</vxe-table-column>
</vxe-table>
<!-- 修改添加弹框 -->
<vxe-modal
resize
width="450"
v-model="dictData.showEdit"
:title="dictData.selectRow ? '编辑' : '新增'"
:loading="dictData.submitLoading"
@hide="$refs.xForm.reset()"
>
<template #default>
<vxe-form
ref="xForm"
:data="dictData.formData"
:items="dictData.formItems"
title-align="right"
title-width="100"
@submit="submitEvent"
></vxe-form>
</template>
</vxe-modal>
<Config :drawer="drawer" drawTitle="字典列表" @handleClose="handleClose" />
</div>
</template>
<style lang="scss" scoped> <style lang="scss" scoped>
.dict-container { .dict-container {
margin: 10px; margin: 10px;

View File

@ -1,13 +1,7 @@
<template> <script setup lang="ts">
<vxe-grid v-bind="gridOptions" style="width: 98%"></vxe-grid>
</template>
<script lang="ts">
import { reactive } from "vue"; import { reactive } from "vue";
import { VxeGridProps } from "vxe-table"; import { VxeGridProps } from "vxe-table";
export default {
name: "user",
setup() {
const gridOptions = reactive({ const gridOptions = reactive({
border: true, border: true,
resizable: true, resizable: true,
@ -241,12 +235,8 @@ export default {
} }
] ]
} as VxeGridProps); } as VxeGridProps);
return {
gridOptions
};
}
};
</script> </script>
<style scoped></style> <template>
<vxe-grid v-bind="gridOptions" style="width: 98%"></vxe-grid>
</template>

View File

@ -1,49 +1,17 @@
<template> <script setup lang="ts">
<div class="welcome">
<el-affix>
<div class="top-content">
<div class="left-mark">
<img
src="https://avatars.githubusercontent.com/u/44761321?s=400&u=30907819abd29bb3779bc247910873e7c7f7c12f&v=4"
title="直达仓库地址"
alt
@click="openDepot"
/>
<span>{{ greetings }}</span>
</div>
<Flop v-if="!mobile" />
</div>
</el-affix>
<!-- 图表 -->
<el-card class="box-card">
<el-skeleton style="height: 50vh" :rows="8" :loading="loading" animated>
<template #default>
<div id="brokenLine"></div>
</template>
</el-skeleton>
</el-card>
</div>
</template>
<script lang="ts">
import Flop from "/@/components/ReFlop"; import Flop from "/@/components/ReFlop";
import { ref, computed, onMounted, nextTick } from "vue"; import { ref, computed, onMounted, nextTick } from "vue";
import { deviceDetection } from "/@/utils/deviceDetection"; import { deviceDetection } from "/@/utils/deviceDetection";
import { useEventListener, tryOnUnmounted, useTimeoutFn } from "@vueuse/core"; import { useEventListener, tryOnUnmounted, useTimeoutFn } from "@vueuse/core";
import { echartsJson } from "/@/api/mock"; import { echartsJson } from "/@/api/mock";
import echarts from "/@/plugins/echarts"; import echarts from "/@/plugins/echarts";
import { ECharts } from "echarts";
let brokenLine: any = null; //线 //线
export default { let brokenLine: ECharts;
name: "welcome", let mobile = ref<boolean>(deviceDetection());
components: {
Flop
},
setup() {
let mobile = ref(deviceDetection());
let date: Date = new Date(); let date: Date = new Date();
let loading = ref(true); let loading = ref<boolean>(true);
setTimeout(() => { setTimeout(() => {
loading.value = !loading.value; loading.value = !loading.value;
@ -65,6 +33,7 @@ export default {
function initbrokenLine() { function initbrokenLine() {
const lineRefDom = document.getElementById("brokenLine"); const lineRefDom = document.getElementById("brokenLine");
if (!lineRefDom) return; if (!lineRefDom) return;
// @ts-ignore
brokenLine = echarts.init(lineRefDom); brokenLine = echarts.init(lineRefDom);
brokenLine.clear(); // brokenLine.clear(); //
@ -194,17 +163,36 @@ export default {
brokenLine.dispose(); brokenLine.dispose();
brokenLine = null; brokenLine = null;
}); });
return {
greetings,
mobile,
loading,
openDepot
};
}
};
</script> </script>
<template>
<div class="welcome">
<el-affix>
<div class="top-content">
<div class="left-mark">
<img
src="https://avatars.githubusercontent.com/u/44761321?s=400&u=30907819abd29bb3779bc247910873e7c7f7c12f&v=4"
title="直达仓库地址"
alt
@click="openDepot"
/>
<span>{{ greetings }}</span>
</div>
<Flop v-if="!mobile" />
</div>
</el-affix>
<!-- 图表 -->
<el-card class="box-card">
<el-skeleton style="height: 50vh" :rows="8" :loading="loading" animated>
<template #default>
<div id="brokenLine"></div>
</template>
</el-skeleton>
</el-card>
</div>
</template>
<style lang="scss" scoped> <style lang="scss" scoped>
.welcome { .welcome {
width: 100%; width: 100%;

View File

@ -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
View File

@ -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
View File

@ -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]>;
};

View File

@ -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==