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,3 +1,52 @@
<script setup lang="ts">
import { ref, watch, Ref } from "vue";
import { useRoute, useRouter, RouteLocationMatched } from "vue-router";
const levelList: Ref<RouteLocationMatched[]> = ref([]);
const route = useRoute();
const router = useRouter();
const isDashboard = (route: RouteLocationMatched): boolean | string => {
const name = route && (route.name as string);
if (!name) {
return false;
}
return name.trim().toLocaleLowerCase() === "welcome".toLocaleLowerCase();
};
const getBreadcrumb = (): void => {
let matched = route.matched.filter(item => item.meta && item.meta.title);
const first = matched[0];
if (!isDashboard(first)) {
matched = [
{
path: "/welcome",
meta: { title: "message.hshome" }
} as unknown as RouteLocationMatched
].concat(matched);
}
levelList.value = matched.filter(
item => item.meta && item.meta.title && item.meta.breadcrumb !== false
);
};
getBreadcrumb();
watch(
() => route.path,
() => getBreadcrumb()
);
const handleLink = (item: RouteLocationMatched): any => {
const { redirect, path } = item;
if (redirect) {
router.push(redirect.toString());
return;
}
router.push(path);
};
</script>
<template> <template>
<el-breadcrumb class="app-breadcrumb" separator="/"> <el-breadcrumb class="app-breadcrumb" separator="/">
<transition-group appear name="breadcrumb"> <transition-group appear name="breadcrumb">
@ -15,62 +64,6 @@
</el-breadcrumb> </el-breadcrumb>
</template> </template>
<script lang="ts">
import { ref, defineComponent, watch, Ref } from "vue";
import { useRoute, useRouter, RouteLocationMatched } from "vue-router";
export default defineComponent({
name: "ReBreadCrumb",
setup() {
const levelList: Ref<RouteLocationMatched[]> = ref([]);
const route = useRoute();
const router = useRouter();
const isDashboard = (route: RouteLocationMatched): boolean | string => {
const name = route && (route.name as string);
if (!name) {
return false;
}
return name.trim().toLocaleLowerCase() === "welcome".toLocaleLowerCase();
};
const getBreadcrumb = (): void => {
let matched = route.matched.filter(item => item.meta && item.meta.title);
const first = matched[0];
if (!isDashboard(first)) {
matched = [
{
path: "/welcome",
meta: { title: "message.hshome" }
} as unknown as RouteLocationMatched
].concat(matched);
}
levelList.value = matched.filter(
item => item.meta && item.meta.title && item.meta.breadcrumb !== false
);
};
getBreadcrumb();
watch(
() => route.path,
() => getBreadcrumb()
);
const handleLink = (item: RouteLocationMatched): any => {
const { redirect, path } = item;
if (redirect) {
router.push(redirect.toString());
return;
}
router.push(path);
};
return { levelList, handleLink };
}
});
</script>
<style lang="scss" scoped> <style lang="scss" scoped>
.app-breadcrumb.el-breadcrumb { .app-breadcrumb.el-breadcrumb {
display: inline-block; display: inline-block;

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,60 +1,29 @@
<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"; let timer = ref(null);
export default { let flipObjs = ref([]);
name: "Flop",
components: {
flippers
},
setup() {
let timer = ref(null);
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 = () => {
let now = new Date(); let now = new Date();
let nowTimeStr = formatDate(new Date(now.getTime()), "hhiiss"); let nowTimeStr = formatDate(new Date(now.getTime()), "hhiiss");
for (let i = 0; i < flipObjs.value.length; i++) { for (let i = 0; i < flipObjs.value.length; i++) {
flipObjs?.value[i]?.setFront(nowTimeStr[i]); flipObjs?.value[i]?.setFront(nowTimeStr[i]);
} }
}; };
// //
const run = () => { const run = () => {
timer.value = setInterval(() => { timer.value = setInterval(() => {
// //
let now = new Date(); let now = new Date();
@ -67,10 +36,10 @@ export default {
flipObjs?.value[i]?.flipDown(nowTimeStr[i], nextTimeStr[i]); flipObjs?.value[i]?.flipDown(nowTimeStr[i], nextTimeStr[i]);
} }
}, 1000); }, 1000);
}; };
// //
const formatDate = (date: Date, dateFormat: string) => { const formatDate = (date: Date, dateFormat: string) => {
/* y /* y
* 例如yyyy => 2019 * 例如yyyy => 2019
yy => 19 yy => 19
@ -106,14 +75,14 @@ export default {
} }
} }
return dateFormat; return dateFormat;
}; };
// //
const padLeftZero = (str: string | any[]) => { const padLeftZero = (str: string | any[]) => {
return ("00" + str).substr(str.length); return ("00" + str).substr(str.length);
}; };
nextTick(() => { nextTick(() => {
flipObjs.value = [ flipObjs.value = [
unref(flipperHour1), unref(flipperHour1),
unref(flipperHour2), unref(flipperHour2),
@ -125,33 +94,29 @@ export default {
init(); init();
run(); run();
}); });
onUnmounted(() => { onUnmounted(() => {
if (timer.value) { if (timer.value) {
clearInterval(timer.value); clearInterval(timer.value);
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,54 +1,26 @@
<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>(), {
let titleLists = ref([ lf: null
});
const emit = defineEmits<{
(e: "catData"): void;
}>();
const controlButton3 = templateRef<HTMLElement | any>("controlButton3", null);
const controlButton4 = templateRef<HTMLElement | any>("controlButton4", null);
let focusIndex = ref<Number>(-1);
let titleLists = ref([
{ {
icon: "icon-zoom-out-hs", icon: "icon-zoom-out-hs",
text: "缩小", text: "缩小",
@ -84,9 +56,9 @@ export default defineComponent({
text: "查看数据", text: "查看数据",
disabled: false disabled: false
} }
]); ]);
const onControl = (item, key) => { const onControl = (item, key) => {
["zoom", "zoom", "resetZoom", "undo", "redo", "getSnapshot"].forEach( ["zoom", "zoom", "resetZoom", "undo", "redo", "getSnapshot"].forEach(
(v, i) => { (v, i) => {
let domControl = props.lf; let domControl = props.lf;
@ -101,31 +73,48 @@ export default defineComponent({
} }
} }
); );
}; };
const onEnter = key => { const onEnter = key => {
focusIndex.value = key; focusIndex.value = key;
}; };
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: { </style>
isActive: {
type: Boolean,
default: false
}
},
emits: ["toggleClick"],
setup(props, ctx) {
const toggleClick = () => {
ctx.emit("toggleClick");
};
return { toggleClick };
}
});
</script>
<style scoped> <style scoped>
.hamburger { .hamburger {
@ -44,7 +46,7 @@ export default defineComponent({
height: 20px; height: 20px;
} }
.hamburger.is-active { .is-active {
transform: rotate(180deg); transform: rotate(180deg);
} }
</style> </style>

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,36 +19,27 @@ export interface mapInter {
loading: boolean; loading: boolean;
} }
export default defineComponent({ let MarkerCluster;
name: "Amap", let map: MapConfigureInter;
setup() {
const instance = getCurrentInstance();
let map: MapConfigureInter;
const mapSet: mapInter = reactive({ const instance = getCurrentInstance();
const mapSet: mapInter = reactive({
loading: deviceDetection() ? false : true loading: deviceDetection() ? false : true
}); });
// () // ()
const complete = (): void => { const complete = (): void => {
if (map) { if (map) {
map.on("complete", () => { map.on("complete", () => {
mapSet.loading = false; mapSet.loading = false;
}); });
} }
}; };
// onBeforeMount(() => {
const destroyMap = (): void => {
if (map) {
map.destroy() && map.clearEvents("click");
}
};
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 }) => {
@ -145,18 +111,27 @@ export default defineComponent({
mapSet.loading = false; mapSet.loading = false;
throw "地图加载失败,请重新加载"; throw "地图加载失败,请重新加载";
}); });
}); });
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,77 +11,68 @@ 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);
// single const emit = defineEmits<{
let singleWaitTime = null; (e: "scrollEnd"): void;
// moveanimationFrame }>();
let reqFrame = null;
let startPos = null;
//touchStartposY
let startPosY = null;
//touchStartposX
let startPosX = null;
// mouseenter mouseleave scrollMove()
let isHover = false;
let ease = "ease-in";
// eslint-disable-next-line vue/no-setup-props-destructure let xPos = ref<number>(0);
let { classOption } = props; 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
let singleWaitTime = null;
// moveanimationFrame
let reqFrame = null;
let startPos = null;
//touchStartposY
let startPosY = null;
//touchStartposX
let startPosX = null;
// mouseenter mouseleave scrollMove()
let isHover = false;
let ease = "ease-in";
if (classOption["key"] === undefined) { // eslint-disable-next-line vue/no-setup-props-destructure
let { classOption } = props;
if (classOption["key"] === undefined) {
classOption["key"] = 0; classOption["key"] = 0;
} }
const wrap = templateRef<HTMLElement | null>( const wrap = templateRef<HTMLElement | null>(`wrap${classOption["key"]}`, null);
`wrap${classOption["key"]}`, const slotList = templateRef<HTMLElement | null>(
null
);
const slotList = templateRef<HTMLElement | null>(
`slotList${classOption["key"]}`, `slotList${classOption["key"]}`,
null null
); );
const realBox = templateRef<HTMLElement | null>( const realBox = templateRef<HTMLElement | null>(
`realBox${classOption["key"]}`, `realBox${classOption["key"]}`,
null null
); );
let leftSwitchState = computed(() => { let leftSwitchState = computed(() => {
return unref(xPos) < 0; return unref(xPos) < 0;
}); });
let rightSwitchState = computed(() => { let rightSwitchState = computed(() => {
return Math.abs(unref(xPos)) < unref(realBoxWidth) - unref(width); return Math.abs(unref(xPos)) < unref(realBoxWidth) - unref(width);
}); });
let defaultOption = computed(() => { let defaultOption = computed(() => {
return { return {
// //
step: 1, step: 1,
@ -143,30 +99,30 @@ export default defineComponent({
// singleWidth/singleHeight rem // singleWidth/singleHeight rem
isSingleRemUnit: false isSingleRemUnit: false
}; };
}); });
let options = computed(() => { let options = computed(() => {
// @ts-ignore // @ts-ignore
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;
}); });
let rightSwitchClass = computed(() => { let rightSwitchClass = computed(() => {
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`,
transform: "translate(-100%,-50%)" transform: "translate(-100%,-50%)"
}; };
}); });
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 ${
@ -174,68 +130,65 @@ export default defineComponent({
}px`, }px`,
transform: "translateY(-50%)" transform: "translateY(-50%)"
}; };
}); });
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" };
}); });
let pos = computed(() => { let pos = computed(() => {
return { return {
transform: `translate(${unref(xPos)}px,${unref(yPos)}px)`, transform: `translate(${unref(xPos)}px,${unref(yPos)}px)`,
transition: `all ${ease} ${unref(delay)}ms`, transition: `all ${ease} ${unref(delay)}ms`,
overflow: "hidden" overflow: "hidden"
}; };
}); });
let navigation = computed(() => { let navigation = computed(() => {
return unref(options).navigation; return unref(options).navigation;
}); });
let autoPlay = computed(() => { let autoPlay = computed(() => {
if (unref(navigation)) return false; if (unref(navigation)) return false;
return unref(options).autoPlay; return unref(options).autoPlay;
}); });
let scrollSwitch = computed(() => { let scrollSwitch = computed(() => {
// props . // props .
return props.data.length >= unref(options).limitMoveNum; return props.data.length >= unref(options).limitMoveNum;
}); });
let hoverStopSwitch = computed(() => { let hoverStopSwitch = computed(() => {
return unref(options).hoverStop && unref(autoPlay) && unref(scrollSwitch); return unref(options).hoverStop && unref(autoPlay) && unref(scrollSwitch);
}); });
let canTouchScroll = computed(() => { let canTouchScroll = computed(() => {
return unref(options).openTouch; return unref(options).openTouch;
}); });
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;
}); });
let realSingleStopWidth = computed(() => { let realSingleStopWidth = computed(() => {
return unref(options).singleWidth * unref(baseFontSize); return unref(options).singleWidth * unref(baseFontSize);
}); });
let realSingleStopHeight = computed(() => { let realSingleStopHeight = computed(() => {
return unref(options).singleHeight * unref(baseFontSize); return unref(options).singleHeight * unref(baseFontSize);
}); });
let step = computed(() => { let step = computed(() => {
let singleStep; let singleStep;
let step = unref(options).step; let step = unref(options).step;
if (unref(isHorizontal)) { if (unref(isHorizontal)) {
@ -247,16 +200,16 @@ export default defineComponent({
throw "如果设置了单步滚动step需是单步大小的约数否则无法保证单步滚动结束的位置是否准确"; throw "如果设置了单步滚动step需是单步大小的约数否则无法保证单步滚动结束的位置是否准确";
} }
return step; return step;
}); });
function reset() { function reset() {
xPos.value = 0; xPos.value = 0;
yPos.value = 0; yPos.value = 0;
scrollCancle(); scrollCancle();
scrollInitMove(); scrollInitMove();
} }
function leftSwitchClick() { function leftSwitchClick() {
if (!unref(leftSwitchState)) return; if (!unref(leftSwitchState)) return;
// //
if (Math.abs(unref(xPos)) < unref(options).switchSingleStep) { if (Math.abs(unref(xPos)) < unref(options).switchSingleStep) {
@ -264,9 +217,9 @@ export default defineComponent({
return; return;
} }
xPos.value += unref(options).switchSingleStep; xPos.value += unref(options).switchSingleStep;
} }
function rightSwitchClick() { function rightSwitchClick() {
if (!unref(rightSwitchState)) return; if (!unref(rightSwitchState)) return;
// //
if ( if (
@ -277,13 +230,13 @@ export default defineComponent({
return; return;
} }
xPos.value -= unref(options).switchSingleStep; xPos.value -= unref(options).switchSingleStep;
} }
function scrollCancle() { function scrollCancle() {
cancelAnimationFrame(reqFrame || ""); cancelAnimationFrame(reqFrame || "");
} }
function touchStart(e) { function touchStart(e) {
if (!unref(canTouchScroll)) return; if (!unref(canTouchScroll)) return;
let timer; let timer;
//touchestouchtouch //touchestouchtouch
@ -306,9 +259,9 @@ export default defineComponent({
} else { } else {
scrollCancle(); scrollCancle();
} }
} }
function touchMove(e) { function touchMove(e) {
//touchmove //touchmove
if ( if (
!unref(canTouchScroll) || !unref(canTouchScroll) ||
@ -339,9 +292,9 @@ export default defineComponent({
// && // &&
xPos.value = startPosX + endPos.x; xPos.value = startPosX + endPos.x;
} }
} }
function touchEnd() { function touchEnd() {
if (!unref(canTouchScroll)) return; if (!unref(canTouchScroll)) return;
let timer; let timer;
const direction = unref(options).direction; const direction = unref(options).direction;
@ -362,17 +315,17 @@ export default defineComponent({
delay.value = 0; delay.value = 0;
scrollMove(); scrollMove();
}, unref(delay)); }, unref(delay));
} }
function enter() { function enter() {
if (unref(hoverStopSwitch)) scrollStopMove(); if (unref(hoverStopSwitch)) scrollStopMove();
} }
function leave() { function leave() {
if (unref(hoverStopSwitch)) scrollStartMove(); if (unref(hoverStopSwitch)) scrollStartMove();
} }
function scrollMove() { function scrollMove() {
// scrollMove() // scrollMove()
if (isHover) return; if (isHover) return;
//move touchMove //move touchMove
@ -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();
@ -442,9 +389,9 @@ export default defineComponent({
scrollMove(); scrollMove();
} }
}); });
} }
function scrollInitMove() { function scrollInitMove() {
nextTick(() => { nextTick(() => {
const { switchDelay } = unref(options); const { switchDelay } = unref(options);
//copy //copy
@ -485,39 +432,24 @@ export default defineComponent({
yPos.value = xPos.value = 0; yPos.value = xPos.value = 0;
} }
}); });
} }
function scrollStartMove() { function scrollStartMove() {
//scrollMove //scrollMove
isHover = false; isHover = false;
scrollMove(); scrollMove();
} }
function scrollStopMove() { function scrollStopMove() {
//scrollMove //scrollMove
isHover = true; isHover = true;
// hover, // hover,
if (singleWaitTime) clearTimeout(singleWaitTime); if (singleWaitTime) clearTimeout(singleWaitTime);
scrollCancle(); scrollCancle();
} }
// watchEffect(() => { //
// const watchData = data; function wheel(e) {
// if (!watchData) return;
// nextTick(() => {
// reset();
// });
// const watchAutoPlay = unref(autoPlay);
// if (watchAutoPlay) {
// reset();
// } else {
// scrollStopMove();
// }
// });
//
function wheel(e) {
e.preventDefault(); e.preventDefault();
if ( if (
unref(options).direction === "left" || unref(options).direction === "left" ||
@ -527,59 +459,69 @@ export default defineComponent({
useDebounceFn(() => { useDebounceFn(() => {
e.deltaY > 0 ? (yPos.value -= step.value) : (yPos.value += step.value); e.deltaY > 0 ? (yPos.value -= step.value) : (yPos.value += step.value);
}, 50)(); }, 50)();
} }
tryOnMounted(() => { // watchEffect(() => {
// const watchData = data;
// if (!watchData) return;
// nextTick(() => {
// reset();
// });
// const watchAutoPlay = unref(autoPlay);
// if (watchAutoPlay) {
// reset();
// } else {
// scrollStopMove();
// }
// });
tryOnMounted(() => {
scrollInitMove(); scrollInitMove();
}); });
tryOnUnmounted(() => { tryOnUnmounted(() => {
scrollCancle(); scrollCancle();
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", const url = ref(
setup() {
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,10 +6,7 @@ import playbackRate from "xgplayer/dist/controls/playbackRate";
import screenShot from "xgplayer/dist/controls/screenShot"; import screenShot from "xgplayer/dist/controls/screenShot";
import { deviceDetection } from "/@/utils/deviceDetection"; import { deviceDetection } from "/@/utils/deviceDetection";
export default { onMounted(() => {
name: "reVideo",
setup() {
onMounted(() => {
new Player({ new Player({
id: "mse", id: "mse",
autoplay: false, autoplay: false,
@ -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,47 +1,40 @@
<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(unref(editor));
instance = new WangEditor(editor.value);
Object.assign(instance.config, { Object.assign(instance.config, {
onchange() { onchange() {
content.html = instance.txt.html(); html.value = instance.txt.html();
} }
}); });
instance.create(); instance.create();
}); });
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,3 +1,61 @@
<script setup lang="ts">
import { ref, unref, onMounted } from "vue";
import LogicFlow from "@logicflow/core";
import { Snapshot, BpmnElement, Menu } from "@logicflow/extension";
import "@logicflow/core/dist/style/index.css";
import "@logicflow/extension/lib/style/index.css";
import { Control, NodePanel, DataDialog } from "/@/components/ReFlowChart";
import { toLogicflowData } from "/@/components/ReFlowChart/src/adpterForTurbo";
import { BpmnNode } from "/@/components/ReFlowChart/src/config";
import demoData from "./dataTurbo.json";
let lf = ref(null);
let graphData = ref(null);
let dataVisible = ref<boolean>(false);
let config = ref({
grid: true,
background: {
color: "#f7f9ff"
},
keyboard: {
enabled: true
}
});
let nodeList = BpmnNode;
function initLf() {
//
LogicFlow.use(Snapshot);
// 使bpmnbpmnturbo使
LogicFlow.use(BpmnElement);
//
LogicFlow.use(Menu);
const domLf = new LogicFlow({
...unref(config),
container: document.querySelector("#LF-Turbo")
});
lf.value = domLf;
// bpmn:sequenceFlow
unref(lf).setDefaultEdgeType("bpmn:sequenceFlow");
onRender();
}
function onRender() {
// TurboLogicFlow
const lFData = toLogicflowData(demoData);
lf.value.render(lFData);
}
function catData() {
graphData.value = unref(lf).getGraphData();
dataVisible.value = true;
}
onMounted(() => {
initLf();
});
</script>
<template> <template>
<div class="logic-flow-view"> <div class="logic-flow-view">
<!-- 辅助工具栏 --> <!-- 辅助工具栏 -->
@ -19,80 +77,6 @@
</div> </div>
</template> </template>
<script lang="ts">
import { ref, unref, onMounted } from "vue";
import LogicFlow from "@logicflow/core";
import { Snapshot, BpmnElement, Menu } from "@logicflow/extension";
import "@logicflow/core/dist/style/index.css";
import "@logicflow/extension/lib/style/index.css";
import { Control, NodePanel, DataDialog } from "/@/components/ReFlowChart";
import { toLogicflowData } from "/@/components/ReFlowChart/src/adpterForTurbo";
import { BpmnNode } from "/@/components/ReFlowChart/src/config";
import demoData from "./dataTurbo.json";
export default {
name: "reFlowChart",
components: { NodePanel, Control, DataDialog },
setup() {
// eslint-disable-next-line no-undef
let lf = ref<ElRef>(null);
let graphData = ref(null);
let dataVisible = ref(false);
let config = ref({
grid: true,
background: {
color: "#f7f9ff"
},
keyboard: {
enabled: true
}
});
let nodeList = BpmnNode;
function initLf() {
//
LogicFlow.use(Snapshot);
// 使bpmnbpmnturbo使
LogicFlow.use(BpmnElement);
//
LogicFlow.use(Menu);
const domLf = new LogicFlow({
...unref(config),
container: document.querySelector("#LF-Turbo")
});
lf.value = domLf;
// bpmn:sequenceFlow
unref(lf).setDefaultEdgeType("bpmn:sequenceFlow");
onRender();
}
function onRender() {
// TurboLogicFlow
const lFData = toLogicflowData(demoData);
lf.value.render(lFData);
}
function catData() {
graphData.value = unref(lf).getGraphData();
dataVisible.value = true;
}
onMounted(() => {
initLf();
});
return {
lf,
graphData,
dataVisible,
config,
nodeList,
catData
};
}
};
</script>
<style scoped> <style scoped>
#LF-Turbo { #LF-Turbo {
width: 100vw; width: 100vw;

View File

@ -1,48 +1,33 @@
<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();
const refreshGetVerify = async () => {
//
const refreshGetVerify = async () => {
let { svg } = await getVerify(); let { svg } = await getVerify();
contextInfo.svg = svg; contextInfo.svg = svg;
}; };
const contextInfo: ContextProps = reactive({ const contextInfo: ContextProps = reactive({
userName: "", userName: "",
passWord: "", passWord: "",
verify: null, verify: null,
svg: null svg: null
}); });
const toPage = (info: Object): void => { const toPage = (info: Object): void => {
storageSession.setItem("info", info); storageSession.setItem("info", info);
router.push("/"); router.push("/");
}; };
// //
const onLogin = async () => { const onLogin = async () => {
let { userName, passWord, verify } = contextInfo; let { userName, passWord, verify } = contextInfo;
let { code, info, accessToken } = await getLogin({ let { code, info, accessToken } = await getLogin({
username: userName, username: userName,
@ -56,23 +41,23 @@ export default {
accessToken accessToken
}) })
: warnMessage(info); : warnMessage(info);
};
const refreshVerify = (): void => {
refreshGetVerify();
};
onBeforeMount(() => {
// refreshGetVerify();
});
return {
contextInfo,
onLogin,
router,
toPage,
refreshVerify
};
}
}; };
const refreshVerify = (): void => {
refreshGetVerify();
};
onBeforeMount(() => {
// refreshGetVerify();
});
</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,25 +1,10 @@
<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",
setup() {
let purview: string = ref(storageSession.getItem("info").username);
function changRole() { let purview = ref<string>(storageSession.getItem("info").username);
function changRole() {
if (unref(purview) === "admin") { if (unref(purview) === "admin") {
storageSession.setItem("info", { storageSession.setItem("info", {
username: "test", username: "test",
@ -33,12 +18,18 @@ 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,26 +1,20 @@
<script setup lang="ts">
import { unref } from "vue";
import { useRouter } from "vue-router";
const { currentRoute, replace } = useRouter();
const { params, query } = unref(currentRoute);
const { path } = params;
const _path = Array.isArray(path) ? path.join("/") : path;
replace({
path: "/" + _path,
query
});
</script>
<template> <template>
<div></div> <div></div>
</template> </template>
<script lang="ts">
import { defineComponent, unref } from "vue";
import { useRouter } from "vue-router";
export default defineComponent({
name: "redirect",
setup() {
const { currentRoute, replace } = useRouter();
const { params, query } = unref(currentRoute);
const { path } = params;
const _path = Array.isArray(path) ? path.join("/") : path;
replace({
path: "/" + _path,
query
});
return {};
}
});
</script>

View File

@ -1,42 +1,27 @@
<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();
const refreshGetVerify = async () => {
//
const refreshGetVerify = async () => {
let { svg } = await getVerify(); let { svg } = await getVerify();
contextInfo.svg = svg; contextInfo.svg = svg;
}; };
const contextInfo: ContextProps = reactive({ const contextInfo: ContextProps = reactive({
userName: "", userName: "",
passWord: "", passWord: "",
verify: null, verify: null,
svg: null svg: null
}); });
// //
const onRegist = async () => { const onRegist = async () => {
let { userName, passWord, verify } = contextInfo; let { userName, passWord, verify } = contextInfo;
let { code, info } = await getRegist({ let { code, info } = await getRegist({
username: userName, username: userName,
@ -46,22 +31,23 @@ export default {
code === 0 code === 0
? successMessage(info) && router.push("/login") ? successMessage(info) && router.push("/login")
: warnMessage(info); : warnMessage(info);
};
const refreshVerify = (): void => {
refreshGetVerify();
};
onBeforeMount(() => {
// refreshGetVerify();
});
return {
contextInfo,
onRegist,
router,
refreshVerify
};
}
}; };
const refreshVerify = (): void => {
refreshGetVerify();
};
onBeforeMount(() => {
// refreshGetVerify();
});
</script> </script>
<template>
<div class="register">
<info
:ruleForm="contextInfo"
@on-behavior="onRegist"
@refreshVerify="refreshVerify"
/>
</div>
</template>

View File

@ -1,3 +1,79 @@
<script setup lang="ts">
import { reactive } from "vue";
import { VxeTableEvents } from "vxe-table";
import { templateRef } from "@vueuse/core";
interface Props {
drawer: boolean;
drawTitle?: string;
direction?: string;
}
withDefaults(defineProps<Props>(), {
drawer: false,
drawTitle: "",
direction: "rtl"
});
const emit = defineEmits<{
(e: "handleClose"): void;
}>();
const xTable = templateRef<any>("xTable", null);
const configData = reactive({
tableData: [
{
name: "禁用",
dataval: "0"
},
{
name: "启用",
dataval: "1"
}
],
isAllChecked: false,
isIndeterminate: false,
selectRecords: [] as any[],
tablePage: {
total: 0,
currentPage: 1,
pageSize: 10
}
});
//
function handleClose() {
configData.isAllChecked = false;
configData.isIndeterminate = false;
emit("handleClose");
}
function editConfig(row) {
console.log("editConfig", row);
}
function delConfig(row) {
console.log("delConfig", row);
}
const changeAllEvent = () => {
setTimeout(() => {
console.log(xTable);
}, 1000);
const $table = xTable.value;
$table.setAllCheckboxRow(configData.isAllChecked);
configData.selectRecords = $table.getCheckboxRecords();
};
const checkboxChangeEvent: VxeTableEvents.CheckboxChange = ({ records }) => {
const $table = xTable.value;
configData.isAllChecked = $table.isAllCheckboxChecked();
configData.isIndeterminate = $table.isCheckboxIndeterminate();
configData.selectRecords = records;
};
</script>
<template> <template>
<div class="config"> <div class="config">
<el-drawer <el-drawer
@ -14,7 +90,7 @@
<vxe-table <vxe-table
ref="xTable" ref="xTable"
border border
:data="tableData" :data="configData.tableData"
@checkbox-change="checkboxChangeEvent" @checkbox-change="checkboxChangeEvent"
@checkbox-all="checkboxChangeEvent" @checkbox-all="checkboxChangeEvent"
> >
@ -40,9 +116,9 @@
</vxe-table> </vxe-table>
<vxe-pager <vxe-pager
perfect perfect
v-model:current-page="tablePage.currentPage" v-model:current-page="configData.tablePage.currentPage"
v-model:page-size="tablePage.pageSize" v-model:page-size="configData.tablePage.pageSize"
:total="tablePage.total" :total="configData.tablePage.total"
:layouts="[ :layouts="[
'PrevJump', 'PrevJump',
'PrevPage', 'PrevPage',
@ -57,12 +133,12 @@
<template #left> <template #left>
<span class="page-left"> <span class="page-left">
<vxe-checkbox <vxe-checkbox
v-model="isAllChecked" v-model="configData.isAllChecked"
:indeterminate="isIndeterminate" :indeterminate="configData.isIndeterminate"
@change="changeAllEvent" @change="changeAllEvent"
></vxe-checkbox> ></vxe-checkbox>
<span class="select-count" <span class="select-count"
>已选中{{ selectRecords.length }}</span >已选中{{ configData.selectRecords.length }}</span
> >
<vxe-button size="small">{{ $t("message.hsdelete") }}</vxe-button> <vxe-button size="small">{{ $t("message.hsdelete") }}</vxe-button>
</span> </span>
@ -73,98 +149,6 @@
</div> </div>
</template> </template>
<script lang="ts">
import { defineComponent, reactive, toRefs } from "vue";
import { propTypes } from "/@/utils/propTypes";
import { VxeTableEvents } from "vxe-table";
import { templateRef } from "@vueuse/core";
export default defineComponent({
props: {
drawer: propTypes.bool.def(false),
drawTitle: propTypes.string.def(""),
direction: propTypes.string.def("rtl")
},
emits: ["handleClose"],
setup(props, ctx) {
const { emit } = ctx;
const xTable = templateRef<any>("xTable", null);
const configData = reactive({
tableData: [
{
name: "禁用",
dataval: "0"
},
{
name: "启用",
dataval: "1"
}
],
isAllChecked: false,
isIndeterminate: false,
selectRecords: [] as any[],
tablePage: {
total: 0,
currentPage: 1,
pageSize: 10
}
});
//
function handleClose() {
configData.isAllChecked = false;
configData.isIndeterminate = false;
emit("handleClose");
}
function editConfig(row) {
console.log(
"%crow===>>>: ",
"color: MidnightBlue; background: Aquamarine; font-size: 20px;",
row
);
}
function delConfig(row) {
console.log(
"%crow===>>>: ",
"color: MidnightBlue; background: Aquamarine; font-size: 20px;",
row
);
}
const changeAllEvent = () => {
setTimeout(() => {
console.log(xTable);
}, 1000);
const $table = xTable.value;
$table.setAllCheckboxRow(configData.isAllChecked);
configData.selectRecords = $table.getCheckboxRecords();
};
const checkboxChangeEvent: VxeTableEvents.CheckboxChange = ({
records
}) => {
const $table = xTable.value;
configData.isAllChecked = $table.isAllCheckboxChecked();
configData.isIndeterminate = $table.isCheckboxIndeterminate();
configData.selectRecords = records;
};
return {
...toRefs(configData),
handleClose,
editConfig,
delConfig,
changeAllEvent,
checkboxChangeEvent
};
}
});
</script>
<style lang="scss" scoped> <style lang="scss" scoped>
.list { .list {
padding: 10px; padding: 10px;

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,15 +11,12 @@ import {
VxeTableEvents, VxeTableEvents,
VxeFormPropTypes VxeFormPropTypes
} from "vxe-table"; } from "vxe-table";
import Config from "./config.vue"; type onEditNRow = {
name: string;
model: string;
};
export default { const dictData = reactive({
name: "dict",
components: {
Config
},
setup() {
const dictData = reactive({
submitLoading: false, submitLoading: false,
showEdit: false, showEdit: false,
selectRow: null, selectRow: null,
@ -193,17 +80,13 @@ export default {
} }
} }
] as VxeFormPropTypes.Items ] as VxeFormPropTypes.Items
}); });
let originData = cloneDeep(dictData.tableData); let originData = cloneDeep(dictData.tableData);
const xTree = templateRef<HTMLElement | any>("xTree", null); const xTree = templateRef<HTMLElement | any>("xTree", null);
const formatDate = (value: any) => { const handleSearch = () => {
return XEUtils.toDateString(value, "yyyy-MM-dd HH:mm:ss.S");
};
const handleSearch = () => {
const filterName = XEUtils.toValueString(dictData.filterName).trim(); const filterName = XEUtils.toValueString(dictData.filterName).trim();
if (filterName) { if (filterName) {
@ -227,49 +110,45 @@ export default {
} else { } else {
dictData.tableData = originData; dictData.tableData = originData;
} }
}; };
// 100 // 100
const searchEvent = XEUtils.debounce( const searchEvent = XEUtils.debounce(
function () { function () {
handleSearch(); handleSearch();
}, },
100, 100,
{ leading: false, trailing: true } { leading: false, trailing: true }
); );
const confirmEvent = async () => { const confirmEvent = async () => {
const type = await VXETable.modal.confirm("您确定要删除吗?"); const type = await VXETable.modal.confirm("您确定要删除吗?");
(await type) === "confirm" && (await type) === "confirm" &&
VXETable.modal.message({ VXETable.modal.message({
content: "测试数据,不可删除", content: "测试数据,不可删除",
status: "error" status: "error"
}); });
}; };
function commonFn(value, disabled) { function commonFn(value, disabled) {
dictData.selectRow = value; dictData.selectRow = value;
dictData.showEdit = true; dictData.showEdit = true;
dictData.formItems[1].itemRender.props.disabled = disabled; dictData.formItems[1].itemRender.props.disabled = disabled;
} }
// //
function onAdd() { function onAdd() {
commonFn(null, false); commonFn(null, false);
} }
// //
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 : "暂无字典类型"
@ -279,17 +158,17 @@ export default {
// content: "", // content: "",
// status: "error" // status: "error"
// }); // });
} }
// //
const { clipboardRef } = useCopyToClipboard(); const { clipboardRef } = useCopyToClipboard();
const cellDBLClickEvent: VxeTableEvents.CellDblclick = ({ row }) => { const cellDBLClickEvent: VxeTableEvents.CellDblclick = ({ row }) => {
clipboardRef.value = unref(row).model; clipboardRef.value = unref(row).model;
}; };
const xTable = ref({} as VxeTableInstance); const xTable = ref({} as VxeTableInstance);
const submitEvent = () => { const submitEvent = () => {
dictData.submitLoading = true; dictData.submitLoading = true;
setTimeout(() => { setTimeout(() => {
const $table = xTable.value; const $table = xTable.value;
@ -303,35 +182,132 @@ export default {
$table.insert(dictData.formData); $table.insert(dictData.formData);
} }
}, 500); }, 500);
};
let drawer = ref(false);
function onDeploy() {
drawer.value = true;
}
function handleClose() {
drawer.value = false;
}
return {
...toRefs(dictData),
formatDate,
searchEvent,
confirmEvent,
cellDBLClickEvent,
submitEvent,
onEdit,
onAddChild,
onAdd,
onDeploy,
drawer,
handleClose
};
}
}; };
let drawer = ref(false);
function onDeploy(value?: object) {
console.log("onDeploy", value);
drawer.value = true;
}
function handleClose() {
drawer.value = false;
}
</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,14 +1,8 @@
<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", const gridOptions = reactive({
setup() {
const gridOptions = reactive({
border: true, border: true,
resizable: true, resizable: true,
keepSource: true, keepSource: true,
@ -240,13 +234,9 @@ export default {
editRender: { name: "input" } editRender: { name: "input" }
} }
] ]
} 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,58 +1,26 @@
<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: { let date: Date = new Date();
Flop let loading = ref<boolean>(true);
},
setup() {
let mobile = ref(deviceDetection());
let date: Date = new Date();
let loading = ref(true);
setTimeout(() => { setTimeout(() => {
loading.value = !loading.value; loading.value = !loading.value;
nextTick(() => { nextTick(() => {
initbrokenLine(); initbrokenLine();
}); });
}, 500); }, 500);
let greetings = computed(() => { let greetings = computed(() => {
if (date.getHours() >= 0 && date.getHours() < 12) { if (date.getHours() >= 0 && date.getHours() < 12) {
return "上午阳光明媚,祝你薪水翻倍🌞!"; return "上午阳光明媚,祝你薪水翻倍🌞!";
} else if (date.getHours() >= 12 && date.getHours() < 18) { } else if (date.getHours() >= 12 && date.getHours() < 18) {
@ -60,11 +28,12 @@ export default {
} else { } else {
return "折一根天使羽毛,愿拂去您的疲惫烦恼忧伤🌛!"; return "折一根天使羽毛,愿拂去您的疲惫烦恼忧伤🌛!";
} }
}); });
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(); //
@ -172,13 +141,13 @@ export default {
} }
}); });
}); });
} }
const openDepot = (): void => { const openDepot = (): void => {
window.open("https://github.com/xiaoxian521/vue-pure-admin"); window.open("https://github.com/xiaoxian521/vue-pure-admin");
}; };
onMounted(() => { onMounted(() => {
nextTick(() => { nextTick(() => {
useEventListener("resize", () => { useEventListener("resize", () => {
if (!brokenLine) return; if (!brokenLine) return;
@ -187,24 +156,43 @@ export default {
}, 180); }, 180);
}); });
}); });
}); });
tryOnUnmounted(() => { tryOnUnmounted(() => {
if (!brokenLine) return; if (!brokenLine) return;
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==