'admin-21.03.14:此次版本变动大!新增eslint、prettier、vuex模块化、echartsMap等系列优化'

This commit is contained in:
lyt 2021-03-15 12:44:58 +08:00
parent d7c10a3308
commit 8c64de8393
139 changed files with 13669 additions and 13860 deletions

18
.eslintignore Normal file
View File

@ -0,0 +1,18 @@
*.sh
node_modules
lib
*.md
*.scss
*.woff
*.ttf
.vscode
.idea
dist
mock
public
bin
build
config
index.html
src/assets

52
.eslintrc.js Normal file
View File

@ -0,0 +1,52 @@
module.exports = {
env: {
browser: true,
es2021: true,
node: true,
},
parser: 'vue-eslint-parser',
parserOptions: {
ecmaVersion: 12,
parser: '@typescript-eslint/parser',
sourceType: 'module',
},
extends: ['plugin:vue/essential'],
plugins: ['vue', '@typescript-eslint'],
rules: {
// http://eslint.cn/docs/rules/
// https://eslint.vuejs.org/rules/
'@type-eslint/ban-ts-ignore': 'off',
'@type-eslint/explicit-function-return-type': 'off',
'@type-eslint/no-explicit-any': 'off',
'@type-eslint/no-var-requires': 'off',
'@type-eslint/no-empty-function': 'off',
'@type-eslint/no-use-before-define': 'off',
'@type-eslint/ban-ts-comment': 'off',
'@type-eslint/ban-types': 'off',
'@type-eslint/no-non-null-assertion': 'off',
'@type-eslint/explicit-module-boundary-types': 'off',
'vue/custom-event-name-casing': 'off',
'vue/attributes-order': 'off',
'vue/one-component-per-file': 'off',
'vue/html-closing-bracket-newline': 'off',
'vue/max-attributes-per-line': 'off',
'vue/multiline-html-element-content-newline': 'off',
'vue/singleline-html-element-content-newline': 'off',
'vue/attribute-hyphenation': 'off',
'vue/html-self-closing': 'off',
'vue/no-multiple-template-root': 'off',
'vue/require-default-prop': 'off',
'vue/no-v-model-argument': 'off',
'vue/no-arrow-functions-in-watch': 'off',
'vue/no-template-key': 'off',
'vue/no-v-html': 'off',
'no-use-before-define': 'off',
'no-restricted-globals': 'off',
'no-restricted-syntax': 'off',
'generator-star-spacing': 'off',
'no-unreachable': 'off',
'no-multiple-template-root': 'off',
'no-unused-vars': 'error',
'no-v-model-argument': 'off',
},
};

3
.gitignore vendored
View File

@ -2,4 +2,5 @@ node_modules
.DS_Store
dist
dist-ssr
*.local
*.local
.vscode

39
.prettierrc.js Normal file
View File

@ -0,0 +1,39 @@
module.exports = {
// 一行最多多少个字符
printWidth: 150,
// 指定每个缩进级别的空格数
tabWidth: 2,
// 使用制表符而不是空格缩进行
useTabs: true,
// 在语句末尾打印分号
semi: true,
// 使用单引号而不是双引号
singleQuote: true,
// 更改引用对象属性的时间 可选值"<as-needed|consistent|preserve>"
quoteProps: 'as-needed',
// 在JSX中使用单引号而不是双引号
jsxSingleQuote: false,
// 多行时尽可能打印尾随逗号。(例如,单行数组永远不会出现逗号结尾。) 可选值"<none|es5|all>"默认none
trailingComma: 'es5',
// 在对象文字中的括号之间打印空格
bracketSpacing: true,
// jsx 标签的反尖括号需要换行
jsxBracketSameLine: false,
// 在单独的箭头函数参数周围包括括号 always(x) => x \ avoidx => x
arrowParens: 'always',
// 这两个选项可用于格式化以给定字符偏移量(分别包括和不包括)开始和结束的代码
rangeStart: 0,
rangeEnd: Infinity,
// 指定要使用的解析器,不需要写文件开头的 @prettier
requirePragma: false,
// 不需要自动在文件开头插入 @prettier
insertPragma: false,
// 使用默认的折行标准 always\never\preserve
proseWrap: 'preserve',
// 指定HTML文件的全局空格敏感度 css\strict\ignore
htmlWhitespaceSensitivity: 'css',
// Vue文件脚本和样式标签缩进
vueIndentScriptAndStyle: false,
// 换行符使用 lf 结尾是 可选值"<auto|lf|crlf|cr>"
endOfLine: 'lf',
}

View File

@ -1,24 +0,0 @@
// vite 打包相关
import dotenv from 'dotenv'
export interface ViteEnv {
VITE_PORT: number,
VITE_OPEN: boolean,
VITE_PUBLIC_PATH: string
}
export function loadEnv(): ViteEnv {
const env = process.env.NODE_ENV
const ret: any = {}
const envList = [`.env.${env}.local`, `.env.${env}`, '.env.local', '.env', ,]
envList.forEach((e) => { dotenv.config({ path: e }) })
for (const envName of Object.keys(process.env)) {
console.log(envName)
let realName = (process.env as any)[envName].replace(/\\n/g, '\n')
realName = realName === 'true' ? true : realName === 'false' ? false : realName
if (envName === 'VITE_PORT') realName = Number(realName)
if (envName === 'VITE_OPEN') realName = Boolean(realName)
ret[envName] = realName
process.env[envName] = realName
}
return ret
}

View File

@ -1,48 +1,46 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="keywords"
content="vue-admin-wonderful后台管理系统一站式平台模板希望可以帮你完成快速开发。vue2.x、vue2.0、vue2、vue3、vue3.x、vue3.0、
CompositionAPI、typescript、element plus、element、plus、admin、wonderful、wonderful-next、vue-next-admin、vite、快速、高效、
后台模板、后台系统、管理系统"
/>
<meta
name="description"
content="vue-next-admin基于 vue3 + CompositionAPI + typescript + vite + element plus适配手机、平板、pc"
/>
<link rel="icon" href="/favicon.ico" />
<link rel="stylesheet" type="text/css" href="/loading.css" />
<title>vue-next-admin</title>
</head>
<body>
<div id="app">
<div class="loading-next">
<div class="loading-next-box">
<div class="loading-next-animation">
<div class="loading-next-animation-box">
<div></div>
<div></div>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
if (window.location.origin === 'https://lyt-top.gitee.io') {
var _hmt = _hmt || [];
(function () {
var hm = document.createElement('script');
hm.src =
'https://hm.baidu.com/hm.js?d9c8b87d10717013641458b300c552e4';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(hm, s);
})();
}
</script>
<script type="module" src="/src/main.ts"></script>
</body>
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="keywords"
content="vue-next-adminvue-admin-wonderful后台管理系统一站式平台模板希望可以帮你完成快速开发。vue2.xvue2.0vue2vue3vue3.xvue3.0CompositionAPItypescriptelement pluselementplusadminwonderfulwonderful-nextvue-next-adminvitevite-admin快速高效后台模板后台系统管理系统"
/>
<meta
name="description"
content="vue-next-admin基于 vue3 + CompositionAPI + typescript + vite + element plus适配手机、平板、pc 的后台开源免费管理系统模板!"
/>
<link rel="icon" href="/favicon.ico" />
<link rel="stylesheet" type="text/css" href="/loading.css" />
<title>vue-next-admin</title>
</head>
<body>
<div id="app">
<div class="loading-next">
<div class="loading-next-box">
<div class="loading-next-animation">
<div class="loading-next-animation-box">
<div></div>
<div></div>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
if (window.location.origin === 'https://lyt-top.gitee.io') {
var _hmt = _hmt || [];
(function () {
var hm = document.createElement('script');
hm.src = 'https://hm.baidu.com/hm.js?d9c8b87d10717013641458b300c552e4';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(hm, s);
})();
}
</script>
<script type="module" src="/src/main.ts"></script>
<script type="text/javascript" src="https://api.map.baidu.com/api?v=3.0&ak=wsijQt8sLXrCW71YesmispvYHitfG9gv&s=1"></script>
</body>
</html>

View File

@ -1,39 +1,48 @@
{
"name": "vue-next-admin",
"version": "1.0.0",
"scripts": {
"dev": "vite",
"build": "vite build"
},
"dependencies": {
"axios": "^0.21.1",
"clipboard": "^2.0.7",
"countup.js": "^2.0.7",
"cropperjs": "^1.5.11",
"echarts": "^5.0.2",
"echarts-wordcloud": "^2.0.0",
"element-plus": "^1.0.2-beta.33",
"mitt": "^2.1.0",
"nprogress": "^0.2.0",
"screenfull": "^5.1.0",
"sortablejs": "^1.13.0",
"vue": "^3.0.5",
"vue-router": "^4.0.2",
"vuex": "^4.0.0-rc.2",
"wangeditor": "^4.6.8"
},
"devDependencies": {
"@types/axios": "^0.14.0",
"@types/clipboard": "^2.0.1",
"@types/node": "^14.14.32",
"@types/nprogress": "^0.2.0",
"@types/sortablejs": "^1.10.6",
"@vitejs/plugin-vue": "^1.1.5",
"@vue/compiler-sfc": "^3.0.7",
"dotenv": "^8.2.0",
"sass": "^1.32.8",
"sass-loader": "^11.0.1",
"typescript": "^4.2.3",
"vite": "^2.0.5"
}
}
"name": "vue-next-admin",
"version": "1.0.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"lint-fix": "eslint --fix --ext .js --ext .jsx --ext .vue src/"
},
"dependencies": {
"@antv/g6": "^4.2.0",
"axios": "^0.21.1",
"clipboard": "^2.0.8",
"countup.js": "^2.0.7",
"cropperjs": "^1.5.11",
"echarts": "^5.0.2",
"echarts-wordcloud": "^2.0.0",
"element-plus": "^1.0.2-beta.34",
"mitt": "^2.1.0",
"nprogress": "^0.2.0",
"qrcodejs2-fixes": "^0.0.2",
"screenfull": "^5.1.0",
"sortablejs": "^1.13.0",
"vue": "^3.0.5",
"vue-router": "^4.0.2",
"vuex": "^4.0.0-rc.2",
"wangeditor": "^4.6.9"
},
"devDependencies": {
"@types/axios": "^0.14.0",
"@types/clipboard": "^2.0.1",
"@types/node": "^14.14.34",
"@types/nprogress": "^0.2.0",
"@types/sortablejs": "^1.10.6",
"@typescript-eslint/eslint-plugin": "^4.17.0",
"@typescript-eslint/parser": "^4.17.0",
"@vitejs/plugin-vue": "^1.1.5",
"@vue/compiler-sfc": "^3.0.7",
"dotenv": "^8.2.0",
"eslint": "^7.22.0",
"eslint-plugin-vue": "^7.7.0",
"prettier": "^2.2.1",
"sass": "^1.32.8",
"sass-loader": "^11.0.1",
"typescript": "^4.2.3",
"vite": "^2.0.5",
"vue-eslint-parser": "^7.6.0"
}
}

9
shim.d.ts vendored
View File

@ -1,5 +1,4 @@
declare module "*.vue" {
import { Component } from "vue"
const component: Component
export default component
}
declare module '*.vue' {
const component: DefineComponent<{}, {}, any>;
export default component;
}

6
source.d.ts vendored
View File

@ -1,6 +1,8 @@
declare const React: string;
declare module '*.json';
declare module '*.png';
declare module '*.jpg';
declare module '*.scss';
declare module '*.ts';
declare module '*.ts';
declare module 'qrcodejs2-fixes';
declare module 'element-plus';
declare module 'element-plus/lib/locale/lang/zh-cn';

View File

@ -1,68 +1,60 @@
<template>
<router-view v-show="getThemeConfig.lockScreenTime !== 0" />
<LockScreen v-if="getThemeConfig.isLockScreen" />
<Setings ref="setingsRef" v-show="getThemeConfig.lockScreenTime !== 0" />
<router-view v-show="getThemeConfig.lockScreenTime !== 0" />
<LockScreen v-if="getThemeConfig.isLockScreen" />
<Setings ref="setingsRef" v-show="getThemeConfig.lockScreenTime !== 0" />
</template>
<script lang="ts">
import {
computed,
ref,
getCurrentInstance,
onBeforeMount,
onMounted,
onUnmounted,
nextTick,
} from "vue";
import { useStore } from "/@/store/index.ts";
import { getLocal } from "/@/utils/storage.ts";
import setIntroduction from "/@/utils/setIconfont.ts";
import LockScreen from "/@/views/layout/lockScreen/index.vue";
import Setings from "/@/views/layout/navBars/breadcrumb/setings.vue";
export default {
name: "app",
components: { LockScreen, Setings },
setup() {
const { proxy } = getCurrentInstance();
const setingsRef = ref();
const store = useStore();
//
const getThemeConfig = computed(() => {
return store.state.themeConfig;
});
//
const openSetingsDrawer = () => {
setingsRef.value.openDrawer();
};
//
onBeforeMount(() => {
// icon
setIntroduction.cssCdn();
// js
setIntroduction.jsCdn();
});
//
onMounted(() => {
nextTick(() => {
//
proxy.mittBus.on("openSetingsDrawer", () => {
openSetingsDrawer();
});
//
if (getLocal("themeConfig")) {
store.dispatch("setThemeConfig", getLocal("themeConfig"));
document.documentElement.style.cssText = getLocal("themeConfigStyle");
}
});
});
//
onUnmounted(() => {
proxy.mittBus.off("openSetingsDrawer", () => {});
});
return {
setingsRef,
getThemeConfig,
};
},
};
</script>
import { computed, ref, getCurrentInstance, onBeforeMount, onMounted, onUnmounted, nextTick, defineComponent } from 'vue';
import { useStore } from '/@/store/index.ts';
import { getLocal } from '/@/utils/storage.ts';
import setIntroduction from '/@/utils/setIconfont.ts';
import LockScreen from '/@/views/layout/lockScreen/index.vue';
import Setings from '/@/views/layout/navBars/breadcrumb/setings.vue';
export default defineComponent({
name: 'app',
components: { LockScreen, Setings },
setup() {
const { proxy } = getCurrentInstance() as any;
const setingsRef = ref();
const store = useStore();
//
const getThemeConfig = computed(() => {
return store.state.themeConfig.themeConfig;
});
//
const openSetingsDrawer = () => {
setingsRef.value.openDrawer();
};
//
onBeforeMount(() => {
// icon
setIntroduction.cssCdn();
// js
setIntroduction.jsCdn();
});
//
onMounted(() => {
nextTick(() => {
//
proxy.mittBus.on('openSetingsDrawer', () => {
openSetingsDrawer();
});
//
if (getLocal('themeConfig')) {
store.dispatch('themeConfig/setThemeConfig', getLocal('themeConfig'));
document.documentElement.style.cssText = getLocal('themeConfigStyle');
}
});
});
//
onUnmounted(() => {
proxy.mittBus.off('openSetingsDrawer', () => {});
});
return {
setingsRef,
getThemeConfig,
};
},
});
</script>

View File

@ -1,19 +1,19 @@
import request from '/@/utils/request.ts'
import request from '/@/utils/request.ts';
// 用户登录
export function signIn(params: object) {
return request({
url: '/user/signIn',
method: 'post',
data: params
})
return request({
url: '/user/signIn',
method: 'post',
data: params,
});
}
// 用户退出登录
export function signOut(params: object) {
return request({
url: '/user/signOut',
method: 'post',
data: params
})
}
return request({
url: '/user/signOut',
method: 'post',
data: params,
});
}

View File

@ -1,4 +1,4 @@
import request from '/@/utils/request.ts'
import request from '/@/utils/request.ts';
/**
* json https://gitee.com/lyt-top/vue-next-admin-images/raw/master/menu/menu
@ -6,18 +6,18 @@ import request from '/@/utils/request.ts'
*/
// 获取后端动态路由菜单(admin)
export function getMenuAdmin(params?: object) {
return request({
url: '/gitee/lyt-top/vue-next-admin-images/raw/master/menu/adminMenu.json',
method: 'get',
params,
});
return request({
url: '/gitee/lyt-top/vue-next-admin-images/raw/master/menu/adminMenu.json',
method: 'get',
params,
});
}
// 获取后端动态路由菜单(test)
export function getMenuTest(params?: object) {
return request({
url: '/gitee/lyt-top/vue-next-admin-images/raw/master/menu/testMenu.json',
method: 'get',
params,
});
return request({
url: '/gitee/lyt-top/vue-next-admin-images/raw/master/menu/testMenu.json',
method: 'get',
params,
});
}

View File

@ -1,29 +1,29 @@
<template>
<div v-if="getUserAuthBtnList">
<slot />
</div>
<div v-if="getUserAuthBtnList">
<slot />
</div>
</template>
<script lang="ts">
import { computed } from "vue";
import { useStore } from "/@/store/index.ts";
import { computed } from 'vue';
import { useStore } from '/@/store/index.ts';
export default {
name: "auth",
props: {
value: {
type: String,
default: () => "",
},
},
setup(props) {
const store = useStore();
// vuex
const getUserAuthBtnList = computed(() => {
return store.state.userInfos.authBtnList.some((v) => v === props.value);
});
return {
getUserAuthBtnList,
};
},
name: 'auth',
props: {
value: {
type: String,
default: () => '',
},
},
setup(props) {
const store = useStore();
// vuex
const getUserAuthBtnList = computed(() => {
return store.state.userInfos.userInfos.authBtnList.some((v: any) => v === props.value);
});
return {
getUserAuthBtnList,
};
},
};
</script>
</script>

View File

@ -1,30 +1,30 @@
<template>
<div v-if="getUserAuthBtnList">
<slot />
</div>
<div v-if="getUserAuthBtnList">
<slot />
</div>
</template>
<script lang="ts">
import { computed } from "vue";
import { useStore } from "/@/store/index.ts";
import { judementSameArr } from "/@/utils/arrayOperation.ts";
import { computed } from 'vue';
import { useStore } from '/@/store/index.ts';
import { judementSameArr } from '/@/utils/arrayOperation.ts';
export default {
name: "authAll",
props: {
value: {
type: Array,
default: () => [],
},
},
setup(props) {
const store = useStore();
// vuex
const getUserAuthBtnList = computed(() => {
return judementSameArr(props.value, store.state.userInfos.authBtnList);
});
return {
getUserAuthBtnList,
};
},
name: 'authAll',
props: {
value: {
type: Array,
default: () => [],
},
},
setup(props) {
const store = useStore();
// vuex
const getUserAuthBtnList = computed(() => {
return judementSameArr(props.value, store.state.userInfos.userInfos.authBtnList);
});
return {
getUserAuthBtnList,
};
},
};
</script>
</script>

View File

@ -1,35 +1,35 @@
<template>
<div v-if="getUserAuthBtnList">
<slot />
</div>
<div v-if="getUserAuthBtnList">
<slot />
</div>
</template>
<script lang="ts">
import { computed } from "vue";
import { useStore } from "/@/store/index.ts";
import { computed } from 'vue';
import { useStore } from '/@/store/index.ts';
export default {
name: "auths",
props: {
value: {
type: Array,
default: () => [],
},
},
setup(props) {
const store = useStore();
// vuex
const getUserAuthBtnList = computed(() => {
let flag = false;
store.state.userInfos.authBtnList.map((val) => {
props.value.map((v) => {
if (val === v) flag = true;
});
});
return flag;
});
return {
getUserAuthBtnList,
};
},
name: 'auths',
props: {
value: {
type: Array,
default: () => [],
},
},
setup(props) {
const store = useStore();
// vuex
const getUserAuthBtnList = computed(() => {
let flag = false;
store.state.userInfos.userInfos.authBtnList.map((val: any) => {
props.value.map((v) => {
if (val === v) flag = true;
});
});
return flag;
});
return {
getUserAuthBtnList,
};
},
};
</script>
</script>

View File

@ -1,148 +1,145 @@
<template>
<div>
<el-dialog title="更换头像" v-model="isShowDialog" width="769px">
<div class="cropper-warp">
<div class="cropper-warp-left">
<img :src="cropperImg" class="cropper-warp-left-img" />
</div>
<div class="cropper-warp-right">
<div class="cropper-warp-right-title">预览</div>
<div class="cropper-warp-right-item">
<div class="cropper-warp-right-value">
<img :src="cropperImgBase64" class="cropper-warp-right-value-img" />
</div>
<div class="cropper-warp-right-label">100 x 100</div>
</div>
<div class="cropper-warp-right-item">
<div class="cropper-warp-right-value">
<img :src="cropperImgBase64" class="cropper-warp-right-value-img cropper-size" />
</div>
<div class="cropper-warp-right-label">50 x 50</div>
</div>
</div>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="onCancel" size="small"> </el-button>
<el-button type="primary" @click="onSubmit" size="small"> </el-button>
</span>
</template>
</el-dialog>
</div>
<div>
<el-dialog title="更换头像" v-model="isShowDialog" width="769px">
<div class="cropper-warp">
<div class="cropper-warp-left">
<img :src="cropperImg" class="cropper-warp-left-img" />
</div>
<div class="cropper-warp-right">
<div class="cropper-warp-right-title">预览</div>
<div class="cropper-warp-right-item">
<div class="cropper-warp-right-value">
<img :src="cropperImgBase64" class="cropper-warp-right-value-img" />
</div>
<div class="cropper-warp-right-label">100 x 100</div>
</div>
<div class="cropper-warp-right-item">
<div class="cropper-warp-right-value">
<img :src="cropperImgBase64" class="cropper-warp-right-value-img cropper-size" />
</div>
<div class="cropper-warp-right-label">50 x 50</div>
</div>
</div>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="onCancel" size="small"> </el-button>
<el-button type="primary" @click="onSubmit" size="small"> </el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script lang="ts">
import { reactive, toRefs, nextTick } from "vue";
import Cropper from "cropperjs";
import "cropperjs/dist/cropper.css";
import { reactive, toRefs, nextTick } from 'vue';
import Cropper from 'cropperjs';
import 'cropperjs/dist/cropper.css';
export default {
name: "cropperIndex",
setup() {
const state = reactive({
isShowDialog: false,
cropperImg: "",
cropperImgBase64: "",
});
//
const openDialog = (imgs) => {
state.cropperImg = imgs;
state.isShowDialog = true;
nextTick(() => {
initCropper();
});
};
//
const closeDialog = (row) => {
state.isShowDialog = false;
};
//
const onCancel = () => {
closeDialog();
};
//
const onSubmit = () => {};
// cropperjs
const initCropper = () => {
const cropper = new Cropper(
document.querySelector(".cropper-warp-left-img"),
{
viewMode: 1,
dragMode: "none",
initialAspectRatio: 1,
aspectRatio: 1,
preview: ".before",
background: false,
autoCropArea: 0.6,
zoomOnWheel: false,
crop: (e) => {
state.cropperImgBase64 = cropper
.getCroppedCanvas()
.toDataURL("image/jpeg");
},
}
);
};
return {
openDialog,
closeDialog,
onCancel,
onSubmit,
initCropper,
...toRefs(state),
};
},
name: 'cropperIndex',
setup() {
const state = reactive({
isShowDialog: false,
cropperImg: '',
cropperImgBase64: '',
});
//
const openDialog = (imgs: any) => {
state.cropperImg = imgs;
state.isShowDialog = true;
nextTick(() => {
initCropper();
});
};
//
const closeDialog = () => {
state.isShowDialog = false;
};
//
const onCancel = () => {
closeDialog();
};
//
const onSubmit = () => {};
// cropperjs
const initCropper = () => {
const letImg: any = document.querySelector('.cropper-warp-left-img');
const cropper = new Cropper(letImg, {
viewMode: 1,
dragMode: 'none',
initialAspectRatio: 1,
aspectRatio: 1,
preview: '.before',
background: false,
autoCropArea: 0.6,
zoomOnWheel: false,
crop: () => {
state.cropperImgBase64 = cropper.getCroppedCanvas().toDataURL('image/jpeg');
},
});
};
return {
openDialog,
closeDialog,
onCancel,
onSubmit,
initCropper,
...toRefs(state),
};
},
};
</script>
<style scoped lang="scss">
.cropper-warp {
display: flex;
.cropper-warp-left {
position: relative;
display: inline-block;
height: 350px;
flex: 1;
border: 1px solid #ebeef5;
background: #fff;
overflow: hidden;
background-repeat: no-repeat;
cursor: move;
border-radius: 3px;
.cropper-warp-left-img {
width: 100%;
height: 100%;
}
}
.cropper-warp-right {
width: 150px;
height: 350px;
.cropper-warp-right-title {
text-align: center;
height: 20px;
line-height: 20px;
}
.cropper-warp-right-item {
margin: 15px 0;
.cropper-warp-right-value {
.cropper-warp-right-value-img {
width: 100px;
height: 100px;
border-radius: 100%;
margin: auto;
}
.cropper-size {
width: 50px;
height: 50px;
}
}
.cropper-warp-right-label {
text-align: center;
font-size: 12px;
color: #666666;
height: 30px;
line-height: 30px;
}
}
}
display: flex;
.cropper-warp-left {
position: relative;
display: inline-block;
height: 350px;
flex: 1;
border: 1px solid #ebeef5;
background: #fff;
overflow: hidden;
background-repeat: no-repeat;
cursor: move;
border-radius: 3px;
.cropper-warp-left-img {
width: 100%;
height: 100%;
}
}
.cropper-warp-right {
width: 150px;
height: 350px;
.cropper-warp-right-title {
text-align: center;
height: 20px;
line-height: 20px;
}
.cropper-warp-right-item {
margin: 15px 0;
.cropper-warp-right-value {
display: flex;
.cropper-warp-right-value-img {
width: 100px;
height: 100px;
border-radius: 100%;
margin: auto;
}
.cropper-size {
width: 50px;
height: 50px;
}
}
.cropper-warp-right-label {
text-align: center;
font-size: 12px;
color: #666666;
height: 30px;
line-height: 30px;
}
}
}
}
</style>
</style>

View File

@ -1,165 +1,171 @@
<template>
<div class="icon-selector">
<el-popover :placement="placement" :width="fontIconWidth" v-model:visible="fontIconVisible"
popper-class="icon-selector-popper">
<template #reference>
<el-input v-model="fontIcon" placeholder="请点击选择图标" clearable size="small" ref="inputWidthRef"
:prefix-icon="fontIconPrefix" @clear="onClearFontIcon"></el-input>
</template>
<transition name="el-zoom-in-top">
<div class="icon-selector-warp" v-show="fontIconVisible">
<div class="icon-selector-warp-title">请选择一个图标</div>
<div v-if="isAllOn" class="icon-selector-all">
<el-input v-model="fontIconSearch" placeholder="请输入内容进行搜索" size="small"></el-input>
<div class="icon-selector-all-tabs">
<div class="icon-selector-all-tabs-item" v-for="(v,k) in fontIconTabsList" :key="k"
@click="onFontIconTabsClick(v,k)" :class="{'icon-selector-all-tabs-active': fontIconTabsIndex === k}">
<div class="label">{{v.label}}</div>
</div>
</div>
</div>
<div class="icon-selector-warp-row">
<el-row :gutter="10">
<el-col :xs="4" :sm="4" :md="2" :lg="2" :xl="1" :class="`${iconShow}-col`" @click="onColClick(v,k)"
v-for="(v,k) in fontIconSheetsFilterList" :key="k">
<div class="icon-selector-warp-item" :class="{'icon-selector-active': fontIconIndex === k}">
<div class="flex-margin">
<div class="icon-selector-warp-item-value">
<i :class="[iconShow,v]"></i>
</div>
</div>
</div>
</el-col>
</el-row>
<el-empty :image-size="100" v-if="fontIconSheetsFilterList.length <= 0"></el-empty>
</div>
</div>
</transition>
</el-popover>
</div>
<div class="icon-selector">
<el-popover :placement="placement" :width="fontIconWidth" v-model:visible="fontIconVisible" popper-class="icon-selector-popper">
<template #reference>
<el-input
v-model="fontIcon"
placeholder="请点击选择图标"
clearable
size="small"
ref="inputWidthRef"
:prefix-icon="fontIconPrefix"
@clear="onClearFontIcon"
></el-input>
</template>
<transition name="el-zoom-in-top">
<div class="icon-selector-warp" v-show="fontIconVisible">
<div class="icon-selector-warp-title">请选择一个图标</div>
<div v-if="isAllOn" class="icon-selector-all">
<el-input v-model="fontIconSearch" placeholder="请输入内容进行搜索" size="small"></el-input>
<div class="icon-selector-all-tabs">
<div
class="icon-selector-all-tabs-item"
v-for="(v, k) in fontIconTabsList"
:key="k"
@click="onFontIconTabsClick(v, k)"
:class="{ 'icon-selector-all-tabs-active': fontIconTabsIndex === k }"
>
<div class="label">{{ v.label }}</div>
</div>
</div>
</div>
<div class="icon-selector-warp-row">
<el-row :gutter="10">
<el-col
:xs="4"
:sm="4"
:md="2"
:lg="2"
:xl="1"
:class="`${fontIconTabsIcon}-col`"
@click="onColClick(v, k)"
v-for="(v, k) in fontIconSheetsFilterList"
:key="k"
>
<div class="icon-selector-warp-item" :class="{ 'icon-selector-active': fontIconIndex === k }">
<div class="flex-margin">
<div class="icon-selector-warp-item-value">
<i :class="[fontIconTabsIcon, v]"></i>
</div>
</div>
</div>
</el-col>
</el-row>
<el-empty :image-size="100" v-if="fontIconSheetsFilterList.length <= 0"></el-empty>
</div>
</div>
</transition>
</el-popover>
</div>
</template>
<script lang="ts">
import { ref, toRefs, reactive, onMounted, nextTick, computed } from "vue";
import initIconfont from "/@/utils/getStyleSheets.ts";
import { stat } from "node:fs";
import { ref, toRefs, reactive, onMounted, nextTick, computed } from 'vue';
import initIconfont from '/@/utils/getStyleSheets.ts';
export default {
name: "iconSelector",
props: {
//
isAllOn: {
type: Boolean,
default: () => false,
},
//
placement: {
type: String,
default: () => "bottom",
},
},
setup(props, { emit }) {
const inputWidthRef = ref();
const state = reactive({
fontIcon: "",
fontIconPrefix: "",
fontIconVisible: false,
fontIconWidth: 0,
fontIconIndex: "",
fontIconSearch: "",
fontIconTabsIndex: 0,
fontIconTabsList: [
{ label: "iconfont" },
{ label: "element" },
{ label: "awesome" },
],
fontIconSheetsList: [],
fontIconSheetsListAli: [],
fontIconSheetsListEle: [],
fontIconSheetsListAwe: [],
});
// iconShow
const iconShow = computed(() => {
if (state.fontIconTabsIndex === 0) return `iconfont ali`;
else if (state.fontIconTabsIndex === 1) return `ele`;
else if (state.fontIconTabsIndex === 2) return `fa awe`;
});
//
const fontIconSheetsFilterList = computed(() => {
if (!state.fontIconSearch) return state.fontIconSheetsList;
let search = state.fontIconSearch.trim().toLowerCase();
return state.fontIconSheetsList.filter((item) => {
if (item.toLowerCase().indexOf(search) !== -1) return item;
});
});
// input
const getInputWidth = () => {
nextTick(() => {
state.fontIconWidth = inputWidthRef.value.$el.offsetWidth;
});
};
//
const initResize = () => {
window.addEventListener("resize", () => {
getInputWidth();
});
};
//
const initFontIconData = () => {
initIconfont.ali().then((res) => {
state.fontIconSheetsList = res;
state.fontIconSheetsListAli = res;
});
initIconfont.ele().then((res) => {
state.fontIconSheetsListEle = res;
});
initIconfont.awe().then((res) => {
state.fontIconSheetsListAwe = res;
});
};
//
const onColClick = (v, k) => {
state.fontIconIndex = k;
state.fontIcon = v;
state.fontIconVisible = false;
if (state.fontIconTabsIndex === 0)
state.fontIconPrefix = `iconfont ali ${v}`;
else if (state.fontIconTabsIndex === 1) state.fontIconPrefix = `ele ${v}`;
else if (state.fontIconTabsIndex === 2)
state.fontIconPrefix = `fa awe ${v}`;
emit("get", state.fontIconPrefix);
};
// input
const onClearFontIcon = () => {
state.fontIconIndex = "";
state.fontIconPrefix = "";
emit("get", state.fontIconPrefix);
};
// tabs
const onFontIconTabsClick = (v, k) => {
state.fontIconTabsIndex = k;
if (v.label === "iconfont") {
state.fontIconSheetsList = state.fontIconSheetsListAli;
} else if (v.label === "element") {
state.fontIconSheetsList = state.fontIconSheetsListEle;
} else if (v.label === "awesome") {
state.fontIconSheetsList = state.fontIconSheetsListAwe;
}
};
//
onMounted(() => {
initFontIconData();
initResize();
getInputWidth();
});
return {
inputWidthRef,
iconShow,
fontIconSheetsFilterList,
onColClick,
onClearFontIcon,
onFontIconTabsClick,
...toRefs(state),
};
},
name: 'iconSelector',
props: {
//
isAllOn: {
type: Boolean,
default: () => false,
},
//
placement: {
type: String,
default: () => 'bottom',
},
},
setup(props, { emit }) {
const inputWidthRef = ref();
const state: any = reactive({
fontIcon: '',
fontIconPrefix: '',
fontIconVisible: false,
fontIconWidth: 0,
fontIconIndex: '',
fontIconSearch: '',
fontIconTabsIndex: 0,
fontIconTabsIcon: 'iconfont ali',
fontIconTabsList: [{ label: 'iconfont' }, { label: 'element' }, { label: 'awesome' }],
fontIconSheetsList: [],
fontIconSheetsListAli: [],
fontIconSheetsListEle: [],
fontIconSheetsListAwe: [],
});
//
const fontIconSheetsFilterList = computed(() => {
if (!state.fontIconSearch) return state.fontIconSheetsList;
let search = state.fontIconSearch.trim().toLowerCase();
return state.fontIconSheetsList.filter((item: any) => {
if (item.toLowerCase().indexOf(search) !== -1) return item;
});
});
// input
const getInputWidth = () => {
nextTick(() => {
state.fontIconWidth = inputWidthRef.value.$el.offsetWidth;
});
};
//
const initResize = () => {
window.addEventListener('resize', () => {
getInputWidth();
});
};
//
const initFontIconData = () => {
initIconfont.ali().then((res: any) => {
state.fontIconSheetsList = res;
state.fontIconSheetsListAli = res;
});
initIconfont.ele().then((res: any) => {
state.fontIconSheetsListEle = res;
});
initIconfont.awe().then((res: any) => {
state.fontIconSheetsListAwe = res;
});
};
//
const onColClick = (v: any, k: number) => {
state.fontIconIndex = k;
state.fontIcon = v;
state.fontIconVisible = false;
if (state.fontIconTabsIndex === 0) state.fontIconPrefix = `iconfont ali ${v}`;
else if (state.fontIconTabsIndex === 1) state.fontIconPrefix = `ele ${v}`;
else if (state.fontIconTabsIndex === 2) state.fontIconPrefix = `fa awe ${v}`;
emit('get', state.fontIconPrefix);
};
// input
const onClearFontIcon = () => {
state.fontIconIndex = '';
state.fontIconPrefix = '';
emit('get', state.fontIconPrefix);
};
// tabs
const onFontIconTabsClick = (v: any, k: number) => {
state.fontIconTabsIndex = k;
if (v.label === 'iconfont') state.fontIconSheetsList = state.fontIconSheetsListAli;
else if (v.label === 'element') state.fontIconSheetsList = state.fontIconSheetsListEle;
else if (v.label === 'awesome') state.fontIconSheetsList = state.fontIconSheetsListAwe;
if (k === 0) state.fontIconTabsIcon = `iconfont ali`;
else if (k === 1) state.fontIconTabsIcon = `ele`;
else if (k === 2) state.fontIconTabsIcon = `fa awe`;
};
//
onMounted(() => {
initFontIconData();
initResize();
getInputWidth();
});
return {
inputWidthRef,
fontIconSheetsFilterList,
onColClick,
onClearFontIcon,
onFontIconTabsClick,
...toRefs(state),
};
},
};
</script>
</script>

View File

@ -1,17 +1,17 @@
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import { store, key } from './store'
import { authDirective } from '/@/utils/authDirective.ts'
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import { store, key } from './store';
import { authDirective } from '/@/utils/authDirective.ts';
import ElementPlus from 'element-plus'
import 'element-plus/lib/theme-chalk/index.css'
import '/@/theme/index.scss'
import lang from 'element-plus/lib/locale/lang/zh-cn'
import mitt from "mitt"
import ElementPlus from 'element-plus';
import 'element-plus/lib/theme-chalk/index.css';
import '/@/theme/index.scss';
import lang from 'element-plus/lib/locale/lang/zh-cn';
import mitt from 'mitt';
const app = createApp(App)
app.use(router).use(store, key).use(ElementPlus, { locale: lang }).mount('#app')
app.config.globalProperties.mittBus = mitt()
const app = createApp(App);
app.use(router).use(store, key).use(ElementPlus, { locale: lang }).mount('#app');
app.config.globalProperties.mittBus = mitt();
authDirective(app)
authDirective(app);

File diff suppressed because it is too large Load Diff

View File

@ -1,128 +1,25 @@
import { InjectionKey } from 'vue'
import { createStore, useStore as baseUseStore, Store } from 'vuex'
import themeConfig from '/@/utils/themeConfig.ts'
import { getSession } from "/@/utils/storage.ts";
export interface RootStateTypes {
themeConfig: {
isDrawer: boolean,
primary: string,
success: string,
info: string,
warning: string,
danger: string,
topBar: string,
menuBar: string,
columnsMenuBar: string,
topBarColor: string,
menuBarColor: string,
columnsMenuBarColor: string,
isTopBarColorGradual: boolean,
isMenuBarColorGradual: boolean,
isMenuBarColorHighlight: boolean,
isCollapse: boolean,
isUniqueOpened: boolean,
isFixedHeader: boolean,
isFixedHeaderChange: boolean,
isClassicSplitMenu: boolean,
isLockScreen: boolean,
lockScreenTime: number,
isShowLogo: boolean,
isShowLogoChange: boolean,
isBreadcrumb: boolean,
isTagsview: boolean,
isBreadcrumbIcon: boolean,
isTagsviewIcon: boolean,
isCacheTagsView: boolean,
isSortableTagsView: boolean,
isFooter: boolean,
isGrayscale: boolean,
isInvert: boolean,
isWartermark: boolean,
wartermarkText: string,
tagsStyle: string,
animation: string,
columnsAsideStyle: string,
layout: string,
isRequestRoutes: boolean,
globalTitle: string,
globalViceTitle: string,
},
routes: Array<object>,
keepAliveNames: Array<string>,
tagsViewRoutes: Array<object>,
userInfos: object,
requestOldRoutes: Array<object>,
}
import { InjectionKey } from 'vue';
import { createStore, useStore as baseUseStore, Store } from 'vuex';
import themeConfig from '/@/store/modules/themeConfig.ts';
import routesList from '/@/store/modules/routesList.ts';
import keepAliveNames from '/@/store/modules/keepAliveNames.ts';
import tagsViewRoutes from '/@/store/modules/tagsViewRoutes.ts';
import userInfos from '/@/store/modules/userInfos.ts';
import requestOldRoutes from '/@/store/modules/requestOldRoutes.ts';
export const key: InjectionKey<Store<RootStateTypes>> = Symbol()
export const key: InjectionKey<Store<RootStateTypes>> = Symbol();
export const store = createStore<RootStateTypes>({
state: {
themeConfig,
routes: [],
keepAliveNames: [],
tagsViewRoutes: [],
userInfos: {},
requestOldRoutes: []
},
mutations: {
// 设置布局配置
getThemeConfig(state: any, data: object) {
state.themeConfig = Object.assign({}, data)
},
// 设置路由,菜单中使用到
getRoutes(state: any, data: Array<object>) {
state.routes = data
},
// 设置缓存name字段
getCacheKeepAlive(state: any, data: Array<string>) {
state.keepAliveNames = data
},
// 设置 TagsView 路由
getTagsViewRoutes(state: any, data: Array<string>) {
state.tagsViewRoutes = data
},
// 设置用户信息
getUserInfos(state: any, data: object) {
state.userInfos = data
},
// 后端控制路由
getBackEndControlRoutes(state: any, data: object) {
state.requestOldRoutes = data
},
},
actions: {
// 设置布局配置
setThemeConfig({ commit }, data: object) {
commit('getThemeConfig', data)
},
// 设置路由,菜单中使用到
async setRoutes({ commit }, data: any) {
commit('getRoutes', data)
},
// 设置缓存name字段
async setCacheKeepAlive({ commit }, data: Array<string>) {
commit('getCacheKeepAlive', data)
},
// 设置 TagsView 路由
async setTagsViewRoutes({ commit }, data: Array<string>) {
commit('getTagsViewRoutes', data)
},
// 设置用户信息
async setUserInfos({ commit }, data: object) {
if (data) {
commit('getUserInfos', data)
} else {
if (getSession('userInfo')) commit('getUserInfos', getSession('userInfo'))
}
},
// 后端控制路由
setBackEndControlRoutes({ commit }, routes: Array<string>) {
commit('getBackEndControlRoutes', routes)
}
}
})
modules: {
themeConfig,
routesList,
keepAliveNames,
tagsViewRoutes,
userInfos,
requestOldRoutes,
},
});
export function useStore() {
return baseUseStore(key)
}
return baseUseStore(key);
}

View File

@ -0,0 +1,84 @@
// 接口类型声明
// 布局配置
declare interface ThemeConfigState {
themeConfig: {
isDrawer: boolean;
primary: string;
success: string;
info: string;
warning: string;
danger: string;
topBar: string;
menuBar: string;
columnsMenuBar: string;
topBarColor: string;
menuBarColor: string;
columnsMenuBarColor: string;
isTopBarColorGradual: boolean;
isMenuBarColorGradual: boolean;
isMenuBarColorHighlight: boolean;
isCollapse: boolean;
isUniqueOpened: boolean;
isFixedHeader: boolean;
isFixedHeaderChange: boolean;
isClassicSplitMenu: boolean;
isLockScreen: boolean;
lockScreenTime: number;
isShowLogo: boolean;
isShowLogoChange: boolean;
isBreadcrumb: boolean;
isTagsview: boolean;
isBreadcrumbIcon: boolean;
isTagsviewIcon: boolean;
isCacheTagsView: boolean;
isSortableTagsView: boolean;
isFooter: boolean;
isGrayscale: boolean;
isInvert: boolean;
isWartermark: boolean;
wartermarkText: string;
tagsStyle: string;
animation: string;
columnsAsideStyle: string;
layout: string;
isRequestRoutes: boolean;
globalTitle: string;
globalViceTitle: string;
};
}
// 路由列表
declare interface RoutesListState {
routesList: Array<object>;
}
// 路由缓存列表
declare interface KeepAliveNamesState {
keepAliveNames: Array<string>;
}
// TagsView 路由列表
declare interface TagsViewRoutesState {
tagsViewRoutes: Array<object>;
}
// 用户信息
declare interface UserInfosState {
userInfos: object;
}
// 后端返回原始路由(未处理时)
declare interface RequestOldRoutesState {
requestOldRoutes: Array<object>;
}
// 主接口(顶级类型声明)
declare interface RootStateTypes {
themeConfig: ThemeConfigState;
routesList: RoutesListState;
keepAliveNames: KeepAliveNamesState;
tagsViewRoutes: TagsViewRoutesState;
userInfos: UserInfosState;
requestOldRoutes: RequestOldRoutesState;
}

View File

@ -0,0 +1,22 @@
import { Module } from 'vuex';
const keepAliveNamesModule: Module<KeepAliveNamesState, RootStateTypes> = {
namespaced: true,
state: {
keepAliveNames: [],
},
mutations: {
// 设置路由缓存name字段
getCacheKeepAlive(state: any, data: Array<string>) {
state.keepAliveNames = data;
},
},
actions: {
// 设置路由缓存name字段
async setCacheKeepAlive({ commit }, data: Array<string>) {
commit('getCacheKeepAlive', data);
},
},
};
export default keepAliveNamesModule;

View File

@ -0,0 +1,22 @@
import { Module } from 'vuex';
const requestOldRoutesModule: Module<RequestOldRoutesState, RootStateTypes> = {
namespaced: true,
state: {
requestOldRoutes: [],
},
mutations: {
// 后端控制路由
getBackEndControlRoutes(state: any, data: object) {
state.requestOldRoutes = data;
},
},
actions: {
// 后端控制路由
setBackEndControlRoutes({ commit }, routes: Array<string>) {
commit('getBackEndControlRoutes', routes);
},
},
};
export default requestOldRoutesModule;

View File

@ -0,0 +1,22 @@
import { Module } from 'vuex';
const routesListModule: Module<RoutesListState, RootStateTypes> = {
namespaced: true,
state: {
routesList: [],
},
mutations: {
// 设置路由,菜单中使用到
getRoutesList(state: any, data: Array<object>) {
state.routesList = data;
},
},
actions: {
// 设置路由,菜单中使用到
async setRoutesList({ commit }, data: any) {
commit('getRoutesList', data);
},
},
};
export default routesListModule;

View File

@ -0,0 +1,22 @@
import { Module } from 'vuex';
const tagsViewRoutesModule: Module<TagsViewRoutesState, RootStateTypes> = {
namespaced: true,
state: {
tagsViewRoutes: [],
},
mutations: {
// 设置 TagsView 路由
getTagsViewRoutes(state: any, data: Array<string>) {
state.tagsViewRoutes = data;
},
},
actions: {
// 设置 TagsView 路由
async setTagsViewRoutes({ commit }, data: Array<string>) {
commit('getTagsViewRoutes', data);
},
},
};
export default tagsViewRoutesModule;

View File

@ -0,0 +1,132 @@
import { Module } from 'vuex';
const themeConfigModule: Module<ThemeConfigState, RootStateTypes> = {
namespaced: true,
state: {
themeConfig: {
// 是否开启布局配置抽屉
isDrawer: false,
/*
------------------------------- */
// 默认 primary 颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
primary: '#409eff',
// 默认 success 颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
success: '#67c23a',
// 默认 info 颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
info: '#909399',
// 默认 warning 颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
warning: '#e6a23c',
// 默认 danger 颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
danger: '#f56c6c',
/* 菜单 /
------------------------------- */
// 默认顶栏导航背景颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
topBar: '#ffffff',
// 默认菜单导航背景颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
menuBar: '#545c64',
// 默认分栏菜单背景颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
columnsMenuBar: '#545c64',
// 默认顶栏导航字体颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
topBarColor: '#606266',
// 默认菜单导航字体颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
menuBarColor: '#eaeaea',
// 默认分栏菜单字体颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
columnsMenuBarColor: '#e6e6e6',
// 是否开启顶栏背景颜色渐变
isTopBarColorGradual: false,
// 是否开启菜单背景颜色渐变
isMenuBarColorGradual: false,
// 是否开启菜单字体背景高亮
isMenuBarColorHighlight: false,
// 是否开启菜单字体背景高亮
/*
------------------------------- */
// 是否开启菜单水平折叠效果
isCollapse: false,
// 是否开启菜单手风琴效果
isUniqueOpened: false,
// 是否开启固定 Header
isFixedHeader: false,
// 初始化变量,用于更新菜单 el-scrollbar 的高度,请勿删除
isFixedHeaderChange: false,
// 是否开启经典布局分割菜单(仅经典布局生效)
isClassicSplitMenu: false,
// 是否开启自动锁屏
isLockScreen: false,
// 开启自动锁屏倒计时(s/秒)
lockScreenTime: 30,
/*
------------------------------- */
// 是否开启侧边栏 Logo
isShowLogo: false,
// 初始化变量,用于 el-scrollbar 的高度更新,请勿删除
isShowLogoChange: false,
// 是否开启 Breadcrumb
isBreadcrumb: true,
// 是否开启 Tagsview
isTagsview: true,
// 是否开启 Breadcrumb 图标
isBreadcrumbIcon: false,
// 是否开启 Tagsview 图标
isTagsviewIcon: false,
// 是否开启 TagsView 缓存
isCacheTagsView: false,
// 是否开启 TagsView 拖拽
isSortableTagsView: true,
// 是否开启 Footer 底部版权信息
isFooter: false,
// 是否开启灰色模式
isGrayscale: false,
// 是否开启色弱模式
isInvert: false,
// 是否开启水印
isWartermark: false,
// 水印文案
wartermarkText: 'small@小柒',
/*
------------------------------- */
// 默认 Tagsview 风格,可选 1、 tags-style-one 2、 tags-style-two 3、 tags-style-three 4、 tags-style-four
tagsStyle: 'tags-style-one',
// 默认主页面切换动画,可选 1、 slide-right 2、 slide-left 3、 opacitys
animation: 'slide-right',
// 默认分栏高亮风格,可选 1、 圆角 columns-round 2、 卡片 columns-card
columnsAsideStyle: 'columns-round',
/*
------------------------------- */
// 默认布局,可选 1、默认 defaults 2、经典 classic 3、横向 transverse 4、分栏 columns
layout: 'defaults',
/*
------------------------------- */
// 是否开启后端控制路由
isRequestRoutes: false,
/* 全局网站标题 /
------------------------------- */
// 网站主标题(菜单导航、浏览器当前网页标题)
globalTitle: 'vue-next-admin',
// 网站副标题(登录页顶部文字)
globalViceTitle: 'SMALL@小柒',
},
},
mutations: {
// 设置布局配置
getThemeConfig(state: any, data: object) {
state.themeConfig = data;
},
},
actions: {
// 设置布局配置
setThemeConfig({ commit }, data: object) {
commit('getThemeConfig', data);
},
},
};
export default themeConfigModule;

View File

@ -0,0 +1,27 @@
import { Module } from 'vuex';
import { getSession } from '/@/utils/storage.ts';
const userInfosModule: Module<UserInfosState, RootStateTypes> = {
namespaced: true,
state: {
userInfos: {},
},
mutations: {
// 设置用户信息
getUserInfos(state: any, data: object) {
state.userInfos = data;
},
},
actions: {
// 设置用户信息
async setUserInfos({ commit }, data: object) {
if (data) {
commit('getUserInfos', data);
} else {
if (getSession('userInfo')) commit('getUserInfos', getSession('userInfo'));
}
},
},
};
export default userInfosModule;

View File

@ -14,8 +14,7 @@ body,
padding: 0;
width: 100%;
height: 100%;
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB,
Microsoft YaHei, SimSun, sans-serif;
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif;
font-weight: 400;
-webkit-font-smoothing: antialiased;
-webkit-tap-highlight-color: transparent;

View File

@ -4,82 +4,82 @@
.slide-right-leave-active,
.slide-left-enter-active,
.slide-left-leave-active {
will-change: transform;
transition: all 0.3s ease;
will-change: transform;
transition: all 0.3s ease;
}
// slide-right
.slide-right-enter-from {
opacity: 0;
transform: translateX(-20px);
opacity: 0;
transform: translateX(-20px);
}
.slide-right-leave-to {
opacity: 0;
transform: translateX(20px);
opacity: 0;
transform: translateX(20px);
}
// slide-left
.slide-left-enter-from {
@extend .slide-right-leave-to;
@extend .slide-right-leave-to;
}
.slide-left-leave-to {
@extend .slide-right-enter-from;
@extend .slide-right-enter-from;
}
// opacitys
.opacitys-enter-active,
.opacitys-leave-active {
will-change: transform;
transition: all 0.3s ease;
will-change: transform;
transition: all 0.3s ease;
}
.opacitys-enter-from,
.opacitys-leave-to {
opacity: 0;
opacity: 0;
}
/* Breadcrumb 面包屑过渡动画
------------------------------- */
.breadcrumb-enter-active,
.breadcrumb-leave-active {
transition: all 0.3s;
transition: all 0.3s;
}
.breadcrumb-enter-from,
.breadcrumb-leave-active {
opacity: 0;
transform: translateX(20px);
opacity: 0;
transform: translateX(20px);
}
.breadcrumb-leave-active {
position: absolute;
position: absolute;
}
/* logo 过渡动画
------------------------------- */
@keyframes logoAnimation {
0% {
transform: scale(0);
}
80% {
transform: scale(1.2);
}
100% {
transform: scale(1);
}
0% {
transform: scale(0);
}
80% {
transform: scale(1.2);
}
100% {
transform: scale(1);
}
}
/* 404401 过渡动画
------------------------------- */
@keyframes error-num {
0% {
transform: translateY(60px);
opacity: 0;
}
100% {
transform: translateY(0);
opacity: 1;
}
0% {
transform: translateY(60px);
opacity: 0;
}
100% {
transform: translateY(0);
opacity: 1;
}
}
@keyframes error-img {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}

View File

@ -68,62 +68,62 @@ $--bg-columnsMenuBarColor: #e6e6e6;
/* 赋值给:root
------------------------------- */
:root {
--color-primary: #{$--color-primary};
--color-whites: #{$--color-whites};
--color-blacks: #{$--color-blacks};
--color-primary-light-1: #{$--color-primary-light-1};
--color-primary-light-2: #{$--color-primary-light-2};
--color-primary-light-3: #{$--color-primary-light-3};
--color-primary-light-4: #{$--color-primary-light-4};
--color-primary-light-5: #{$--color-primary-light-5};
--color-primary-light-6: #{$--color-primary-light-6};
--color-primary-light-7: #{$--color-primary-light-7};
--color-primary-light-8: #{$--color-primary-light-8};
--color-primary-light-9: #{$--color-primary-light-9};
--color-success: #{$--color-success};
--color-success-light-1: #{$--color-success-light-1};
--color-success-light-2: #{$--color-success-light-2};
--color-success-light-3: #{$--color-success-light-3};
--color-success-light-4: #{$--color-success-light-4};
--color-success-light-5: #{$--color-success-light-5};
--color-success-light-6: #{$--color-success-light-6};
--color-success-light-7: #{$--color-success-light-7};
--color-success-light-8: #{$--color-success-light-8};
--color-success-light-9: #{$--color-success-light-9};
--color-info: #{$--color-info};
--color-info-light-1: #{$--color-info-light-1};
--color-info-light-2: #{$--color-info-light-2};
--color-info-light-3: #{$--color-info-light-3};
--color-info-light-4: #{$--color-info-light-4};
--color-info-light-5: #{$--color-info-light-5};
--color-info-light-6: #{$--color-info-light-6};
--color-info-light-7: #{$--color-info-light-7};
--color-info-light-8: #{$--color-info-light-8};
--color-info-light-9: #{$--color-info-light-9};
--color-warning: #{$--color-warning};
--color-warning-light-1: #{$--color-warning-light-1};
--color-warning-light-2: #{$--color-warning-light-2};
--color-warning-light-3: #{$--color-warning-light-3};
--color-warning-light-4: #{$--color-warning-light-4};
--color-warning-light-5: #{$--color-warning-light-5};
--color-warning-light-6: #{$--color-warning-light-6};
--color-warning-light-7: #{$--color-warning-light-7};
--color-warning-light-8: #{$--color-warning-light-8};
--color-warning-light-9: #{$--color-warning-light-9};
--color-danger: #{$--color-danger};
--color-danger-light-1: #{$--color-danger-light-1};
--color-danger-light-2: #{$--color-danger-light-2};
--color-danger-light-3: #{$--color-danger-light-3};
--color-danger-light-4: #{$--color-danger-light-4};
--color-danger-light-5: #{$--color-danger-light-5};
--color-danger-light-6: #{$--color-danger-light-6};
--color-danger-light-7: #{$--color-danger-light-7};
--color-danger-light-8: #{$--color-danger-light-8};
--color-danger-light-9: #{$--color-danger-light-9};
--bg-topBar: #{$--bg-topBar};
--bg-menuBar: #{$--bg-menuBar};
--bg-columnsMenuBar: #{$--bg-columnsMenuBar};
--bg-topBarColor: #{$--bg-topBarColor};
--bg-menuBarColor: #{$--bg-menuBarColor};
--bg-columnsMenuBarColor: #{$--bg-columnsMenuBarColor};
--color-primary: #{$--color-primary};
--color-whites: #{$--color-whites};
--color-blacks: #{$--color-blacks};
--color-primary-light-1: #{$--color-primary-light-1};
--color-primary-light-2: #{$--color-primary-light-2};
--color-primary-light-3: #{$--color-primary-light-3};
--color-primary-light-4: #{$--color-primary-light-4};
--color-primary-light-5: #{$--color-primary-light-5};
--color-primary-light-6: #{$--color-primary-light-6};
--color-primary-light-7: #{$--color-primary-light-7};
--color-primary-light-8: #{$--color-primary-light-8};
--color-primary-light-9: #{$--color-primary-light-9};
--color-success: #{$--color-success};
--color-success-light-1: #{$--color-success-light-1};
--color-success-light-2: #{$--color-success-light-2};
--color-success-light-3: #{$--color-success-light-3};
--color-success-light-4: #{$--color-success-light-4};
--color-success-light-5: #{$--color-success-light-5};
--color-success-light-6: #{$--color-success-light-6};
--color-success-light-7: #{$--color-success-light-7};
--color-success-light-8: #{$--color-success-light-8};
--color-success-light-9: #{$--color-success-light-9};
--color-info: #{$--color-info};
--color-info-light-1: #{$--color-info-light-1};
--color-info-light-2: #{$--color-info-light-2};
--color-info-light-3: #{$--color-info-light-3};
--color-info-light-4: #{$--color-info-light-4};
--color-info-light-5: #{$--color-info-light-5};
--color-info-light-6: #{$--color-info-light-6};
--color-info-light-7: #{$--color-info-light-7};
--color-info-light-8: #{$--color-info-light-8};
--color-info-light-9: #{$--color-info-light-9};
--color-warning: #{$--color-warning};
--color-warning-light-1: #{$--color-warning-light-1};
--color-warning-light-2: #{$--color-warning-light-2};
--color-warning-light-3: #{$--color-warning-light-3};
--color-warning-light-4: #{$--color-warning-light-4};
--color-warning-light-5: #{$--color-warning-light-5};
--color-warning-light-6: #{$--color-warning-light-6};
--color-warning-light-7: #{$--color-warning-light-7};
--color-warning-light-8: #{$--color-warning-light-8};
--color-warning-light-9: #{$--color-warning-light-9};
--color-danger: #{$--color-danger};
--color-danger-light-1: #{$--color-danger-light-1};
--color-danger-light-2: #{$--color-danger-light-2};
--color-danger-light-3: #{$--color-danger-light-3};
--color-danger-light-4: #{$--color-danger-light-4};
--color-danger-light-5: #{$--color-danger-light-5};
--color-danger-light-6: #{$--color-danger-light-6};
--color-danger-light-7: #{$--color-danger-light-7};
--color-danger-light-8: #{$--color-danger-light-8};
--color-danger-light-9: #{$--color-danger-light-9};
--bg-topBar: #{$--bg-topBar};
--bg-menuBar: #{$--bg-menuBar};
--bg-columnsMenuBar: #{$--bg-columnsMenuBar};
--bg-topBarColor: #{$--bg-topBarColor};
--bg-menuBarColor: #{$--bg-menuBarColor};
--bg-columnsMenuBarColor: #{$--bg-columnsMenuBarColor};
}

File diff suppressed because it is too large Load Diff

View File

@ -1,87 +1,87 @@
/* Popover 弹出框(图标选择器)
------------------------------- */
.icon-selector-popper {
padding: 0 !important;
.icon-selector-warp {
.icon-selector-warp-title {
height: 40px;
line-height: 40px;
padding: 0 15px;
}
.icon-selector-warp-row {
max-height: 260px;
overflow-y: auto;
padding: 15px 15px 5px;
border-top: 1px solid #ebeef5;
.ele-col:nth-last-child(1),
.ele-col:nth-last-child(2) {
display: none;
}
.awe-col:nth-child(-n + 24) {
display: none;
}
.icon-selector-warp-item {
display: flex;
border: 1px solid #ebeef5;
padding: 10px;
border-radius: 5px;
margin-bottom: 10px;
transition: all 0.3s ease;
.icon-selector-warp-item-value {
transition: all 0.3s ease;
i {
font-size: 20px;
color: #606266;
}
}
&:hover {
border: 1px solid var(--color-primary);
cursor: pointer;
transition: all 0.3s ease;
.icon-selector-warp-item-value {
i {
color: var(--color-primary);
transition: all 0.3s ease;
}
}
}
}
.icon-selector-active {
border: 1px solid var(--color-primary);
.icon-selector-warp-item-value {
i {
color: var(--color-primary);
}
}
}
}
.icon-selector-all {
.el-input {
padding: 0 15px;
margin-bottom: 10px;
}
&-tabs {
display: flex;
height: 30px;
line-height: 30px;
padding: 0 15px;
margin-bottom: 5px;
&-item {
flex: 1;
text-align: center;
cursor: pointer;
&:hover {
color: var(--color-primary);
}
}
&-active {
background: var(--color-primary);
border-radius: 5px;
.label {
color: #ffffff;
}
}
}
}
}
padding: 0 !important;
.icon-selector-warp {
.icon-selector-warp-title {
height: 40px;
line-height: 40px;
padding: 0 15px;
}
.icon-selector-warp-row {
max-height: 260px;
overflow-y: auto;
padding: 15px 15px 5px;
border-top: 1px solid #ebeef5;
.ele-col:nth-last-child(1),
.ele-col:nth-last-child(2) {
display: none;
}
.awe-col:nth-child(-n + 24) {
display: none;
}
.icon-selector-warp-item {
display: flex;
border: 1px solid #ebeef5;
padding: 10px;
border-radius: 5px;
margin-bottom: 10px;
transition: all 0.3s ease;
.icon-selector-warp-item-value {
transition: all 0.3s ease;
i {
font-size: 20px;
color: #606266;
}
}
&:hover {
border: 1px solid var(--color-primary);
cursor: pointer;
transition: all 0.3s ease;
.icon-selector-warp-item-value {
i {
color: var(--color-primary);
transition: all 0.3s ease;
}
}
}
}
.icon-selector-active {
border: 1px solid var(--color-primary);
.icon-selector-warp-item-value {
i {
color: var(--color-primary);
}
}
}
}
.icon-selector-all {
.el-input {
padding: 0 15px;
margin-bottom: 10px;
}
&-tabs {
display: flex;
height: 30px;
line-height: 30px;
padding: 0 15px;
margin-bottom: 5px;
&-item {
flex: 1;
text-align: center;
cursor: pointer;
&:hover {
color: var(--color-primary);
}
}
&-active {
background: var(--color-primary);
border-radius: 5px;
.label {
color: #ffffff;
}
}
}
}
}
}

View File

@ -3,88 +3,88 @@
/* 页面宽度小于768px
------------------------------- */
@media screen and (max-width: $sm) {
.big-data-down-left {
width: 100% !important;
flex-direction: unset !important;
flex-wrap: wrap;
.flex-warp-item {
min-height: 196.24px;
padding: 0 7.5px 15px 15px !important;
.flex-warp-item-box {
border: none !important;
border-bottom: 1px solid #ebeef5 !important;
}
}
}
.big-data-down-center {
width: 100% !important;
.big-data-down-center-one,
.big-data-down-center-two {
min-height: 196.24px;
padding-left: 15px !important;
.big-data-down-center-one-content {
border: none !important;
border-bottom: 1px solid #ebeef5 !important;
}
.flex-warp-item-box {
@extend .big-data-down-center-one-content;
}
}
}
.big-data-down-right {
.flex-warp-item {
&:nth-of-type(2) {
padding-left: 15px !important;
}
&:last-of-type {
.flex-warp-item-box {
border: none !important;
}
}
}
}
.big-data-down-left {
width: 100% !important;
flex-direction: unset !important;
flex-wrap: wrap;
.flex-warp-item {
min-height: 196.24px;
padding: 0 7.5px 15px 15px !important;
.flex-warp-item-box {
border: none !important;
border-bottom: 1px solid #ebeef5 !important;
}
}
}
.big-data-down-center {
width: 100% !important;
.big-data-down-center-one,
.big-data-down-center-two {
min-height: 196.24px;
padding-left: 15px !important;
.big-data-down-center-one-content {
border: none !important;
border-bottom: 1px solid #ebeef5 !important;
}
.flex-warp-item-box {
@extend .big-data-down-center-one-content;
}
}
}
.big-data-down-right {
.flex-warp-item {
&:nth-of-type(2) {
padding-left: 15px !important;
}
&:last-of-type {
.flex-warp-item-box {
border: none !important;
}
}
}
}
}
/* 页面宽度大于768px小于1200px
------------------------------- */
@media screen and (min-width: $sm) and (max-width: $lg) {
.chart-warp-bottom {
.big-data-down-left {
width: 50% !important;
}
.big-data-down-center {
width: 50% !important;
}
.big-data-down-right {
.flex-warp-item {
width: 50% !important;
&:nth-of-type(2) {
padding-left: 7.5px !important;
}
}
}
}
.chart-warp-bottom {
.big-data-down-left {
width: 50% !important;
}
.big-data-down-center {
width: 50% !important;
}
.big-data-down-right {
.flex-warp-item {
width: 50% !important;
&:nth-of-type(2) {
padding-left: 7.5px !important;
}
}
}
}
}
/* 页面宽度小于1200px
------------------------------- */
@media screen and (max-width: $lg) {
.chart-warp-top {
.up-left {
display: none;
}
}
.chart-warp-bottom {
overflow-y: auto !important;
flex-wrap: wrap;
.big-data-down-right {
width: 100% !important;
flex-direction: unset !important;
flex-wrap: wrap;
.flex-warp-item {
min-height: 196.24px;
padding: 0 7.5px 15px 15px !important;
}
}
}
.chart-warp-top {
.up-left {
display: none;
}
}
.chart-warp-bottom {
overflow-y: auto !important;
flex-wrap: wrap;
.big-data-down-right {
width: 100% !important;
flex-direction: unset !important;
flex-wrap: wrap;
.flex-warp-item {
min-height: 196.24px;
padding: 0 7.5px 15px 15px !important;
}
}
}
}

View File

@ -3,8 +3,8 @@
/* 页面宽度小于576px
------------------------------- */
@media screen and (max-width: $xs) {
.el-cascader__dropdown.el-popper {
overflow: auto;
max-width: 100%;
}
.el-cascader__dropdown.el-popper {
overflow: auto;
max-width: 100%;
}
}

View File

@ -3,7 +3,7 @@
/* 页面宽度小于800px
------------------------------- */
@media screen and (max-width: 800px) {
.el-dialog {
width: 90% !important;
}
.el-dialog {
width: 90% !important;
}
}

View File

@ -3,33 +3,33 @@
/* 页面宽度小于768px
------------------------------- */
@media screen and (max-width: $sm) {
.error {
.error-flex {
flex-direction: column-reverse !important;
height: auto !important;
width: 100% !important;
}
.right,
.left {
flex: unset !important;
display: flex !important;
}
.left-item {
margin: auto !important;
}
.right img {
max-width: 450px !important;
@extend .left-item;
}
}
.error {
.error-flex {
flex-direction: column-reverse !important;
height: auto !important;
width: 100% !important;
}
.right,
.left {
flex: unset !important;
display: flex !important;
}
.left-item {
margin: auto !important;
}
.right img {
max-width: 450px !important;
@extend .left-item;
}
}
}
/* 页面宽度大于768px小于992px
------------------------------- */
@media screen and (min-width: $sm) and (max-width: $md) {
.error {
.error-flex {
padding-left: 30px !important;
}
}
.error {
.error-flex {
padding-left: 30px !important;
}
}
}

View File

@ -3,11 +3,11 @@
/* 页面宽度小于576px
------------------------------- */
@media screen and (max-width: $xs) {
.el-form-item__label {
width: 100% !important;
text-align: left !important;
}
.el-form-item__content {
margin-left: 0 !important;
}
.el-form-item__label {
width: 100% !important;
text-align: left !important;
}
.el-form-item__content {
margin-left: 0 !important;
}
}

View File

@ -3,8 +3,8 @@
/* 页面宽度小于768px
------------------------------- */
@media screen and (max-width: $sm) {
.home-warning-media,
.home-dynamic-media {
margin-top: 15px;
}
.home-warning-media,
.home-dynamic-media {
margin-top: 15px;
}
}

View File

@ -3,53 +3,53 @@
/* 页面宽度小于576px
------------------------------- */
@media screen and (max-width: $xs) {
// MessageBox 弹框
.el-message-box {
width: 80% !important;
}
// MessageBox 弹框
.el-message-box {
width: 80% !important;
}
}
/* 页面宽度小于768px
------------------------------- */
@media screen and (max-width: $sm) {
// Breadcrumb 面包屑
.layout-navbars-breadcrumb-hide {
display: none;
}
// 外链视图
.layout-view-link {
a {
max-width: 80%;
text-align: center;
}
}
// 菜单搜索
.layout-search-dialog {
.el-autocomplete {
width: 80% !important;
}
}
// Breadcrumb 面包屑
.layout-navbars-breadcrumb-hide {
display: none;
}
// 外链视图
.layout-view-link {
a {
max-width: 80%;
text-align: center;
}
}
// 菜单搜索
.layout-search-dialog {
.el-autocomplete {
width: 80% !important;
}
}
}
/* 页面宽度小于1000px
------------------------------- */
@media screen and (max-width: 1000px) {
// 布局配置
.layout-drawer-content-flex {
position: relative;
&::after {
content: '手机版不支持切换布局';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1;
text-align: center;
height: 140px;
line-height: 140px;
background: rgba(255, 255, 255, 0.9);
color: #666666;
}
}
// 布局配置
.layout-drawer-content-flex {
position: relative;
&::after {
content: '手机版不支持切换布局';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1;
text-align: center;
height: 140px;
line-height: 140px;
background: rgba(255, 255, 255, 0.9);
color: #666666;
}
}
}

View File

@ -3,19 +3,19 @@
/* 页面宽度小于576px
------------------------------- */
@media screen and (max-width: $xs) {
.login-container {
.login-content {
width: 90% !important;
padding: 20px 0 !important;
}
.login-content-form-btn {
width: 100% !important;
padding: 12px 0 !important;
}
.login-copyright {
.login-copyright-msg {
white-space: unset !important;
}
}
}
.login-container {
.login-content {
width: 90% !important;
padding: 20px 0 !important;
}
.login-content-form-btn {
width: 100% !important;
padding: 12px 0 !important;
}
.login-copyright {
.login-copyright-msg {
white-space: unset !important;
}
}
}
}

View File

@ -3,13 +3,13 @@
/* 页面宽度小于576px
------------------------------- */
@media screen and (max-width: $xs) {
.el-pager,
.el-pagination__jump {
display: none !important;
}
.el-pager,
.el-pagination__jump {
display: none !important;
}
}
// 默认居中对齐
.el-pagination {
text-align: center !important;
text-align: center !important;
}

View File

@ -3,14 +3,14 @@
/* 页面宽度小于768px
------------------------------- */
@media screen and (max-width: $sm) {
.personal-info {
padding-left: 0 !important;
margin-top: 15px;
}
.personal-recommend-col {
margin-bottom: 15px;
&:last-of-type {
margin-bottom: 0;
}
}
.personal-info {
padding-left: 0 !important;
margin-top: 15px;
}
.personal-recommend-col {
margin-bottom: 15px;
&:last-of-type {
margin-bottom: 0;
}
}
}

View File

@ -3,54 +3,54 @@
/* 页面宽度小于768px
------------------------------- */
@media screen and (max-width: $sm) {
// 滚动条的宽度
::-webkit-scrollbar {
width: 3px !important;
height: 3px !important;
}
::-webkit-scrollbar-track-piece {
background-color: #f8f8f8;
}
// 滚动条的设置
::-webkit-scrollbar-thumb {
background-color: rgba(144, 147, 153, 0.3);
background-clip: padding-box;
min-height: 28px;
border-radius: 5px;
transition: 0.3s background-color;
}
::-webkit-scrollbar-thumb:hover {
background-color: rgba(144, 147, 153, 0.5);
}
// element plus scrollbar
.el-scrollbar__bar.is-vertical {
width: 2px !important;
}
.el-scrollbar__bar.is-horizontal {
height: 2px !important;
}
// 滚动条的宽度
::-webkit-scrollbar {
width: 3px !important;
height: 3px !important;
}
::-webkit-scrollbar-track-piece {
background-color: #f8f8f8;
}
// 滚动条的设置
::-webkit-scrollbar-thumb {
background-color: rgba(144, 147, 153, 0.3);
background-clip: padding-box;
min-height: 28px;
border-radius: 5px;
transition: 0.3s background-color;
}
::-webkit-scrollbar-thumb:hover {
background-color: rgba(144, 147, 153, 0.5);
}
// element plus scrollbar
.el-scrollbar__bar.is-vertical {
width: 2px !important;
}
.el-scrollbar__bar.is-horizontal {
height: 2px !important;
}
}
/* 页面宽度大于768px
------------------------------- */
@media screen and (min-width: 769px) {
// 滚动条的宽度
::-webkit-scrollbar {
width: 7px;
height: 7px;
}
::-webkit-scrollbar-track-piece {
background-color: #f8f8f8;
}
// 滚动条的设置
::-webkit-scrollbar-thumb {
background-color: rgba(144, 147, 153, 0.3);
background-clip: padding-box;
min-height: 28px;
border-radius: 5px;
transition: 0.3s background-color;
}
::-webkit-scrollbar-thumb:hover {
background-color: rgba(144, 147, 153, 0.5);
}
// 滚动条的宽度
::-webkit-scrollbar {
width: 7px;
height: 7px;
}
::-webkit-scrollbar-track-piece {
background-color: #f8f8f8;
}
// 滚动条的设置
::-webkit-scrollbar-thumb {
background-color: rgba(144, 147, 153, 0.3);
background-clip: padding-box;
min-height: 28px;
border-radius: 5px;
transition: 0.3s background-color;
}
::-webkit-scrollbar-thumb:hover {
background-color: rgba(144, 147, 153, 0.5);
}
}

View File

@ -3,9 +3,9 @@
/* 页面宽度小于768px
------------------------------- */
@media screen and (max-width: $sm) {
.tags-view-form {
.tags-view-form-col {
margin-bottom: 20px;
}
}
.tags-view-form {
.tags-view-form-col {
margin-bottom: 20px;
}
}
}

View File

@ -1,34 +1,34 @@
/* Button 按钮
------------------------------- */
@mixin Button($main, $c1, $c2) {
color: set-color($main);
background: set-color($c1);
border-color: set-color($c2);
color: set-color($main);
background: set-color($c1);
border-color: set-color($c2);
}
/* Radio 单选框Checkbox 多选框
------------------------------- */
@mixin RadioCheckbox($name) {
background-color: set-color($name);
border-color: set-color($name);
background-color: set-color($name);
border-color: set-color($name);
}
/* Tag 标签
------------------------------- */
@mixin Tag($main, $c1, $c2) {
color: set-color($main);
background-color: set-color($c1);
border-color: set-color($c2);
color: set-color($main);
background-color: set-color($c1);
border-color: set-color($c2);
}
@mixin TagDark($main, $c1) {
color: set-color($main);
background-color: set-color($c1);
color: set-color($main);
background-color: set-color($c1);
}
/* Alert 警告
------------------------------- */
@mixin Alert($main, $c1, $c2) {
color: set-color($main);
background: set-color($c1);
border: 1px solid set-color($c2);
color: set-color($main);
background: set-color($c1);
border: 1px solid set-color($c2);
}

View File

@ -1,5 +1,5 @@
/* 颜色调用函数
------------------------------- */
@function set-color($key) {
@return var(--color-#{$key});
@return var(--color-#{$key});
}

View File

@ -1,20 +1,20 @@
/* 文本不换行
------------------------------- */
@mixin text-no-wrap() {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
/* 多行文本溢出
------------------------------- */
@mixin text-ellipsis($line: 2) {
overflow: hidden;
word-break: break-all;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: $line;
-webkit-box-orient: vertical;
overflow: hidden;
word-break: break-all;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: $line;
-webkit-box-orient: vertical;
}
/* 滚动条(页面未使用) div 中使用
@ -23,22 +23,22 @@
// @include scrollBar;
// }
@mixin scrollBar {
// 滚动条凹槽的颜色还可以设置边框属性
&::-webkit-scrollbar-track-piece {
background-color: #f8f8f8;
}
// 滚动条的宽度
&::-webkit-scrollbar {
width: 9px;
height: 9px;
}
// 滚动条的设置
&::-webkit-scrollbar-thumb {
background-color: #dddddd;
background-clip: padding-box;
min-height: 28px;
}
&::-webkit-scrollbar-thumb:hover {
background-color: #bbb;
}
// 滚动条凹槽的颜色还可以设置边框属性
&::-webkit-scrollbar-track-piece {
background-color: #f8f8f8;
}
// 滚动条的宽度
&::-webkit-scrollbar {
width: 9px;
height: 9px;
}
// 滚动条的设置
&::-webkit-scrollbar-thumb {
background-color: #dddddd;
background-clip: padding-box;
min-height: 28px;
}
&::-webkit-scrollbar-thumb:hover {
background-color: #bbb;
}
}

View File

@ -1,16 +1,16 @@
/* wangeditor富文本编辑器
------------------------------- */
.w-e-toolbar {
border: 1px solid #ebeef5 !important;
border-bottom: 1px solid #ebeef5 !important;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
z-index: 2 !important;
border: 1px solid #ebeef5 !important;
border-bottom: 1px solid #ebeef5 !important;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
z-index: 2 !important;
}
.w-e-text-container {
border: 1px solid #ebeef5 !important;
border-top: none !important;
border-bottom-left-radius: 3px;
border-bottom-right-radius: 3px;
z-index: 1 !important;
border: 1px solid #ebeef5 !important;
border-top: none !important;
border-bottom-left-radius: 3px;
border-bottom-right-radius: 3px;
z-index: 1 !important;
}

View File

@ -1,11 +1,11 @@
// 判断两数组是否相同
export function judementSameArr(news: Array<string>, old: Array<string>) {
let count = 0
const leng = old.length
for (let i in old) {
for (let j in news) {
if (old[i] === news[j]) count++
}
}
return count === leng ? true : false
}
let count = 0;
const leng = old.length;
for (let i in old) {
for (let j in news) {
if (old[i] === news[j]) count++;
}
}
return count === leng ? true : false;
}

View File

@ -1,31 +1,31 @@
import type { App } from 'vue'
import { store } from "/@/store/index.ts";
import { judementSameArr } from '/@/utils/arrayOperation.ts'
import type { App } from 'vue';
import { store } from '/@/store/index.ts';
import { judementSameArr } from '/@/utils/arrayOperation.ts';
export function authDirective(app: App) {
// 单个权限验证v-auth="xxx"
app.directive('auth', {
mounted(el, binding) {
if (!store.state.userInfos.authBtnList.some((v: any) => v === binding.value)) el.parentNode.removeChild(el)
}
})
// 多个权限验证满足一个则显示v-auths="[xxx,xxx]"
app.directive('auths', {
mounted(el, binding) {
let flag = false
store.state.userInfos.authBtnList.map((val: any) => {
binding.value.map((v: any) => {
if (val === v) flag = true
})
})
if (!flag) el.parentNode.removeChild(el)
}
})
// 多个权限验证全部满足则显示v-auth-all="[xxx,xxx]"
app.directive('auth-all', {
mounted(el, binding) {
const flag = judementSameArr(binding.value, store.state.userInfos.authBtnList)
if (!flag) el.parentNode.removeChild(el)
}
})
}
// 单个权限验证v-auth="xxx"
app.directive('auth', {
mounted(el, binding) {
if (!store.state.userInfos.userInfos.authBtnList.some((v: any) => v === binding.value)) el.parentNode.removeChild(el);
},
});
// 多个权限验证满足一个则显示v-auths="[xxx,xxx]"
app.directive('auths', {
mounted(el, binding) {
let flag = false;
store.state.userInfos.userInfos.authBtnList.map((val: any) => {
binding.value.map((v: any) => {
if (val === v) flag = true;
});
});
if (!flag) el.parentNode.removeChild(el);
},
});
// 多个权限验证全部满足则显示v-auth-all="[xxx,xxx]"
app.directive('auth-all', {
mounted(el, binding) {
const flag = judementSameArr(binding.value, store.state.userInfos.userInfos.authBtnList);
if (!flag) el.parentNode.removeChild(el);
},
});
}

View File

@ -1,24 +1,23 @@
import { store } from "/@/store/index.ts";
import { judementSameArr } from '/@/utils/arrayOperation.ts'
import { store } from '/@/store/index.ts';
import { judementSameArr } from '/@/utils/arrayOperation.ts';
// 单个权限验证
export function auth(value: string) {
return store.state.userInfos.authBtnList.some((v: any) => v === value)
return store.state.userInfos.userInfos.authBtnList.some((v: any) => v === value);
}
// 多个权限验证,满足一个则为 true
export function auths(value: Array<string>) {
let flag = false
store.state.userInfos.authBtnList.map((val: any) => {
value.map((v: any) => {
if (val === v) flag = true
})
})
return flag
let flag = false;
store.state.userInfos.userInfos.authBtnList.map((val: any) => {
value.map((v: any) => {
if (val === v) flag = true;
});
});
return flag;
}
// 多个权限验证,全部满足则为 true
export function authAll(value: Array<string>) {
return judementSameArr(value, store.state.userInfos.authBtnList)
return judementSameArr(value, store.state.userInfos.userInfos.authBtnList);
}

View File

@ -12,42 +12,43 @@
* formatDate(date, "YYYY-mm-dd HH:MM:SS WWW QQQQ") // 2020-02-09 14:46:12 星期日 第一季度
*/
export function formatDate(date: Date, format: string) {
let we = date.getDay() // 星期
let qut = Math.floor((date.getMonth() + 3) / 3).toString() // 季度
const opt: any = {
"Y+": date.getFullYear().toString(), // 年
"m+": (date.getMonth() + 1).toString(), // 月(月份从0开始要+1)
"d+": date.getDate().toString(), // 日
"H+": date.getHours().toString(), // 时
"M+": date.getMinutes().toString(), // 分
"S+": date.getSeconds().toString(), // 秒
"q+": qut, // 季度
}
// 中文数字 (星期)
const week: any = {
"0": "日",
"1": "一",
"2": "二",
"3": "三",
"4": "四",
"5": "五",
"6": "六",
}
// 中文数字(季度)
const quarter: any = {
"1": "一",
"2": "二",
"3": "三",
"4": "四",
}
if (/(W+)/.test(format)) format = format.replace(RegExp.$1, RegExp.$1.length > 1 ? RegExp.$1.length > 2 ? "星期" + week[we] : "周" + week[we] : week[we])
if (/(Q+)/.test(format)) format = format.replace(RegExp.$1, RegExp.$1.length == 4 ? "第" + quarter[qut] + "季度" : quarter[qut])
for (let k in opt) {
let r = new RegExp("(" + k + ")").exec(format);
// 若输入的长度不为1则前面补零
if (r) format = format.replace(r[1], RegExp.$1.length == 1 ? opt[k] : opt[k].padStart(RegExp.$1.length, "0"))
}
return format
let we = date.getDay(); // 星期
let qut = Math.floor((date.getMonth() + 3) / 3).toString(); // 季度
const opt: any = {
'Y+': date.getFullYear().toString(), // 年
'm+': (date.getMonth() + 1).toString(), // 月(月份从0开始要+1)
'd+': date.getDate().toString(), // 日
'H+': date.getHours().toString(), // 时
'M+': date.getMinutes().toString(), // 分
'S+': date.getSeconds().toString(), // 秒
'q+': qut, // 季度
};
// 中文数字 (星期)
const week: any = {
'0': '日',
'1': '一',
'2': '二',
'3': '三',
'4': '四',
'5': '五',
'6': '六',
};
// 中文数字(季度)
const quarter: any = {
'1': '一',
'2': '二',
'3': '三',
'4': '四',
};
if (/(W+)/.test(format))
format = format.replace(RegExp.$1, RegExp.$1.length > 1 ? (RegExp.$1.length > 2 ? '星期' + week[we] : '周' + week[we]) : week[we]);
if (/(Q+)/.test(format)) format = format.replace(RegExp.$1, RegExp.$1.length == 4 ? '第' + quarter[qut] + '季度' : quarter[qut]);
for (let k in opt) {
let r = new RegExp('(' + k + ')').exec(format);
// 若输入的长度不为1则前面补零
if (r) format = format.replace(r[1], RegExp.$1.length == 1 ? opt[k] : opt[k].padStart(RegExp.$1.length, '0'));
}
return format;
}
/**
@ -67,52 +68,52 @@ export function formatDate(date: Date, format: string) {
* formatPast("2020-06-01") // 2020-06-01
* formatPast("2020-06-01", "YYYY-mm-dd HH:MM:SS WWW QQQQ") // 2020-06-01 08:00:00 星期一 第二季度
*/
export function formatPast(param: any, format: string = "YYYY-mm-dd") {
// 传入格式处理、存储转换值
let t: any, s: any
// 获取js 时间戳
let time: any = new Date().getTime()
// 是否是对象
typeof param === "string" || "object" ? (t = new Date(param).getTime()) : (t = param)
// 当前时间戳 - 传入时间戳
time = Number.parseInt(`${time - t}`)
if (time < 10000) {
// 10秒内
return "刚刚"
} else if (time < 60000 && time >= 10000) {
// 超过10秒少于1分钟内
s = Math.floor(time / 1000)
return `${s}秒前`
} else if (time < 3600000 && time >= 60000) {
// 超过1分钟少于1小时
s = Math.floor(time / 60000)
return `${s}分钟前`
} else if (time < 86400000 && time >= 3600000) {
// 超过1小时少于24小时
s = Math.floor(time / 3600000)
return `${s}小时前`
} else if (time < 259200000 && time >= 86400000) {
// 超过1天少于3天内
s = Math.floor(time / 86400000)
return `${s}天前`
} else {
// 超过3天
let date = typeof param === "string" || "object" ? new Date(param) : param
return formatDate(date, format);
}
export function formatPast(param: any, format: string = 'YYYY-mm-dd') {
// 传入格式处理、存储转换值
let t: any, s: any;
// 获取js 时间戳
let time: any = new Date().getTime();
// 是否是对象
typeof param === 'string' || 'object' ? (t = new Date(param).getTime()) : (t = param);
// 当前时间戳 - 传入时间戳
time = Number.parseInt(`${time - t}`);
if (time < 10000) {
// 10秒内
return '刚刚';
} else if (time < 60000 && time >= 10000) {
// 超过10秒少于1分钟内
s = Math.floor(time / 1000);
return `${s}秒前`;
} else if (time < 3600000 && time >= 60000) {
// 超过1分钟少于1小时
s = Math.floor(time / 60000);
return `${s}分钟前`;
} else if (time < 86400000 && time >= 3600000) {
// 超过1小时少于24小时
s = Math.floor(time / 3600000);
return `${s}小时前`;
} else if (time < 259200000 && time >= 86400000) {
// 超过1天少于3天内
s = Math.floor(time / 86400000);
return `${s}天前`;
} else {
// 超过3天
let date = typeof param === 'string' || 'object' ? new Date(param) : param;
return formatDate(date, format);
}
}
/**
* formatAxis(new Date()) // 上午好
*/
export function formatAxis(param: any) {
let hour: number = new Date(param).getHours()
if (hour < 6) return "凌晨好"
else if (hour < 9) return "早上好"
else if (hour < 12) return "上午好"
else if (hour < 14) return "中午好"
else if (hour < 17) return "下午好"
else if (hour < 19) return "傍晚好"
else if (hour < 22) return "晚上好"
else return "夜里好"
let hour: number = new Date(param).getHours();
if (hour < 6) return '凌晨好';
else if (hour < 9) return '早上好';
else if (hour < 12) return '上午好';
else if (hour < 14) return '中午好';
else if (hour < 17) return '下午好';
else if (hour < 19) return '傍晚好';
else if (hour < 22) return '晚上好';
else return '夜里好';
}

View File

@ -1,111 +1,96 @@
import { nextTick } from "vue"
import { nextTick } from 'vue';
// 获取阿里字体图标
const getAlicdnIconfont = () => {
return new Promise((resolve, reject) => {
nextTick(() => {
const styles: any = document.styleSheets
let sheetsList = []
let sheetsIconList = []
for (let i = 0; i < styles.length; i++) {
if (styles[i].href && styles[i].href.indexOf("at.alicdn.com") > -1) {
sheetsList.push(styles[i])
}
}
for (let i = 0; i < sheetsList.length; i++) {
for (let j = 0; j < sheetsList[i].cssRules.length; j++) {
if (
sheetsList[i].cssRules[j].selectorText &&
sheetsList[i].cssRules[j].selectorText.indexOf(".icon-") > -1
) {
sheetsIconList.push(
`${sheetsList[i].cssRules[j].selectorText
.substring(1, sheetsList[i].cssRules[j].selectorText.length)
.replace(/\:\:before/gi, "")}`
)
}
}
}
if (sheetsIconList.length > 0) resolve(sheetsIconList)
else reject('未获取到值,请刷新重试')
})
})
}
return new Promise((resolve, reject) => {
nextTick(() => {
const styles: any = document.styleSheets;
let sheetsList = [];
let sheetsIconList = [];
for (let i = 0; i < styles.length; i++) {
if (styles[i].href && styles[i].href.indexOf('at.alicdn.com') > -1) {
sheetsList.push(styles[i]);
}
}
for (let i = 0; i < sheetsList.length; i++) {
for (let j = 0; j < sheetsList[i].cssRules.length; j++) {
if (sheetsList[i].cssRules[j].selectorText && sheetsList[i].cssRules[j].selectorText.indexOf('.icon-') > -1) {
sheetsIconList.push(
`${sheetsList[i].cssRules[j].selectorText.substring(1, sheetsList[i].cssRules[j].selectorText.length).replace(/\:\:before/gi, '')}`
);
}
}
}
if (sheetsIconList.length > 0) resolve(sheetsIconList);
else reject('未获取到值,请刷新重试');
});
});
};
// 初始化获取 css 样式,获取 element plus 自带图标
const elementPlusIconfont = () => {
return new Promise((resolve, reject) => {
nextTick(() => {
const styles: any = document.styleSheets
let sheetsIconList = []
for (let i = 0; i < styles.length; i++) {
for (let j = 0; j < styles[i].cssRules.length; j++) {
if (
styles[i].cssRules[j].selectorText &&
styles[i].cssRules[j].selectorText.indexOf(".el-icon-") === 0
) {
sheetsIconList.push(
`${styles[i].cssRules[j].selectorText
.substring(1, styles[i].cssRules[j].selectorText.length)
.replace(/\:\:before/gi, "")}`
)
}
}
}
if (sheetsIconList.length > 0) resolve(sheetsIconList)
else reject('未获取到值,请刷新重试')
})
})
}
return new Promise((resolve, reject) => {
nextTick(() => {
const styles: any = document.styleSheets;
let sheetsIconList = [];
for (let i = 0; i < styles.length; i++) {
for (let j = 0; j < styles[i].cssRules.length; j++) {
if (styles[i].cssRules[j].selectorText && styles[i].cssRules[j].selectorText.indexOf('.el-icon-') === 0) {
sheetsIconList.push(
`${styles[i].cssRules[j].selectorText.substring(1, styles[i].cssRules[j].selectorText.length).replace(/\:\:before/gi, '')}`
);
}
}
}
if (sheetsIconList.length > 0) resolve(sheetsIconList);
else reject('未获取到值,请刷新重试');
});
});
};
// 初始化获取 css 样式,这里使用 fontawesome 的图标
const awesomeIconfont = () => {
return new Promise((resolve, reject) => {
nextTick(() => {
const styles: any = document.styleSheets
let sheetsList = []
let sheetsIconList = []
for (let i = 0; i < styles.length; i++) {
if (
styles[i].href &&
styles[i].href.indexOf("netdna.bootstrapcdn.com") > -1
) {
sheetsList.push(styles[i])
}
}
for (let i = 0; i < sheetsList.length; i++) {
for (let j = 0; j < sheetsList[i].cssRules.length; j++) {
if (
sheetsList[i].cssRules[j].selectorText &&
sheetsList[i].cssRules[j].selectorText.indexOf(".fa-") === 0 &&
sheetsList[i].cssRules[j].selectorText.indexOf(",") === -1
) {
sheetsIconList.push(
`${sheetsList[i].cssRules[j].selectorText
.substring(1, sheetsList[i].cssRules[j].selectorText.length)
.replace(/\:\:before/gi, "")}`
)
}
}
}
if (sheetsIconList.length > 0) resolve(sheetsIconList)
else reject('未获取到值,请刷新重试')
})
})
}
return new Promise((resolve, reject) => {
nextTick(() => {
const styles: any = document.styleSheets;
let sheetsList = [];
let sheetsIconList = [];
for (let i = 0; i < styles.length; i++) {
if (styles[i].href && styles[i].href.indexOf('netdna.bootstrapcdn.com') > -1) {
sheetsList.push(styles[i]);
}
}
for (let i = 0; i < sheetsList.length; i++) {
for (let j = 0; j < sheetsList[i].cssRules.length; j++) {
if (
sheetsList[i].cssRules[j].selectorText &&
sheetsList[i].cssRules[j].selectorText.indexOf('.fa-') === 0 &&
sheetsList[i].cssRules[j].selectorText.indexOf(',') === -1
) {
sheetsIconList.push(
`${sheetsList[i].cssRules[j].selectorText.substring(1, sheetsList[i].cssRules[j].selectorText.length).replace(/\:\:before/gi, '')}`
);
}
}
}
if (sheetsIconList.length > 0) resolve(sheetsIconList);
else reject('未获取到值,请刷新重试');
});
});
};
// 定义导出方法集合
const initIconfont = {
ali: () => {
return getAlicdnIconfont()
},
ele: () => {
return elementPlusIconfont()
},
awe: () => {
return awesomeIconfont()
}
}
ali: () => {
return getAlicdnIconfont();
},
ele: () => {
return elementPlusIconfont();
},
awe: () => {
return awesomeIconfont();
},
};
// 导出方法
export default initIconfont
export default initIconfont;

View File

@ -1,27 +1,27 @@
import axios from "axios"
import { ElMessage, ElMessageBox } from "element-plus"
import { clearSession, getSession } from "/@/utils/storage.ts"
import router, { resetRoute } from "/@/router/index.ts"
import axios from 'axios';
import { ElMessage, ElMessageBox } from 'element-plus';
import { clearSession, getSession } from '/@/utils/storage.ts';
import router, { resetRoute } from '/@/router/index.ts';
// 配置新建一个 axios 实例
const service = axios.create({
baseURL: 'http://localhost:10000/',
timeout: 50000,
headers: { "Content-Type": "application/json" }
headers: { 'Content-Type': 'application/json' },
});
// 添加请求拦截器
service.interceptors.request.use(
(config) => {
// 在发送请求之前做些什么 token
if (getSession("token")) {
config.headers.common["Authorization"] = `${getSession("token")}`
if (getSession('token')) {
config.headers.common['Authorization'] = `${getSession('token')}`;
}
return config
return config;
},
(error) => {
// 对请求错误做些什么
return Promise.reject(error)
return Promise.reject(error);
}
);
@ -29,32 +29,34 @@ service.interceptors.request.use(
service.interceptors.response.use(
(response) => {
// 对响应数据做点什么
const res = response.data
const res = response.data;
if (res.code && res.code !== 0) {
// `token` 过期或者账号已在别处登录
if (res.code === 401 || res.code === 4001) {
clearSession(); // 清除浏览器全部临时缓存
router.push("/login") // 去登录页面
resetRoute() // 删除/重置路由
ElMessageBox.alert('你已被登出,请重新登录', '提示', {}).then(() => { }).catch(() => { })
router.push('/login'); // 去登录页面
resetRoute(); // 删除/重置路由
ElMessageBox.alert('你已被登出,请重新登录', '提示', {})
.then(() => {})
.catch(() => {});
}
return Promise.reject(service.interceptors.response)
return Promise.reject(service.interceptors.response);
} else {
return response.data
return response.data;
}
},
(error) => {
// 对响应错误做点什么
if (error.message.indexOf("timeout") != -1) {
ElMessage.error("网络超时")
} else if (error.message == "Network Error") {
ElMessage.error("网络连接错误")
if (error.message.indexOf('timeout') != -1) {
ElMessage.error('网络超时');
} else if (error.message == 'Network Error') {
ElMessage.error('网络连接错误');
} else {
if (error.response.data) ElMessage.error(error.response.statusText)
else ElMessage.error('接口路径找不到')
if (error.response.data) ElMessage.error(error.response.statusText);
else ElMessage.error('接口路径找不到');
}
return Promise.reject(error)
return Promise.reject(error);
}
);
export default service
export default service;

View File

@ -1,45 +1,42 @@
// 字体图标 url
const cssCdnUrlList: Array<string> = [
'//at.alicdn.com/t/font_2298093_n459lh5kpoh.css',
'//netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css'
]
'//at.alicdn.com/t/font_2298093_rwhkigmjh19.css',
'//netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css',
];
// 第三方 js url
const jsCdnUrlList: Array<string> = [
'https://gw.alipayobjects.com/os/antv/pkg/_antv.g6-3.8.1/dist/g6.min.js',
'https://cdn.bootcdn.net/ajax/libs/qrcodejs/1.0.0/qrcode.min.js'
]
const jsCdnUrlList: Array<string> = [];
// 动态设置字体图标
export function setCssCdn() {
if (cssCdnUrlList.length <= 0) return false
cssCdnUrlList.map(v => {
let link = document.createElement('link')
link.rel = 'stylesheet'
link.href = v
link.crossOrigin = 'anonymous'
document.getElementsByTagName('head')[0].appendChild(link)
})
if (cssCdnUrlList.length <= 0) return false;
cssCdnUrlList.map((v) => {
let link = document.createElement('link');
link.rel = 'stylesheet';
link.href = v;
link.crossOrigin = 'anonymous';
document.getElementsByTagName('head')[0].appendChild(link);
});
}
// 批量设置第三方js
export function setJsCdn() {
if (jsCdnUrlList.length <= 0) return false
jsCdnUrlList.map(v => {
let link = document.createElement('script')
link.src = v
document.body.appendChild(link)
})
if (jsCdnUrlList.length <= 0) return false;
jsCdnUrlList.map((v) => {
let link = document.createElement('script');
link.src = v;
document.body.appendChild(link);
});
}
// 设置执行函数
const setIntroduction = {
cssCdn: () => {
setCssCdn()
},
jsCdn: () => {
setJsCdn()
}
}
cssCdn: () => {
setCssCdn();
},
jsCdn: () => {
setJsCdn();
},
};
// 导出函数方法
export default setIntroduction
export default setIntroduction;

View File

@ -1,37 +1,37 @@
// 1. localStorage
// 设置永久缓存
export function setLocal(key: string, val: any) {
window.localStorage.setItem(key, JSON.stringify(val))
window.localStorage.setItem(key, JSON.stringify(val));
}
// 获取永久缓存
export function getLocal(key: string) {
let json: any = window.localStorage.getItem(key)
return JSON.parse(json)
let json: any = window.localStorage.getItem(key);
return JSON.parse(json);
}
// 移除永久缓存
export function removeLocal(key: string) {
window.localStorage.removeItem(key)
window.localStorage.removeItem(key);
}
// 移除全部永久缓存
export function clearLocal() {
window.localStorage.clear()
window.localStorage.clear();
}
// 2. sessionStorage
// 设置临时缓存
export function setSession(key: string, val: any) {
window.sessionStorage.setItem(key, JSON.stringify(val))
window.sessionStorage.setItem(key, JSON.stringify(val));
}
// 获取临时缓存
export function getSession(key: string) {
let json: any = window.sessionStorage.getItem(key)
return JSON.parse(json)
let json: any = window.sessionStorage.getItem(key);
return JSON.parse(json);
}
// 移除临时缓存
export function removeSession(key: string) {
window.sessionStorage.removeItem(key)
window.sessionStorage.removeItem(key);
}
// 移除全部临时缓存
export function clearSession() {
window.sessionStorage.clear()
window.sessionStorage.clear();
}

View File

@ -1,39 +1,39 @@
import { ElMessage } from 'element-plus'
import { ElMessage } from 'element-plus';
// hex颜色转rgb颜色
export function hexToRgb(str: any) {
let hexs: any = ''
let reg = /^\#?[0-9A-Fa-f]{6}$/
if (!reg.test(str)) return ElMessage({ type: 'warning', message: "输入错误的hex" })
str = str.replace("#", "")
hexs = str.match(/../g)
for (let i = 0; i < 3; i++) hexs[i] = parseInt(hexs[i], 16)
return hexs
let hexs: any = '';
let reg = /^\#?[0-9A-Fa-f]{6}$/;
if (!reg.test(str)) return ElMessage({ type: 'warning', message: '输入错误的hex' });
str = str.replace('#', '');
hexs = str.match(/../g);
for (let i = 0; i < 3; i++) hexs[i] = parseInt(hexs[i], 16);
return hexs;
}
// rgb颜色转Hex颜色
export function rgbToHex(r: any, g: any, b: any) {
let reg = /^\d{1,3}$/
if (!reg.test(r) || !reg.test(g) || !reg.test(b)) return ElMessage({ type: 'warning', message: "输入错误的rgb颜色值" })
let hexs = [r.toString(16), g.toString(16), b.toString(16)]
for (let i = 0; i < 3; i++) if (hexs[i].length == 1) hexs[i] = `0${hexs[i]}`
return `#${hexs.join("")}`
let reg = /^\d{1,3}$/;
if (!reg.test(r) || !reg.test(g) || !reg.test(b)) return ElMessage({ type: 'warning', message: '输入错误的rgb颜色值' });
let hexs = [r.toString(16), g.toString(16), b.toString(16)];
for (let i = 0; i < 3; i++) if (hexs[i].length == 1) hexs[i] = `0${hexs[i]}`;
return `#${hexs.join('')}`;
}
// 加深颜色值level为加深的程度限0-1之间
export function getDarkColor(color: any, level: number) {
let reg = /^\#?[0-9A-Fa-f]{6}$/
if (!reg.test(color)) return ElMessage({ type: 'warning', message: "输入错误的hex颜色值" })
let rgb = hexToRgb(color)
for (let i = 0; i < 3; i++) rgb[i] = Math.floor(rgb[i] * (1 - level))
return rgbToHex(rgb[0], rgb[1], rgb[2])
let reg = /^\#?[0-9A-Fa-f]{6}$/;
if (!reg.test(color)) return ElMessage({ type: 'warning', message: '输入错误的hex颜色值' });
let rgb = hexToRgb(color);
for (let i = 0; i < 3; i++) rgb[i] = Math.floor(rgb[i] * (1 - level));
return rgbToHex(rgb[0], rgb[1], rgb[2]);
}
// 变浅颜色值level为加深的程度限0-1之间
export function getLightColor(color: any, level: number) {
let reg = /^\#?[0-9A-Fa-f]{6}$/
if (!reg.test(color)) return ElMessage({ type: 'warning', message: "输入错误的hex颜色值" })
let rgb = hexToRgb(color)
for (let i = 0; i < 3; i++) rgb[i] = Math.floor((255 - rgb[i]) * level + rgb[i])
return rgbToHex(rgb[0], rgb[1], rgb[2])
}
let reg = /^\#?[0-9A-Fa-f]{6}$/;
if (!reg.test(color)) return ElMessage({ type: 'warning', message: '输入错误的hex颜色值' });
let rgb = hexToRgb(color);
for (let i = 0; i < 3; i++) rgb[i] = Math.floor((255 - rgb[i]) * level + rgb[i]);
return rgbToHex(rgb[0], rgb[1], rgb[2]);
}

View File

@ -1,112 +0,0 @@
// 布局配置
export default {
// 是否开启布局配置抽屉
isDrawer: false,
/*
------------------------------- */
// 默认 primary 颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
primary: "#409eff",
// 默认 success 颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
success: "#67c23a",
// 默认 info 颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
info: "#909399",
// 默认 warning 颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
warning: "#e6a23c",
// 默认 danger 颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
danger: "#f56c6c",
/* 菜单 /
------------------------------- */
// 默认顶栏导航背景颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
topBar: "#ffffff",
// 默认菜单导航背景颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
menuBar: "#545c64",
// 默认分栏菜单背景颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
columnsMenuBar: '#545c64',
// 默认顶栏导航字体颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
topBarColor: "#606266",
// 默认菜单导航字体颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
menuBarColor: "#eaeaea",
// 默认分栏菜单字体颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
columnsMenuBarColor: '#e6e6e6',
// 是否开启顶栏背景颜色渐变
isTopBarColorGradual: false,
// 是否开启菜单背景颜色渐变
isMenuBarColorGradual: false,
// 是否开启菜单字体背景高亮
isMenuBarColorHighlight: false,
// 是否开启菜单字体背景高亮
/*
------------------------------- */
// 是否开启菜单水平折叠效果
isCollapse: false,
// 是否开启菜单手风琴效果
isUniqueOpened: false,
// 是否开启固定 Header
isFixedHeader: false,
// 初始化变量,用于更新菜单 el-scrollbar 的高度,请勿删除
isFixedHeaderChange: false,
// 是否开启经典布局分割菜单(仅经典布局生效)
isClassicSplitMenu: false,
// 是否开启自动锁屏
isLockScreen: false,
// 开启自动锁屏倒计时(s/秒)
lockScreenTime: 30,
/*
------------------------------- */
// 是否开启侧边栏 Logo
isShowLogo: false,
// 初始化变量,用于 el-scrollbar 的高度更新,请勿删除
isShowLogoChange: false,
// 是否开启 Breadcrumb
isBreadcrumb: true,
// 是否开启 Tagsview
isTagsview: true,
// 是否开启 Breadcrumb 图标
isBreadcrumbIcon: false,
// 是否开启 Tagsview 图标
isTagsviewIcon: false,
// 是否开启 TagsView 缓存
isCacheTagsView: false,
// 是否开启 TagsView 拖拽
isSortableTagsView: true,
// 是否开启 Footer 底部版权信息
isFooter: false,
// 是否开启灰色模式
isGrayscale: false,
// 是否开启色弱模式
isInvert: false,
// 是否开启水印
isWartermark: false,
// 水印文案
wartermarkText: 'small@小柒',
/*
------------------------------- */
// 默认 Tagsview 风格,可选 1、 tagsStyleOne 2、 tagsStyleTwo 3、 tagsStyleThree 4、 tagsStyleFour
tagsStyle: 'tagsStyleOne',
// 默认主页面切换动画,可选 1、 slideRight 2、 slideLeft 3、 opacitys
animation: 'slideRight',
// 默认分栏高亮风格,可选 1、 圆角 columnsRound 2、 卡片 columnsCard
columnsAsideStyle: 'columnsRound',
/*
------------------------------- */
// 默认布局,可选 1、默认 defaults 2、经典 classic 3、横向 transverse 4、分栏 columns
layout: 'defaults',
/*
------------------------------- */
// 是否开启后端控制路由
isRequestRoutes: false,
/* 全局网站标题 /
------------------------------- */
// 网站主标题(菜单导航、浏览器当前网页标题)
globalTitle: 'vue-next-admin',
// 网站副标题(登录页顶部文字)
globalViceTitle: 'SMALL@小柒'
}

View File

@ -1,219 +0,0 @@
/**
* 2020.11.29 lyt 整理
* 工具类集合适用于平时开发
* 后期改成 xx.ts
*/
// 小数或整数(不可以负数)
export function verifyNumberIntegerAndFloat(val) {
// 匹配空格
let v = val.replace(/(^\s*)|(\s*$)/g, "")
// 只能是数字和小数点,不能是其他输入
v = v.replace(/[^\d.]/g, "")
// 以0开始只能输入一个
v = v.replace(/^0{2}$/g, "0")
// 保证第一位只能是数字,不能是点
v = v.replace(/^\./g, "")
// 小数只能出现1位
v = v.replace(".", "$#$").replace(/\./g, "").replace("$#$", ".")
// 小数点后面保留2位
v = v.replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3')
// 返回结果
return v
}
// 正整数验证
export function verifiyNumberInteger(val) {
// 匹配空格
let v = val.replace(/(^\s*)|(\s*$)/g, "")
// 去掉 '.' , 防止贴贴的时候出现问题 如 0.1.12.12
v = v.replace(/[\.]*/g, "")
// 去掉以 0 开始后面的数, 防止贴贴的时候出现问题 如 00121323
v = v.replace(/(^0[\d]*)$/g, "0")
// 首位是0,只能出现一次
v = v.replace(/^0\d$/g, "0")
// 只匹配数字
v = v.replace(/[^\d]/g, "")
// 返回结果
return v
}
// 去掉中文及空格
export function verifyCnAndSpace(val) {
// 匹配中文与空格
let v = val.replace(/[\u4e00-\u9fa5\s]+/g, "")
// 匹配空格
v = v.replace(/(^\s*)|(\s*$)/g, "")
// 返回结果
return v
}
// 去掉英文及空格
export function verifyEnAndSpace(val) {
// 匹配英文与空格
let v = val.replace(/[a-zA-Z]+/g, "")
// 匹配空格
v = v.replace(/(^\s*)|(\s*$)/g, "")
// 返回结果
return v
}
// 禁止输入空格
export function verifyAndSpace(val) {
// 匹配空格
let v = val.replace(/(^\s*)|(\s*$)/g, "")
// 返回结果
return v
}
// 金额用 `,` 区分开
export function verifyNumberComma(val) {
// 调用小数或整数(不可以负数)方法
let v = verifyNumberIntegerAndFloat(val)
// 字符串转成数组
v = v.toString().split(".")
// \B 匹配非单词边界,两边都是单词字符或者两边都是非单词字符
v[0] = v[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",")
// 数组转字符串
v = v.join(".")
// 返回结果
return v
}
// 匹配文字变色(搜索时)
export function verifyTextColor(val, text = '', color = 'red') {
// 返回内容,添加颜色
let v = text.replace(new RegExp(val, 'gi'), `<span style='color: ${color}'>${val}</span>`)
// 返回结果
return v
}
// 数字转中文大写
export function verifyNumberCnUppercase(val, unit = '仟佰拾亿仟佰拾万仟佰拾元角分', v = '') {
// 当前内容字符串添加 2个0为什么??
val += "00"
// 返回某个指定的字符串值在字符串中首次出现的位置,没有出现,则该方法返回 -1
let lookup = val.indexOf('.')
// substring不包含结束下标内容substr包含结束下标内容
if (lookup >= 0) val = val.substring(0, lookup) + val.substr(lookup + 1, 2)
// 根据内容 val 的长度,截取返回对应大写
unit = unit.substr(unit.length - val.length)
// 循环截取拼接大写
for (let i = 0; i < val.length; i++) {
v += '零壹贰叁肆伍陆柒捌玖'.substr(val.substr(i, 1), 1) + unit.substr(i, 1)
}
// 正则处理
v = v.replace(/零角零分$/, '整').replace(/零[仟佰拾]/g, '零').replace(/零{2,}/g, '零').replace(/零([亿|万])/g, '$1').replace(/零+元/, '元').replace(/亿零{0,3}万/, '亿').replace(/^元/, "零元")
// 返回结果
return v
}
// 手机号码
export function verifyPhone(val) {
// false: 手机号码不正确
if (!/^((12[0-9])|(13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\d{8}$/.test(val)) return false
// true: 手机号码正确
else return true
}
// 国内电话号码
export function verifyTelPhone(val) {
// false: 国内电话号码不正确
if (!/\d{3}-\d{8}|\d{4}-\d{7}/.test(val)) return false
// true: 国内电话号码正确
else return true
}
// 登录账号 (字母开头允许5-16字节允许字母数字下划线)
export function verifyAccount(val) {
// false: 登录账号不正确
if (!/^[a-zA-Z][a-zA-Z0-9_]{4,15}$/.test(val)) return false
// true: 登录账号正确
else return true
}
// 密码 (以字母开头长度在6~16之间只能包含字母、数字和下划线)
export function verifyPassword(val) {
// false: 密码不正确
if (!/^[a-zA-Z]\w{5,15}$/.test(val)) return false
// true: 密码正确
else return true
}
// 强密码 (字母+数字+特殊字符长度在6-16之间)
export function verifyPasswordPowerful(val) {
// false: 强密码不正确
if (!/^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&\.*]+$)(?![a-zA-z\d]+$)(?![a-zA-z!@#$%^&\.*]+$)(?![\d!@#$%^&\.*]+$)[a-zA-Z\d!@#$%^&\.*]{6,16}$/.test(val)) return false
// true: 强密码正确
else return true
}
// 密码强度
export function verifyPasswordStrength(val) {
let v = ''
// 弱:纯数字,纯字母,纯特殊字符
if (/^(?:\d+|[a-zA-Z]+|[!@#$%^&\.*]+){6,16}$/.test(val)) v = '弱'
// 中:字母+数字,字母+特殊字符,数字+特殊字符
if (/^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&\.*]+$)[a-zA-Z\d!@#$%^&\.*]{6,16}$/.test(val)) v = '中'
// 强:字母+数字+特殊字符
if (/^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&\.*]+$)(?![a-zA-z\d]+$)(?![a-zA-z!@#$%^&\.*]+$)(?![\d!@#$%^&\.*]+$)[a-zA-Z\d!@#$%^&\.*]{6,16}$/.test(val)) v = '强'
// 返回结果
return v
}
// IP地址
export function verifyIPAddress(val) {
// false: IP地址不正确
if (!/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/.test(val)) return false
// true: IP地址正确
else return true
}
// 邮箱
export function verifyEmail(val) {
// false: 邮箱不正确
if (!/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(val)) return false
// true: 邮箱正确
else return true
}
// 身份证
export function verifyIdCard(val) {
// false: 身份证不正确
if (!/^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/.test(val)) return false
// true: 身份证正确
else return true
}
// 姓名
export function verifyFullName(val) {
// false: 姓名不正确
if (!/^[\u4e00-\u9fa5]{1,6}(·[\u4e00-\u9fa5]{1,6}){0,2}$/.test(val)) return false
// true: 姓名正确
else return true
}
// 邮政编码
export function verifyPostalCode(val) {
// false: 邮政编码不正确
if (!/^[1-9][0-9]{5}$/.test(val)) return false
// true: 邮政编码正确
else return true
}
// url
export function verifyUrl(val) {
// false: url不正确
if (!/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(val)) return false
// true: url正确
else return true
}
// 车牌号
export function verifyCarNum(val) {
// false: 车牌号不正确
if (!/^(([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z](([0-9]{5}[DF])|([DF]([A-HJ-NP-Z0-9])[0-9]{4})))|([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳使领]))$/.test(val)) return false
// true车牌号正确
else return true
}

246
src/utils/toolsValidate.ts Normal file
View File

@ -0,0 +1,246 @@
/**
* 2020.11.29 lyt
*
*/
// 小数或整数(不可以负数)
export function verifyNumberIntegerAndFloat(val: string) {
// 匹配空格
let v = val.replace(/(^\s*)|(\s*$)/g, '');
// 只能是数字和小数点,不能是其他输入
v = v.replace(/[^\d.]/g, '');
// 以0开始只能输入一个
v = v.replace(/^0{2}$/g, '0');
// 保证第一位只能是数字,不能是点
v = v.replace(/^\./g, '');
// 小数只能出现1位
v = v.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.');
// 小数点后面保留2位
v = v.replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3');
// 返回结果
return v;
}
// 正整数验证
export function verifiyNumberInteger(val: string) {
// 匹配空格
let v = val.replace(/(^\s*)|(\s*$)/g, '');
// 去掉 '.' , 防止贴贴的时候出现问题 如 0.1.12.12
v = v.replace(/[\.]*/g, '');
// 去掉以 0 开始后面的数, 防止贴贴的时候出现问题 如 00121323
v = v.replace(/(^0[\d]*)$/g, '0');
// 首位是0,只能出现一次
v = v.replace(/^0\d$/g, '0');
// 只匹配数字
v = v.replace(/[^\d]/g, '');
// 返回结果
return v;
}
// 去掉中文及空格
export function verifyCnAndSpace(val: string) {
// 匹配中文与空格
let v = val.replace(/[\u4e00-\u9fa5\s]+/g, '');
// 匹配空格
v = v.replace(/(^\s*)|(\s*$)/g, '');
// 返回结果
return v;
}
// 去掉英文及空格
export function verifyEnAndSpace(val: string) {
// 匹配英文与空格
let v = val.replace(/[a-zA-Z]+/g, '');
// 匹配空格
v = v.replace(/(^\s*)|(\s*$)/g, '');
// 返回结果
return v;
}
// 禁止输入空格
export function verifyAndSpace(val: string) {
// 匹配空格
let v = val.replace(/(^\s*)|(\s*$)/g, '');
// 返回结果
return v;
}
// 金额用 `,` 区分开
export function verifyNumberComma(val: string) {
// 调用小数或整数(不可以负数)方法
let v: any = verifyNumberIntegerAndFloat(val);
// 字符串转成数组
v = v.toString().split('.');
// \B 匹配非单词边界,两边都是单词字符或者两边都是非单词字符
v[0] = v[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
// 数组转字符串
v = v.join('.');
// 返回结果
return v;
}
// 匹配文字变色(搜索时)
export function verifyTextColor(val: string, text = '', color = 'red') {
// 返回内容,添加颜色
let v = text.replace(new RegExp(val, 'gi'), `<span style='color: ${color}'>${val}</span>`);
// 返回结果
return v;
}
// 数字转中文大写
export function verifyNumberCnUppercase(val: any, unit = '仟佰拾亿仟佰拾万仟佰拾元角分', v = '') {
// 当前内容字符串添加 2个0为什么??
val += '00';
// 返回某个指定的字符串值在字符串中首次出现的位置,没有出现,则该方法返回 -1
let lookup = val.indexOf('.');
// substring不包含结束下标内容substr包含结束下标内容
if (lookup >= 0) val = val.substring(0, lookup) + val.substr(lookup + 1, 2);
// 根据内容 val 的长度,截取返回对应大写
unit = unit.substr(unit.length - val.length);
// 循环截取拼接大写
for (let i = 0; i < val.length; i++) {
v += '零壹贰叁肆伍陆柒捌玖'.substr(val.substr(i, 1), 1) + unit.substr(i, 1);
}
// 正则处理
v = v
.replace(/零角零分$/, '整')
.replace(/零[仟佰拾]/g, '零')
.replace(/零{2,}/g, '零')
.replace(/零([亿|万])/g, '$1')
.replace(/零+元/, '元')
.replace(/亿零{0,3}万/, '亿')
.replace(/^元/, '零元');
// 返回结果
return v;
}
// 手机号码
export function verifyPhone(val: string) {
// false: 手机号码不正确
if (!/^((12[0-9])|(13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\d{8}$/.test(val)) return false;
// true: 手机号码正确
else return true;
}
// 国内电话号码
export function verifyTelPhone(val: string) {
// false: 国内电话号码不正确
if (!/\d{3}-\d{8}|\d{4}-\d{7}/.test(val)) return false;
// true: 国内电话号码正确
else return true;
}
// 登录账号 (字母开头允许5-16字节允许字母数字下划线)
export function verifyAccount(val: string) {
// false: 登录账号不正确
if (!/^[a-zA-Z][a-zA-Z0-9_]{4,15}$/.test(val)) return false;
// true: 登录账号正确
else return true;
}
// 密码 (以字母开头长度在6~16之间只能包含字母、数字和下划线)
export function verifyPassword(val: string) {
// false: 密码不正确
if (!/^[a-zA-Z]\w{5,15}$/.test(val)) return false;
// true: 密码正确
else return true;
}
// 强密码 (字母+数字+特殊字符长度在6-16之间)
export function verifyPasswordPowerful(val: string) {
// false: 强密码不正确
if (!/^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&\.*]+$)(?![a-zA-z\d]+$)(?![a-zA-z!@#$%^&\.*]+$)(?![\d!@#$%^&\.*]+$)[a-zA-Z\d!@#$%^&\.*]{6,16}$/.test(val))
return false;
// true: 强密码正确
else return true;
}
// 密码强度
export function verifyPasswordStrength(val: string) {
let v = '';
// 弱:纯数字,纯字母,纯特殊字符
if (/^(?:\d+|[a-zA-Z]+|[!@#$%^&\.*]+){6,16}$/.test(val)) v = '弱';
// 中:字母+数字,字母+特殊字符,数字+特殊字符
if (/^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&\.*]+$)[a-zA-Z\d!@#$%^&\.*]{6,16}$/.test(val)) v = '中';
// 强:字母+数字+特殊字符
if (/^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&\.*]+$)(?![a-zA-z\d]+$)(?![a-zA-z!@#$%^&\.*]+$)(?![\d!@#$%^&\.*]+$)[a-zA-Z\d!@#$%^&\.*]{6,16}$/.test(val))
v = '强';
// 返回结果
return v;
}
// IP地址
export function verifyIPAddress(val: string) {
// false: IP地址不正确
if (
!/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/.test(
val
)
)
return false;
// true: IP地址正确
else return true;
}
// 邮箱
export function verifyEmail(val: string) {
// false: 邮箱不正确
if (
!/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(
val
)
)
return false;
// true: 邮箱正确
else return true;
}
// 身份证
export function verifyIdCard(val: string) {
// false: 身份证不正确
if (!/^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/.test(val)) return false;
// true: 身份证正确
else return true;
}
// 姓名
export function verifyFullName(val: string) {
// false: 姓名不正确
if (!/^[\u4e00-\u9fa5]{1,6}(·[\u4e00-\u9fa5]{1,6}){0,2}$/.test(val)) return false;
// true: 姓名正确
else return true;
}
// 邮政编码
export function verifyPostalCode(val: string) {
// false: 邮政编码不正确
if (!/^[1-9][0-9]{5}$/.test(val)) return false;
// true: 邮政编码正确
else return true;
}
// url
export function verifyUrl(val: string) {
// false: url不正确
if (
!/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(
val
)
)
return false;
// true: url正确
else return true;
}
// 车牌号
export function verifyCarNum(val: string) {
// false: 车牌号不正确
if (
!/^(([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z](([0-9]{5}[DF])|([DF]([A-HJ-NP-Z0-9])[0-9]{4})))|([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳使领]))$/.test(
val
)
)
return false;
// true车牌号正确
else return true;
}

26
src/utils/viteBuild.ts Normal file
View File

@ -0,0 +1,26 @@
// vite 打包相关
import dotenv from 'dotenv';
export interface ViteEnv {
VITE_PORT: number;
VITE_OPEN: boolean;
VITE_PUBLIC_PATH: string;
}
export function loadEnv(): ViteEnv {
const env = process.env.NODE_ENV;
const ret: any = {};
const envList = [`.env.${env}.local`, `.env.${env}`, '.env.local', '.env', ,];
envList.forEach((e) => {
dotenv.config({ path: e });
});
for (const envName of Object.keys(process.env)) {
console.log(envName);
let realName = (process.env as any)[envName].replace(/\\n/g, '\n');
realName = realName === 'true' ? true : realName === 'false' ? false : realName;
if (envName === 'VITE_PORT') realName = Number(realName);
if (envName === 'VITE_OPEN') realName = Boolean(realName);
ret[envName] = realName;
process.env[envName] = realName;
}
return ret;
}

View File

@ -1,42 +1,42 @@
// 页面添加水印效果
const setWatermark = (str: any) => {
const id = "1.23452384164.123412416"
if (document.getElementById(id) !== null) document.body.removeChild(document.getElementById(id) as any)
const can = document.createElement("canvas")
can.width = 250
can.height = 180
const cans: any = can.getContext("2d")
cans.rotate((-20 * Math.PI) / 180)
cans.font = "12px Vedana"
cans.fillStyle = "rgba(200, 200, 200, 0.30)"
cans.textAlign = "center"
cans.textBaseline = "Middle"
cans.fillText(str, can.width / 10, can.height / 2)
const div = document.createElement("div")
div.id = id
div.style.pointerEvents = "none"
div.style.top = "35px"
div.style.left = "0px"
div.style.position = "fixed"
div.style.zIndex = "10000000"
div.style.width = document.documentElement.clientWidth + "px"
div.style.height = document.documentElement.clientHeight + "px"
div.style.background = `url(${can.toDataURL("image/png")}) left top repeat`
document.body.appendChild(div)
return id
const id = '1.23452384164.123412416';
if (document.getElementById(id) !== null) document.body.removeChild(document.getElementById(id) as any);
const can = document.createElement('canvas');
can.width = 250;
can.height = 180;
const cans: any = can.getContext('2d');
cans.rotate((-20 * Math.PI) / 180);
cans.font = '12px Vedana';
cans.fillStyle = 'rgba(200, 200, 200, 0.30)';
cans.textAlign = 'center';
cans.textBaseline = 'Middle';
cans.fillText(str, can.width / 10, can.height / 2);
const div = document.createElement('div');
div.id = id;
div.style.pointerEvents = 'none';
div.style.top = '35px';
div.style.left = '0px';
div.style.position = 'fixed';
div.style.zIndex = '10000000';
div.style.width = document.documentElement.clientWidth + 'px';
div.style.height = document.documentElement.clientHeight + 'px';
div.style.background = `url(${can.toDataURL('image/png')}) left top repeat`;
document.body.appendChild(div);
return id;
};
const watermark = {
// 设置水印
set: (str: any) => {
let id = setWatermark(str)
if (document.getElementById(id) === null) id = setWatermark(str)
},
// 删除水印
del: () => {
let id = '1.23452384164.123412416'
if (document.getElementById(id) !== null) document.body.removeChild(document.getElementById(id) as any)
}
}
// 设置水印
set: (str: any) => {
let id = setWatermark(str);
if (document.getElementById(id) === null) id = setWatermark(str);
},
// 删除水印
del: () => {
let id = '1.23452384164.123412416';
if (document.getElementById(id) !== null) document.body.removeChild(document.getElementById(id) as any);
},
};
export default watermark
export default watermark;

View File

@ -1,430 +1,428 @@
.chart-scrollbar {
.chart-warp {
display: flex;
flex-direction: column;
height: 100%;
.chart-warp-bottom {
flex: 1;
overflow: hidden;
display: flex;
.big-data-down-left,
.big-data-down-right {
width: 30%;
display: flex;
flex-direction: column;
.flex-warp-item {
padding: 0 7.5px 15px 15px;
width: 100%;
height: 33.33%;
.flex-warp-item-box {
width: 100%;
height: 100%;
background: white;
border: 1px solid #ebeef5;
border-radius: 4px;
display: flex;
flex-direction: column;
padding: 15px;
transition: all ease 0.3s;
&:hover {
box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
transition: all ease 0.3s;
}
.flex-title {
margin-bottom: 15px;
display: flex;
justify-content: space-between;
.flex-title-small {
font-size: 12px;
}
}
.flex-content {
flex: 1;
font-size: 12px;
}
.flex-content-overflow {
overflow: hidden;
}
}
}
}
.big-data-down-left {
color: #303133;
.sky {
display: flex;
align-items: center;
.sky-left {
font-size: 30px;
}
.sky-center {
flex: 1;
overflow: hidden;
padding: 0 10px;
font {
margin-right: 15px;
}
.span {
background: #22bc76;
border-radius: 2px;
padding: 0 5px;
color: white;
}
}
.sky-right {
span {
font-size: 30px;
}
font {
font-size: 20px;
}
}
}
.sky-dd {
.sky-dl {
display: flex;
align-items: center;
height: 28px;
overflow: hidden;
div {
flex: 1;
overflow: hidden;
i {
font-size: 14px;
}
}
.tip {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
.sky-dl-first {
color: var(--color-primary);
}
}
.d-states {
display: flex;
.d-states-item {
flex: 1;
display: flex;
align-items: center;
overflow: hidden;
i {
font-size: 20px;
height: 33px;
width: 33px;
line-height: 33px;
text-align: center;
border-radius: 100%;
flex-shrink: 1;
color: #ffffff;
}
.i-bg1 {
background: #22bc76;
}
.i-bg2 {
background: #e2356d;
}
.i-bg3 {
background: #43bbef;
}
.d-states-flex {
overflow: hidden;
padding: 0 10px 0;
.d-states-item-label {
color: var(--color-primary);
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.d-states-item-value {
font-size: 14px;
text-align: center;
margin-top: 3px;
color: var(--color-primary);
}
}
}
}
.d-btn {
margin-top: 5px;
.d-btn-item {
border: 1px solid var(--color-primary);
display: flex;
width: 100%;
border-radius: 35px;
align-items: center;
padding: 5px;
margin-top: 15px;
cursor: pointer;
transition: all ease 0.3s;
color: var(--color-primary);
.d-btn-item-left {
font-size: 20px;
border: 1px solid var(--color-primary);
width: 25px;
height: 25px;
line-height: 25px;
border-radius: 100%;
text-align: center;
font-size: 14px;
}
.d-btn-item-center {
padding: 0 10px;
flex: 1;
}
.d-btn-item-eight {
text-align: right;
padding-right: 10px;
}
}
}
}
.big-data-down-center {
width: 40%;
display: flex;
flex-direction: column;
.big-data-down-center-one {
height: 66.67%;
padding: 0 7.5px 15px;
.big-data-down-center-one-content {
height: 100%;
background: white;
padding: 15px;
border: 1px solid #ebeef5;
border-radius: 4px;
transition: all ease 0.3s;
&:hover {
box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
transition: all ease 0.3s;
}
}
}
.big-data-down-center-two {
padding: 0 7.5px 15px;
height: 33.33%;
.flex-warp-item-box {
width: 100%;
height: 100%;
background: white;
display: flex;
flex-direction: column;
padding: 15px;
border: 1px solid #ebeef5;
border-radius: 4px;
transition: all ease 0.3s;
&:hover {
box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
transition: all ease 0.3s;
}
.flex-title {
margin-bottom: 15px;
color: #303133;
display: flex;
justify-content: space-between;
.flex-title-small {
font-size: 12px;
}
}
.flex-content {
flex: 1;
font-size: 12px;
display: flex;
height: calc(100% - 30px);
.flex-content-left {
display: flex;
flex-wrap: wrap;
width: 120px;
height: 100%;
.monitor-item {
width: 50%;
display: flex;
align-items: center;
.monitor-wave {
cursor: pointer;
width: 40px;
height: 40px;
position: relative;
background-color: var(--color-primary);
border-radius: 50%;
overflow: hidden;
text-align: center;
&::before,
&::after {
content: '';
position: absolute;
left: 50%;
width: 40px;
height: 40px;
background: #f4f4f4;
animation: roateOne 10s linear infinite;
transform: translateX(-50%);
z-index: 1;
}
&::before {
bottom: 10px;
border-radius: 60%;
}
&::after {
bottom: 8px;
opacity: 0.7;
border-radius: 37%;
}
.monitor-z-index {
position: relative;
z-index: 2;
color: var(--color-primary);
display: flex;
align-items: center;
height: 100%;
justify-content: center;
}
}
@keyframes roateOne {
0% {
transform: translate(-50%, 0) rotateZ(0deg);
}
50% {
transform: translate(-50%, -2%) rotateZ(180deg);
}
100% {
transform: translate(-50%, 0%) rotateZ(360deg);
}
}
.monitor-active {
background-color: #22bc76;
.monitor-z-index {
color: #22bc76;
}
}
}
}
.flex-content-right {
flex: 1;
}
}
}
}
}
.big-data-down-right {
.flex-warp-item {
padding: 0 15px 15px 7.5px;
.flex-content {
display: flex;
flex-direction: column;
.task {
display: flex;
height: 45px;
.task-item {
flex: 1;
color: #ffffff;
display: flex;
justify-content: center;
.task-item-box {
position: relative;
width: 45px;
height: 45px;
overflow: hidden;
border-radius: 100%;
z-index: 0;
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
box-shadow: 0 10px 12px 0 rgba(0, 0, 0, 0.3);
&::before {
content: '';
position: absolute;
z-index: -2;
left: -50%;
top: -50%;
width: 200%;
height: 200%;
background-repeat: no-repeat;
background-size: 50% 50%, 50% 50%;
background-position: 0 0, 100% 0, 100% 100%, 0 100%;
background-image: linear-gradient(#19d4ae, #19d4ae),
linear-gradient(#5ab1ef, #5ab1ef),
linear-gradient(#fa6e86, #fa6e86),
linear-gradient(#ffb980, #ffb980);
animation: rotate 2s linear infinite;
}
&::after {
content: '';
position: absolute;
z-index: -1;
left: 1px;
top: 1px;
width: calc(100% - 2px);
height: calc(100% - 2px);
border-radius: 100%;
}
.task-item-value {
text-align: center;
font-size: 14px;
font-weight: bold;
}
.task-item-label {
text-align: center;
}
}
.task1 {
&::after {
background: #5492be;
}
}
.task2 {
&::after {
background: #43a177;
}
}
.task3 {
&::after {
background: #a76077;
}
}
}
.task-first-item {
flex-direction: column;
text-align: center;
color: var(--color-primary);
.task-first {
font-size: 20px;
}
}
}
.progress {
color: #303133;
display: flex;
flex-direction: column;
flex: 1;
justify-content: space-between;
margin-top: 15px;
.progress-item {
height: 33.33%;
display: flex;
align-items: center;
.progress-box {
flex: 1;
width: 100%;
margin-left: 10px;
::v-deep(.el-progress__text) {
color: #303133;
font-size: 12px !important;
text-align: right;
}
::v-deep(.el-progress-bar__outer) {
background-color: rgba(0, 0, 0, 0.1) !important;
}
::v-deep(.el-progress-bar) {
margin-right: -22px !important;
}
}
}
}
}
}
}
}
}
.chart-warp {
display: flex;
flex-direction: column;
height: 100%;
.chart-warp-bottom {
flex: 1;
overflow: hidden;
display: flex;
.big-data-down-left,
.big-data-down-right {
width: 30%;
display: flex;
flex-direction: column;
.flex-warp-item {
padding: 0 7.5px 15px 15px;
width: 100%;
height: 33.33%;
.flex-warp-item-box {
width: 100%;
height: 100%;
background: white;
border: 1px solid #ebeef5;
border-radius: 4px;
display: flex;
flex-direction: column;
padding: 15px;
transition: all ease 0.3s;
&:hover {
box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
transition: all ease 0.3s;
}
.flex-title {
margin-bottom: 15px;
display: flex;
justify-content: space-between;
.flex-title-small {
font-size: 12px;
}
}
.flex-content {
flex: 1;
font-size: 12px;
}
.flex-content-overflow {
overflow: hidden;
}
}
}
}
.big-data-down-left {
color: #303133;
.sky {
display: flex;
align-items: center;
.sky-left {
font-size: 30px;
}
.sky-center {
flex: 1;
overflow: hidden;
padding: 0 10px;
font {
margin-right: 15px;
}
.span {
background: #22bc76;
border-radius: 2px;
padding: 0 5px;
color: white;
}
}
.sky-right {
span {
font-size: 30px;
}
font {
font-size: 20px;
}
}
}
.sky-dd {
.sky-dl {
display: flex;
align-items: center;
height: 28px;
overflow: hidden;
div {
flex: 1;
overflow: hidden;
i {
font-size: 14px;
}
}
.tip {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
.sky-dl-first {
color: var(--color-primary);
}
}
.d-states {
display: flex;
.d-states-item {
flex: 1;
display: flex;
align-items: center;
overflow: hidden;
i {
font-size: 20px;
height: 33px;
width: 33px;
line-height: 33px;
text-align: center;
border-radius: 100%;
flex-shrink: 1;
color: #ffffff;
}
.i-bg1 {
background: #22bc76;
}
.i-bg2 {
background: #e2356d;
}
.i-bg3 {
background: #43bbef;
}
.d-states-flex {
overflow: hidden;
padding: 0 10px 0;
.d-states-item-label {
color: var(--color-primary);
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.d-states-item-value {
font-size: 14px;
text-align: center;
margin-top: 3px;
color: var(--color-primary);
}
}
}
}
.d-btn {
margin-top: 5px;
.d-btn-item {
border: 1px solid var(--color-primary);
display: flex;
width: 100%;
border-radius: 35px;
align-items: center;
padding: 5px;
margin-top: 15px;
cursor: pointer;
transition: all ease 0.3s;
color: var(--color-primary);
.d-btn-item-left {
font-size: 20px;
border: 1px solid var(--color-primary);
width: 25px;
height: 25px;
line-height: 25px;
border-radius: 100%;
text-align: center;
font-size: 14px;
}
.d-btn-item-center {
padding: 0 10px;
flex: 1;
}
.d-btn-item-eight {
text-align: right;
padding-right: 10px;
}
}
}
}
.big-data-down-center {
width: 40%;
display: flex;
flex-direction: column;
.big-data-down-center-one {
height: 66.67%;
padding: 0 7.5px 15px;
.big-data-down-center-one-content {
height: 100%;
background: white;
padding: 15px;
border: 1px solid #ebeef5;
border-radius: 4px;
transition: all ease 0.3s;
&:hover {
box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
transition: all ease 0.3s;
}
}
}
.big-data-down-center-two {
padding: 0 7.5px 15px;
height: 33.33%;
.flex-warp-item-box {
width: 100%;
height: 100%;
background: white;
display: flex;
flex-direction: column;
padding: 15px;
border: 1px solid #ebeef5;
border-radius: 4px;
transition: all ease 0.3s;
&:hover {
box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
transition: all ease 0.3s;
}
.flex-title {
margin-bottom: 15px;
color: #303133;
display: flex;
justify-content: space-between;
.flex-title-small {
font-size: 12px;
}
}
.flex-content {
flex: 1;
font-size: 12px;
display: flex;
height: calc(100% - 30px);
.flex-content-left {
display: flex;
flex-wrap: wrap;
width: 120px;
height: 100%;
.monitor-item {
width: 50%;
display: flex;
align-items: center;
.monitor-wave {
cursor: pointer;
width: 40px;
height: 40px;
position: relative;
background-color: var(--color-primary);
border-radius: 50%;
overflow: hidden;
text-align: center;
&::before,
&::after {
content: '';
position: absolute;
left: 50%;
width: 40px;
height: 40px;
background: #f4f4f4;
animation: roateOne 10s linear infinite;
transform: translateX(-50%);
z-index: 1;
}
&::before {
bottom: 10px;
border-radius: 60%;
}
&::after {
bottom: 8px;
opacity: 0.7;
border-radius: 37%;
}
.monitor-z-index {
position: relative;
z-index: 2;
color: var(--color-primary);
display: flex;
align-items: center;
height: 100%;
justify-content: center;
}
}
@keyframes roateOne {
0% {
transform: translate(-50%, 0) rotateZ(0deg);
}
50% {
transform: translate(-50%, -2%) rotateZ(180deg);
}
100% {
transform: translate(-50%, 0%) rotateZ(360deg);
}
}
.monitor-active {
background-color: #22bc76;
.monitor-z-index {
color: #22bc76;
}
}
}
}
.flex-content-right {
flex: 1;
}
}
}
}
}
.big-data-down-right {
.flex-warp-item {
padding: 0 15px 15px 7.5px;
.flex-content {
display: flex;
flex-direction: column;
.task {
display: flex;
height: 45px;
.task-item {
flex: 1;
color: #ffffff;
display: flex;
justify-content: center;
.task-item-box {
position: relative;
width: 45px;
height: 45px;
overflow: hidden;
border-radius: 100%;
z-index: 0;
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
box-shadow: 0 10px 12px 0 rgba(0, 0, 0, 0.3);
&::before {
content: '';
position: absolute;
z-index: -2;
left: -50%;
top: -50%;
width: 200%;
height: 200%;
background-repeat: no-repeat;
background-size: 50% 50%, 50% 50%;
background-position: 0 0, 100% 0, 100% 100%, 0 100%;
background-image: linear-gradient(#19d4ae, #19d4ae), linear-gradient(#5ab1ef, #5ab1ef), linear-gradient(#fa6e86, #fa6e86),
linear-gradient(#ffb980, #ffb980);
animation: rotate 2s linear infinite;
}
&::after {
content: '';
position: absolute;
z-index: -1;
left: 1px;
top: 1px;
width: calc(100% - 2px);
height: calc(100% - 2px);
border-radius: 100%;
}
.task-item-value {
text-align: center;
font-size: 14px;
font-weight: bold;
}
.task-item-label {
text-align: center;
}
}
.task1 {
&::after {
background: #5492be;
}
}
.task2 {
&::after {
background: #43a177;
}
}
.task3 {
&::after {
background: #a76077;
}
}
}
.task-first-item {
flex-direction: column;
text-align: center;
color: var(--color-primary);
.task-first {
font-size: 20px;
}
}
}
.progress {
color: #303133;
display: flex;
flex-direction: column;
flex: 1;
justify-content: space-between;
margin-top: 15px;
.progress-item {
height: 33.33%;
display: flex;
align-items: center;
.progress-box {
flex: 1;
width: 100%;
margin-left: 10px;
::v-deep(.el-progress__text) {
color: #303133;
font-size: 12px !important;
text-align: right;
}
::v-deep(.el-progress-bar__outer) {
background-color: rgba(0, 0, 0, 0.1) !important;
}
::v-deep(.el-progress-bar) {
margin-right: -22px !important;
}
}
}
}
}
}
}
}
}
}

View File

@ -1,78 +1,78 @@
// sky 天气
export const skyList = [
{
v1: "时间",
v2: "天气",
v3: "温度",
v5: "降水",
v7: "风力",
type: "title",
},
{
v1: "今天",
v2: "el-icon-cloudy-and-sunny",
v3: "20°/26°",
v5: "50%",
v7: "13m/s",
},
{
v1: "明天",
v2: "el-icon-lightning",
v3: "20°/26°",
v5: "50%",
v7: "13m/s",
},
{
v1: '时间',
v2: '天气',
v3: '温度',
v5: '降水',
v7: '风力',
type: 'title',
},
{
v1: '今天',
v2: 'el-icon-cloudy-and-sunny',
v3: '20°/26°',
v5: '50%',
v7: '13m/s',
},
{
v1: '明天',
v2: 'el-icon-lightning',
v3: '20°/26°',
v5: '50%',
v7: '13m/s',
},
];
// 当前设置状态
export const dBtnList = [
{
v2: "阳光玫瑰种植",
v3: "126天",
v4: "设备在线",
}
{
v2: '阳光玫瑰种植',
v3: '126天',
v4: '设备在线',
},
];
// 当前设备监测
export const chartData4List = [
{
label: "温度",
},
{
label: "光照",
},
{
label: "湿度",
},
{
label: "风力",
}
{
label: '温度',
},
{
label: '光照',
},
{
label: '湿度',
},
{
label: '风力',
},
];
// 3DEarth 地图周围按钮组
export const earth3DBtnList = [
{
topLevelClass: "fixed-top",
icon: "el-icon-s-marketing",
label: "环境监测",
type: 0,
},
{
topLevelClass: "fixed-right",
icon: "el-icon-s-cooperation",
label: "精准管理",
type: 1,
},
{
topLevelClass: "fixed-bottom",
icon: "el-icon-s-order",
label: "数据报表",
type: 2,
},
{
topLevelClass: "fixed-left",
icon: "el-icon-s-claim",
label: "产品追溯",
type: 3,
},
];
{
topLevelClass: 'fixed-top',
icon: 'el-icon-s-marketing',
label: '环境监测',
type: 0,
},
{
topLevelClass: 'fixed-right',
icon: 'el-icon-s-cooperation',
label: '精准管理',
type: 1,
},
{
topLevelClass: 'fixed-bottom',
icon: 'el-icon-s-order',
label: '数据报表',
type: 2,
},
{
topLevelClass: 'fixed-left',
icon: 'el-icon-s-claim',
label: '产品追溯',
type: 3,
},
];

View File

@ -1,117 +1,106 @@
<template>
<div class="big-data-up mb15">
<div class="up-left">
<i class="el-icon-time mr5"></i>
<span>{{ time.txt }}</span>
</div>
<div class="up-center">
<span>智慧农业系统平台</span>
</div>
</div>
<div class="big-data-up mb15">
<div class="up-left">
<i class="el-icon-time mr5"></i>
<span>{{ time.txt }}</span>
</div>
<div class="up-center">
<span>智慧农业系统平台</span>
</div>
</div>
</template>
<script>
import { reactive, toRefs, onBeforeMount, onUnmounted } from 'vue'
import { formatDate } from "/@/utils/formatTime"
<script lang="ts">
import { reactive, toRefs, onBeforeMount, onUnmounted } from 'vue';
import { formatDate } from '/@/utils/formatTime.ts';
export default {
name: "chartHead",
setup() {
const state = reactive({
time: {
txt: "",
fun: null,
}
})
//
const initTime = () => {
state.time.txt = formatDate(new Date(), "YYYY-mm-dd HH:MM:SS WWW QQQQ");
state.time.fun = setInterval(() => {
state.time.txt = formatDate(new Date(), "YYYY-mm-dd HH:MM:SS WWW QQQQ");
}, 1000);
}
//
onBeforeMount(() => {
initTime()
})
//
onUnmounted(() => {
clearInterval(state.time.fun)
})
return {
...toRefs(state)
};
},
name: 'chartHead',
setup() {
const state = reactive({
time: {
txt: '',
fun: 0,
},
});
//
const initTime = () => {
state.time.txt = formatDate(new Date(), 'YYYY-mm-dd HH:MM:SS WWW QQQQ');
state.time.fun = window.setInterval(() => {
state.time.txt = formatDate(new Date(), 'YYYY-mm-dd HH:MM:SS WWW QQQQ');
}, 1000);
};
//
onBeforeMount(() => {
initTime();
});
//
onUnmounted(() => {
window.clearInterval(state.time.fun);
});
return {
...toRefs(state),
};
},
};
</script>
<style scoped lang="scss">
.big-data-up {
height: 55px;
width: 100%;
display: flex;
align-items: center;
padding: 0 15px;
color: var(--color-primary);
overflow: hidden;
position: relative;
.up-left {
position: absolute;
}
.up-center {
width: 100%;
display: flex;
justify-content: center;
font-size: 18px;
letter-spacing: 5px;
background-image: -webkit-linear-gradient(
left,
var(--color-primary),
var(--color-primary-light-1) 25%,
var(--color-primary) 50%,
var(--color-primary-light-1) 75%,
var(--color-primary)
);
-webkit-text-fill-color: transparent;
-webkit-background-clip: text;
background-clip: text;
background-size: 200% 100%;
-webkit-animation: masked-animation-data-v-b02d8052 4s linear infinite;
animation: masked-animation-data-v-b02d8052 4s linear infinite;
-webkit-box-reflect: below -2px -webkit-gradient(
linear,
left top,
left bottom,
from(transparent),
to(hsla(0, 0%, 100%, 0.1))
);
position: relative;
@keyframes masked-animation {
0% {
background-position: 0 0;
}
100% {
background-position: -100% 0;
}
}
position: relative;
&::after {
content: "";
width: 250px;
position: absolute;
bottom: -15px;
left: 50%;
transform: translateX(-50%);
border: 1px transparent solid;
border-image: linear-gradient(
to right,
var(--color-primary-light-9),
var(--color-primary)
)
1 10;
}
span {
cursor: pointer;
}
}
height: 55px;
width: 100%;
display: flex;
align-items: center;
padding: 0 15px;
color: var(--color-primary);
overflow: hidden;
position: relative;
.up-left {
position: absolute;
}
.up-center {
width: 100%;
display: flex;
justify-content: center;
font-size: 18px;
letter-spacing: 5px;
background-image: -webkit-linear-gradient(
left,
var(--color-primary),
var(--color-primary-light-1) 25%,
var(--color-primary) 50%,
var(--color-primary-light-1) 75%,
var(--color-primary)
);
-webkit-text-fill-color: transparent;
-webkit-background-clip: text;
background-clip: text;
background-size: 200% 100%;
-webkit-animation: masked-animation-data-v-b02d8052 4s linear infinite;
animation: masked-animation-data-v-b02d8052 4s linear infinite;
-webkit-box-reflect: below -2px -webkit-gradient(linear, left top, left bottom, from(transparent), to(hsla(0, 0%, 100%, 0.1)));
position: relative;
@keyframes masked-animation {
0% {
background-position: 0 0;
}
100% {
background-position: -100% 0;
}
}
position: relative;
&::after {
content: '';
width: 250px;
position: absolute;
bottom: -15px;
left: 50%;
transform: translateX(-50%);
border: 1px transparent solid;
border-image: linear-gradient(to right, var(--color-primary-light-9), var(--color-primary)) 1 10;
}
span {
cursor: pointer;
}
}
}
</style>
</style>

View File

@ -1,477 +1,469 @@
<template>
<div class="chart-scrollbar" :style="{height: `calc(100vh - ${initTagViewHeight}`}">
<div class="chart-warp layout-view-bg-white">
<div class="chart-warp-top">
<ChartHead />
</div>
<div class="chart-warp-bottom">
<!-- 左边 -->
<div class="big-data-down-left">
<div class="flex-warp-item">
<div class="flex-warp-item-box">
<div class="flex-title">天气预报</div>
<div class="flex-content">
<div class="sky">
<i class="sky-left el-icon-cloudy-and-sunny"></i>
<div class="sky-center">
<div class="mb2">
<span>多云转晴</span>
<span>东南风</span>
<span class="span ml5"></span>
</div>
</div>
<div class="sky-right">
<span>25</span>
<span>°C</span>
</div>
</div>
<div class="sky-dd">
<div class="sky-dl" v-for="(v,k) in skyList" :key="k" :class="{'sky-dl-first': k === 1}">
<div>{{v.v1}}</div>
<div v-if="v.type === 'title'">{{v.v2}}</div>
<div v-else>
<i :class="v.v2"></i>
</div>
<div>{{v.v3}}</div>
<div class="tip">{{v.v5}}</div>
<div>{{v.v7}}</div>
</div>
</div>
</div>
</div>
</div>
<div class="flex-warp-item">
<div class="flex-warp-item-box">
<div class="flex-title">当前设备状态</div>
<div class="flex-content flex-content-overflow">
<div class="d-states">
<div class="d-states-item">
<i class="el-icon-odometer i-bg1"></i>
<div class="d-states-flex">
<div class="d-states-item-label">设备</div>
<div class="d-states-item-value">99</div>
</div>
</div>
<div class="d-states-item">
<i class="el-icon-first-aid-kit i-bg2"></i>
<div class="d-states-flex">
<div class="d-states-item-label">预警</div>
<div class="d-states-item-value">10</div>
</div>
</div>
<div class="d-states-item">
<i class="el-icon-video-play i-bg3"></i>
<div class="d-states-flex">
<div class="d-states-item-label">运行</div>
<div class="d-states-item-value">20</div>
</div>
</div>
</div>
<div class="d-btn">
<div class="d-btn-item" v-for="(v,k) in dBtnList" :key="k">
<i class="d-btn-item-left el-icon-money"></i>
<div class="d-btn-item-center">
<div>{{v.v2}}|{{v.v3}}</div>
</div>
<div class="d-btn-item-eight">{{v.v4}}</div>
</div>
</div>
</div>
</div>
</div>
<div class="flex-warp-item">
<div class="flex-warp-item-box">
<div class="flex-title">近30天预警总数</div>
<div class="flex-content">
<div id="chartsWarning" style="height:100%;"></div>
</div>
</div>
</div>
</div>
<div class="chart-scrollbar" :style="{ height: `calc(100vh - ${initTagViewHeight}` }">
<div class="chart-warp layout-view-bg-white">
<div class="chart-warp-top">
<ChartHead />
</div>
<div class="chart-warp-bottom">
<!-- 左边 -->
<div class="big-data-down-left">
<div class="flex-warp-item">
<div class="flex-warp-item-box">
<div class="flex-title">天气预报</div>
<div class="flex-content">
<div class="sky">
<i class="sky-left el-icon-cloudy-and-sunny"></i>
<div class="sky-center">
<div class="mb2">
<span>多云转晴</span>
<span>东南风</span>
<span class="span ml5"></span>
</div>
</div>
<div class="sky-right">
<span>25</span>
<span>°C</span>
</div>
</div>
<div class="sky-dd">
<div class="sky-dl" v-for="(v, k) in skyList" :key="k" :class="{ 'sky-dl-first': k === 1 }">
<div>{{ v.v1 }}</div>
<div v-if="v.type === 'title'">{{ v.v2 }}</div>
<div v-else>
<i :class="v.v2"></i>
</div>
<div>{{ v.v3 }}</div>
<div class="tip">{{ v.v5 }}</div>
<div>{{ v.v7 }}</div>
</div>
</div>
</div>
</div>
</div>
<div class="flex-warp-item">
<div class="flex-warp-item-box">
<div class="flex-title">当前设备状态</div>
<div class="flex-content flex-content-overflow">
<div class="d-states">
<div class="d-states-item">
<i class="el-icon-odometer i-bg1"></i>
<div class="d-states-flex">
<div class="d-states-item-label">设备</div>
<div class="d-states-item-value">99</div>
</div>
</div>
<div class="d-states-item">
<i class="el-icon-first-aid-kit i-bg2"></i>
<div class="d-states-flex">
<div class="d-states-item-label">预警</div>
<div class="d-states-item-value">10</div>
</div>
</div>
<div class="d-states-item">
<i class="el-icon-video-play i-bg3"></i>
<div class="d-states-flex">
<div class="d-states-item-label">运行</div>
<div class="d-states-item-value">20</div>
</div>
</div>
</div>
<div class="d-btn">
<div class="d-btn-item" v-for="(v, k) in dBtnList" :key="k">
<i class="d-btn-item-left el-icon-money"></i>
<div class="d-btn-item-center">
<div>{{ v.v2 }}|{{ v.v3 }}</div>
</div>
<div class="d-btn-item-eight">{{ v.v4 }}</div>
</div>
</div>
</div>
</div>
</div>
<div class="flex-warp-item">
<div class="flex-warp-item-box">
<div class="flex-title">近30天预警总数</div>
<div class="flex-content">
<div style="height: 100%" ref="chartsWarningRef"></div>
</div>
</div>
</div>
</div>
<!-- 中间 -->
<div class="big-data-down-center">
<div class="big-data-down-center-one">
<div class="big-data-down-center-one-content">
<div id="chartsCenterOne" style="height:100%;"></div>
</div>
</div>
<div class="big-data-down-center-two">
<div class="flex-warp-item-box">
<div class="flex-title">
<span>当前设备监测</span>
<span class="flex-title-small">单位</span>
</div>
<div class="flex-content">
<div class="flex-content-left">
<div class="monitor-item" v-for="(v,k) in chartData4List" :key="k">
<div class="monitor-wave">
<div class="monitor-z-index">
<div class="monitor-item-label">{{v.label}}</div>
</div>
</div>
</div>
</div>
<div class="flex-content-right">
<div id="chartsMonitor" style="height:100%;"></div>
</div>
</div>
</div>
</div>
</div>
<!-- 中间 -->
<div class="big-data-down-center">
<div class="big-data-down-center-one">
<div class="big-data-down-center-one-content">
<div style="height: 100%" ref="chartsCenterOneRef"></div>
</div>
</div>
<div class="big-data-down-center-two">
<div class="flex-warp-item-box">
<div class="flex-title">
<span>当前设备监测</span>
<span class="flex-title-small">单位</span>
</div>
<div class="flex-content">
<div class="flex-content-left">
<div class="monitor-item" v-for="(v, k) in chartData4List" :key="k">
<div class="monitor-wave">
<div class="monitor-z-index">
<div class="monitor-item-label">{{ v.label }}</div>
</div>
</div>
</div>
</div>
<div class="flex-content-right">
<div style="height: 100%" ref="chartsMonitorRef"></div>
</div>
</div>
</div>
</div>
</div>
<!-- 右边 -->
<div class="big-data-down-right">
<div class="flex-warp-item">
<div class="flex-warp-item-box">
<div class="flex-title">
<span>近7天产品追溯扫码统计</span>
<span class="flex-title-small">单位</span>
</div>
<div class="flex-content">
<div id="chartsSevenDays" style="height:100%;"></div>
</div>
</div>
</div>
<div class="flex-warp-item">
<div class="flex-warp-item-box">
<div class="flex-title">当前任务统计</div>
<div class="flex-content">
<div class="task">
<div class="task-item task-first-item">
<div class="task-item-value task-first">25</div>
<div class="task-item-label">待办任务</div>
</div>
<div class="task-item">
<div class="task-item-box task1">
<div class="task-item-value">12</div>
<div class="task-item-label">施肥</div>
</div>
</div>
<div class="task-item">
<div class="task-item-box task2">
<div class="task-item-value">3</div>
<div class="task-item-label">施药</div>
</div>
</div>
<div class="task-item">
<div class="task-item-box task3">
<div class="task-item-value">5</div>
<div class="task-item-label">农事</div>
</div>
</div>
</div>
<div class="progress">
<div class="progress-item">
<span>施肥率</span>
<div class="progress-box">
<el-progress :percentage="70" color="#43bdf0"></el-progress>
</div>
</div>
<div class="progress-item">
<span>施药率</span>
<div class="progress-box">
<el-progress :percentage="36" color="#43bdf0"></el-progress>
</div>
</div>
<div class="progress-item">
<span>农事率</span>
<div class="progress-box">
<el-progress :percentage="91" color="#43bdf0"></el-progress>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="flex-warp-item">
<div class="flex-warp-item-box">
<div class="flex-title">
<span>近7天投入品记录</span>
<span class="flex-title-small">单位</span>
</div>
<div class="flex-content">
<div id="chartsInvestment" style="height:100%;"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 右边 -->
<div class="big-data-down-right">
<div class="flex-warp-item">
<div class="flex-warp-item-box">
<div class="flex-title">
<span>近7天产品追溯扫码统计</span>
<span class="flex-title-small">单位</span>
</div>
<div class="flex-content">
<div style="height: 100%" ref="chartsSevenDaysRef"></div>
</div>
</div>
</div>
<div class="flex-warp-item">
<div class="flex-warp-item-box">
<div class="flex-title">当前任务统计</div>
<div class="flex-content">
<div class="task">
<div class="task-item task-first-item">
<div class="task-item-value task-first">25</div>
<div class="task-item-label">待办任务</div>
</div>
<div class="task-item">
<div class="task-item-box task1">
<div class="task-item-value">12</div>
<div class="task-item-label">施肥</div>
</div>
</div>
<div class="task-item">
<div class="task-item-box task2">
<div class="task-item-value">3</div>
<div class="task-item-label">施药</div>
</div>
</div>
<div class="task-item">
<div class="task-item-box task3">
<div class="task-item-value">5</div>
<div class="task-item-label">农事</div>
</div>
</div>
</div>
<div class="progress">
<div class="progress-item">
<span>施肥率</span>
<div class="progress-box">
<el-progress :percentage="70" color="#43bdf0"></el-progress>
</div>
</div>
<div class="progress-item">
<span>施药率</span>
<div class="progress-box">
<el-progress :percentage="36" color="#43bdf0"></el-progress>
</div>
</div>
<div class="progress-item">
<span>农事率</span>
<div class="progress-box">
<el-progress :percentage="91" color="#43bdf0"></el-progress>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="flex-warp-item">
<div class="flex-warp-item-box">
<div class="flex-title">
<span>近7天投入品记录</span>
<span class="flex-title-small">单位</span>
</div>
<div class="flex-content">
<div style="height: 100%" ref="chartsInvestmentRef"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import { toRefs, reactive, computed, onMounted } from "vue";
import { useStore } from "/@/store/index.ts";
import ChartHead from "/@/views/chart/head.vue";
import * as echarts from "echarts";
import "echarts-wordcloud";
import {
skyList,
dBtnList,
chartData4List,
earth3DBtnList,
} from "/@/views/chart/chart.ts";
import { toRefs, reactive, computed, onMounted, getCurrentInstance } from 'vue';
import { useStore } from '/@/store/index.ts';
import ChartHead from '/@/views/chart/head.vue';
import * as echarts from 'echarts';
import 'echarts-wordcloud';
import { skyList, dBtnList, chartData4List, earth3DBtnList } from '/@/views/chart/chart.ts';
export default {
name: "chartIndex",
components: { ChartHead },
setup() {
const store = useStore();
const state = reactive({
tagViewHeight: "",
skyList,
dBtnList,
chartData4List,
earth3DBtnList,
});
//
const initTagViewHeight = computed(() => {
let { isTagsview } = store.state.themeConfig;
if (isTagsview) return `114px`;
else return `80px`;
});
// 1
const initChartsCenterOne = () => {
const myChart = echarts.init(document.getElementById("chartsCenterOne"));
const option = {
grid: {
top: 15,
right: 15,
bottom: 20,
left: 30,
},
tooltip: {},
series: [
{
type: "wordCloud",
sizeRange: [12, 40],
rotationRange: [0, 0],
rotationStep: 45,
gridSize: Math.random() * 20 + 5,
shape: "circle",
width: "100%",
height: "100%",
textStyle: {
fontFamily: "sans-serif",
fontWeight: "bold",
color: function () {
return `rgb(${[
Math.round(Math.random() * 160),
Math.round(Math.random() * 160),
Math.round(Math.random() * 160),
].join(",")})`;
},
},
data: [
{ name: "vue-next-admin", value: 520 },
{ name: "lyt", value: 520 },
{ name: "next-admin", value: 500 },
{ name: "更名", value: 420 },
{ name: "智慧农业", value: 520 },
{ name: "男神", value: 2.64 },
{ name: "好身材", value: 4.03 },
{ name: "校草", value: 24.95 },
{ name: "酷", value: 4.04 },
{ name: "时尚", value: 5.27 },
{ name: "阳光活力", value: 5.8 },
{ name: "初恋", value: 3.09 },
{ name: "英俊潇洒", value: 24.71 },
{ name: "霸气", value: 6.33 },
{ name: "腼腆", value: 2.55 },
{ name: "蠢萌", value: 3.88 },
{ name: "青春", value: 8.04 },
{ name: "网红", value: 5.87 },
{ name: "萌", value: 6.97 },
{ name: "认真", value: 2.53 },
{ name: "古典", value: 2.49 },
{ name: "温柔", value: 3.91 },
{ name: "有个性", value: 3.25 },
{ name: "可爱", value: 9.93 },
{ name: "幽默诙谐", value: 3.65 },
],
},
],
};
myChart.setOption(option);
window.addEventListener("resize", () => {
myChart.resize();
});
};
// 7
const initChartsSevenDays = () => {
const myChart = echarts.init(document.getElementById("chartsSevenDays"));
const option = {
grid: {
top: 15,
right: 15,
bottom: 20,
left: 30,
},
tooltip: {
trigger: "axis",
},
xAxis: {
type: "category",
boundaryGap: false,
data: ["1天", "2天", "3天", "4天", "5天", "6天", "7天"],
},
yAxis: {
type: "value",
},
series: [
{
name: "邮件营销",
type: "line",
stack: "总量",
data: [12, 32, 11, 34, 90, 23, 21],
},
{
name: "联盟广告",
type: "line",
stack: "总量",
data: [22, 82, 91, 24, 90, 30, 30],
},
{
name: "视频广告",
type: "line",
stack: "总量",
data: [50, 32, 18, 14, 90, 30, 50],
},
],
};
myChart.setOption(option);
window.addEventListener("resize", () => {
myChart.resize();
});
};
// 30
const initChartsWarning = () => {
const myChart = echarts.init(document.getElementById("chartsWarning"));
const option = {
grid: {
top: 50,
right: 20,
bottom: 30,
left: 30,
},
tooltip: {
trigger: "item",
},
series: [
{
name: "面积模式",
type: "pie",
radius: [20, 50],
center: ["50%", "50%"],
roseType: "area",
itemStyle: {
borderRadius: 8,
},
data: [
{ value: 40, name: "监测设备预警" },
{ value: 38, name: "天气预警" },
{ value: 32, name: "任务预警" },
{ value: 30, name: "病虫害预警" },
],
},
],
};
myChart.setOption(option);
window.addEventListener("resize", () => {
myChart.resize();
});
};
//
const initChartsMonitor = () => {
const myChart = echarts.init(document.getElementById("chartsMonitor"));
const option = {
grid: {
top: 15,
right: 15,
bottom: 20,
left: 30,
},
tooltip: {
trigger: "axis",
},
xAxis: {
type: "category",
boundaryGap: false,
data: ["02:00", "04:00", "06:00", "08:00", "10:00", "12:00", "14:00"],
},
yAxis: {
type: "value",
},
series: [
{
itemStyle: {
color: "#289df5",
borderColor: "#289df5",
areaStyle: {
type: "default",
opacity: 0.1,
},
},
data: [20, 32, 31, 34, 12, 13, 20],
type: "line",
areaStyle: {},
},
],
};
myChart.setOption(option);
window.addEventListener("resize", () => {
myChart.resize();
});
};
// 7
const initChartsInvestment = () => {
const myChart = echarts.init(document.getElementById("chartsInvestment"));
const option = {
grid: {
top: 15,
right: 15,
bottom: 20,
left: 30,
},
tooltip: {
trigger: "axis",
},
xAxis: {
type: "category",
data: ["1天", "2天", "3天", "4天", "5天", "6天", "7天"],
},
yAxis: {
type: "value",
},
series: [
{
data: [10, 20, 15, 80, 70, 11, 30],
type: "bar",
},
],
};
myChart.setOption(option);
window.addEventListener("resize", () => {
myChart.resize();
});
};
//
onMounted(() => {
initChartsCenterOne();
initChartsSevenDays();
initChartsWarning();
initChartsMonitor();
initChartsInvestment();
});
return {
initTagViewHeight,
...toRefs(state),
};
},
name: 'chartIndex',
components: { ChartHead },
setup() {
const { proxy } = getCurrentInstance() as any;
const store = useStore();
const state = reactive({
tagViewHeight: '',
skyList,
dBtnList,
chartData4List,
earth3DBtnList,
});
//
const initTagViewHeight = computed(() => {
let { isTagsview } = store.state.themeConfig.themeConfig;
if (isTagsview) return `114px`;
else return `80px`;
});
// 1
const initChartsCenterOne = () => {
const myChart = echarts.init(proxy.$refs.chartsCenterOneRef);
const option = {
grid: {
top: 15,
right: 15,
bottom: 20,
left: 30,
},
tooltip: {},
series: [
{
type: 'wordCloud',
sizeRange: [12, 40],
rotationRange: [0, 0],
rotationStep: 45,
gridSize: Math.random() * 20 + 5,
shape: 'circle',
width: '100%',
height: '100%',
textStyle: {
fontFamily: 'sans-serif',
fontWeight: 'bold',
color: function () {
return `rgb(${[Math.round(Math.random() * 160), Math.round(Math.random() * 160), Math.round(Math.random() * 160)].join(',')})`;
},
},
data: [
{ name: 'vue-next-admin', value: 520 },
{ name: 'lyt', value: 520 },
{ name: 'next-admin', value: 500 },
{ name: '更名', value: 420 },
{ name: '智慧农业', value: 520 },
{ name: '男神', value: 2.64 },
{ name: '好身材', value: 4.03 },
{ name: '校草', value: 24.95 },
{ name: '酷', value: 4.04 },
{ name: '时尚', value: 5.27 },
{ name: '阳光活力', value: 5.8 },
{ name: '初恋', value: 3.09 },
{ name: '英俊潇洒', value: 24.71 },
{ name: '霸气', value: 6.33 },
{ name: '腼腆', value: 2.55 },
{ name: '蠢萌', value: 3.88 },
{ name: '青春', value: 8.04 },
{ name: '网红', value: 5.87 },
{ name: '萌', value: 6.97 },
{ name: '认真', value: 2.53 },
{ name: '古典', value: 2.49 },
{ name: '温柔', value: 3.91 },
{ name: '有个性', value: 3.25 },
{ name: '可爱', value: 9.93 },
{ name: '幽默诙谐', value: 3.65 },
],
},
],
};
myChart.setOption(option);
window.addEventListener('resize', () => {
myChart.resize();
});
};
// 7
const initChartsSevenDays = () => {
const myChart = echarts.init(proxy.$refs.chartsSevenDaysRef);
const option = {
grid: {
top: 15,
right: 15,
bottom: 20,
left: 30,
},
tooltip: {
trigger: 'axis',
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['1天', '2天', '3天', '4天', '5天', '6天', '7天'],
},
yAxis: {
type: 'value',
},
series: [
{
name: '邮件营销',
type: 'line',
stack: '总量',
data: [12, 32, 11, 34, 90, 23, 21],
},
{
name: '联盟广告',
type: 'line',
stack: '总量',
data: [22, 82, 91, 24, 90, 30, 30],
},
{
name: '视频广告',
type: 'line',
stack: '总量',
data: [50, 32, 18, 14, 90, 30, 50],
},
],
};
myChart.setOption(option);
window.addEventListener('resize', () => {
myChart.resize();
});
};
// 30
const initChartsWarning = () => {
const myChart = echarts.init(proxy.$refs.chartsWarningRef);
const option = {
grid: {
top: 50,
right: 20,
bottom: 30,
left: 30,
},
tooltip: {
trigger: 'item',
},
series: [
{
name: '面积模式',
type: 'pie',
radius: [20, 50],
center: ['50%', '50%'],
roseType: 'area',
itemStyle: {
borderRadius: 8,
},
data: [
{ value: 40, name: '监测设备预警' },
{ value: 38, name: '天气预警' },
{ value: 32, name: '任务预警' },
{ value: 30, name: '病虫害预警' },
],
},
],
};
myChart.setOption(option);
window.addEventListener('resize', () => {
myChart.resize();
});
};
//
const initChartsMonitor = () => {
const myChart = echarts.init(proxy.$refs.chartsMonitorRef);
const option = {
grid: {
top: 15,
right: 15,
bottom: 20,
left: 30,
},
tooltip: {
trigger: 'axis',
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['02:00', '04:00', '06:00', '08:00', '10:00', '12:00', '14:00'],
},
yAxis: {
type: 'value',
},
series: [
{
itemStyle: {
color: '#289df5',
borderColor: '#289df5',
areaStyle: {
type: 'default',
opacity: 0.1,
},
},
data: [20, 32, 31, 34, 12, 13, 20],
type: 'line',
areaStyle: {},
},
],
};
myChart.setOption(option);
window.addEventListener('resize', () => {
myChart.resize();
});
};
// 7
const initChartsInvestment = () => {
const myChart = echarts.init(proxy.$refs.chartsInvestmentRef);
const option = {
grid: {
top: 15,
right: 15,
bottom: 20,
left: 30,
},
tooltip: {
trigger: 'axis',
},
xAxis: {
type: 'category',
data: ['1天', '2天', '3天', '4天', '5天', '6天', '7天'],
},
yAxis: {
type: 'value',
},
series: [
{
data: [10, 20, 15, 80, 70, 11, 30],
type: 'bar',
},
],
};
myChart.setOption(option);
window.addEventListener('resize', () => {
myChart.resize();
});
};
//
onMounted(() => {
initChartsCenterOne();
initChartsSevenDays();
initChartsWarning();
initChartsMonitor();
initChartsInvestment();
});
return {
initTagViewHeight,
...toRefs(state),
};
},
};
</script>
<style scoped lang="scss">
@import "./chart.scss";
</style>
@import './chart.scss';
</style>

View File

@ -1,3 +0,0 @@
<template>
<p v-for="v in 100" :key="v">docs</p>
</template>

View File

@ -1,95 +1,95 @@
<template>
<div class="error">
<div class="error-flex">
<div class="left">
<div class="left-item">
<div class="left-item-animation left-item-num">401</div>
<div class="left-item-animation left-item-title">您未被授权没有操作权限~</div>
<div class="left-item-animation left-item-msg">联系方式加QQ群探讨 665452019</div>
<div class="left-item-animation left-item-btn">
<el-button type="primary" round @click="onSetAuth">重新授权</el-button>
</div>
</div>
</div>
<div class="right">
<img src="https://gitee.com/lyt-top/vue-next-admin-images/raw/master/error/401.png" />
</div>
</div>
</div>
<div class="error">
<div class="error-flex">
<div class="left">
<div class="left-item">
<div class="left-item-animation left-item-num">401</div>
<div class="left-item-animation left-item-title">您未被授权没有操作权限~</div>
<div class="left-item-animation left-item-msg">联系方式加QQ群探讨 665452019</div>
<div class="left-item-animation left-item-btn">
<el-button type="primary" round @click="onSetAuth">重新授权</el-button>
</div>
</div>
</div>
<div class="right">
<img src="https://gitee.com/lyt-top/vue-next-admin-images/raw/master/error/401.png" />
</div>
</div>
</div>
</template>
<script lang="ts">
import { useRouter } from "vue-router";
import { clearSession } from "/@/utils/storage.ts";
import { useRouter } from 'vue-router';
import { clearSession } from '/@/utils/storage.ts';
export default {
name: "401",
setup() {
const router = useRouter();
const onSetAuth = () => {
clearSession();
router.push("/login");
};
return {
onSetAuth,
};
},
name: '401',
setup() {
const router = useRouter();
const onSetAuth = () => {
clearSession();
router.push('/login');
};
return {
onSetAuth,
};
},
};
</script>
<style scoped lang="scss">
.error {
height: 100%;
background-color: white;
display: flex;
.error-flex {
margin: auto;
display: flex;
height: 350px;
width: 900px;
.left {
flex: 1;
height: 100%;
align-items: center;
display: flex;
.left-item {
.left-item-animation {
opacity: 0;
animation-name: error-num;
animation-duration: 0.5s;
animation-fill-mode: forwards;
}
.left-item-num {
color: #d6e0f6;
font-size: 55px;
}
.left-item-title {
font-size: 20px;
color: #333333;
margin: 15px 0 5px 0;
animation-delay: 0.1s;
}
.left-item-msg {
color: #c0bebe;
font-size: 12px;
margin-bottom: 30px;
animation-delay: 0.2s;
}
.left-item-btn {
animation-delay: 0.2s;
}
}
}
.right {
flex: 1;
opacity: 0;
animation-name: error-img;
animation-duration: 2s;
animation-fill-mode: forwards;
img {
width: 100%;
height: 100%;
}
}
}
height: 100%;
background-color: white;
display: flex;
.error-flex {
margin: auto;
display: flex;
height: 350px;
width: 900px;
.left {
flex: 1;
height: 100%;
align-items: center;
display: flex;
.left-item {
.left-item-animation {
opacity: 0;
animation-name: error-num;
animation-duration: 0.5s;
animation-fill-mode: forwards;
}
.left-item-num {
color: #d6e0f6;
font-size: 55px;
}
.left-item-title {
font-size: 20px;
color: #333333;
margin: 15px 0 5px 0;
animation-delay: 0.1s;
}
.left-item-msg {
color: #c0bebe;
font-size: 12px;
margin-bottom: 30px;
animation-delay: 0.2s;
}
.left-item-btn {
animation-delay: 0.2s;
}
}
}
.right {
flex: 1;
opacity: 0;
animation-name: error-img;
animation-duration: 2s;
animation-fill-mode: forwards;
img {
width: 100%;
height: 100%;
}
}
}
}
</style>
</style>

View File

@ -1,93 +1,93 @@
<template>
<div class="error">
<div class="error-flex">
<div class="left">
<div class="left-item">
<div class="left-item-animation left-item-num">404</div>
<div class="left-item-animation left-item-title">地址输入错误请重新输入地址~</div>
<div class="left-item-animation left-item-msg">您可以先检查网址然后重新输入或给我们反馈问题</div>
<div class="left-item-animation left-item-btn">
<el-button type="primary" round @click="onGoHome">返回首页</el-button>
</div>
</div>
</div>
<div class="right">
<img src="https://gitee.com/lyt-top/vue-next-admin-images/raw/master/error/404.png" />
</div>
</div>
</div>
<div class="error">
<div class="error-flex">
<div class="left">
<div class="left-item">
<div class="left-item-animation left-item-num">404</div>
<div class="left-item-animation left-item-title">地址输入错误请重新输入地址~</div>
<div class="left-item-animation left-item-msg">您可以先检查网址然后重新输入或给我们反馈问题</div>
<div class="left-item-animation left-item-btn">
<el-button type="primary" round @click="onGoHome">返回首页</el-button>
</div>
</div>
</div>
<div class="right">
<img src="https://gitee.com/lyt-top/vue-next-admin-images/raw/master/error/404.png" />
</div>
</div>
</div>
</template>
<script lang="ts">
import { useRouter } from "vue-router";
import { useRouter } from 'vue-router';
export default {
name: "404",
setup() {
const router = useRouter();
const onGoHome = () => {
router.push("/");
};
return {
onGoHome,
};
},
name: '404',
setup() {
const router = useRouter();
const onGoHome = () => {
router.push('/');
};
return {
onGoHome,
};
},
};
</script>
<style scoped lang="scss">
.error {
height: 100%;
background-color: white;
display: flex;
.error-flex {
margin: auto;
display: flex;
height: 350px;
width: 900px;
.left {
flex: 1;
height: 100%;
align-items: center;
display: flex;
.left-item {
.left-item-animation {
opacity: 0;
animation-name: error-num;
animation-duration: 0.5s;
animation-fill-mode: forwards;
}
.left-item-num {
color: #d6e0f6;
font-size: 55px;
}
.left-item-title {
font-size: 20px;
color: #333333;
margin: 15px 0 5px 0;
animation-delay: 0.1s;
}
.left-item-msg {
color: #c0bebe;
font-size: 12px;
margin-bottom: 30px;
animation-delay: 0.2s;
}
.left-item-btn {
animation-delay: 0.2s;
}
}
}
.right {
flex: 1;
opacity: 0;
animation-name: error-img;
animation-duration: 2s;
animation-fill-mode: forwards;
img {
width: 100%;
height: 100%;
}
}
}
height: 100%;
background-color: white;
display: flex;
.error-flex {
margin: auto;
display: flex;
height: 350px;
width: 900px;
.left {
flex: 1;
height: 100%;
align-items: center;
display: flex;
.left-item {
.left-item-animation {
opacity: 0;
animation-name: error-num;
animation-duration: 0.5s;
animation-fill-mode: forwards;
}
.left-item-num {
color: #d6e0f6;
font-size: 55px;
}
.left-item-title {
font-size: 20px;
color: #333333;
margin: 15px 0 5px 0;
animation-delay: 0.1s;
}
.left-item-msg {
color: #c0bebe;
font-size: 12px;
margin-bottom: 30px;
animation-delay: 0.2s;
}
.left-item-btn {
animation-delay: 0.2s;
}
}
}
.right {
flex: 1;
opacity: 0;
animation-name: error-img;
animation-duration: 2s;
animation-fill-mode: forwards;
img {
width: 100%;
height: 100%;
}
}
}
}
</style>
</style>

View File

@ -1,153 +1,156 @@
<template>
<div>
<el-card shadow="hover" header="数字滚动演示">
<el-alert title="感谢优秀的 `countup.js`项目地址https://github.com/inorganik/countUp.js" type="success" :closable="false"
class="mb15"></el-alert>
<el-row :gutter="20">
<el-col :sm="6" class="mb15" v-for="(v,k) in topCardItemList" :key="k">
<div class="countup-card-item countup-card-item-box" :style="{background:v.color}">
<div class="countup-card-item-flex">
<div class="countup-card-item-title pb3">{{v.title}}</div>
<div class="countup-card-item-title-num pb6" :id="`titleNum${k+1}`"></div>
<div class="countup-card-item-tip pb3">{{v.tip}}</div>
<div class="countup-card-item-tip-num" :id="`tipNum${k+1}`"></div>
</div>
<i :class="v.icon" :style="{'color': v.iconColor}"></i>
</div>
</el-col>
</el-row>
<div class="flex-warp">
<div class="flex-warp-item">
<div class="flex-warp-item-box">
<el-button type="primary" size="small" icon="el-icon-refresh-right" @click="refreshCurrent">重置/刷新数值
</el-button>
</div>
</div>
</div>
</el-card>
</div>
<div>
<el-card shadow="hover" header="数字滚动演示">
<el-alert
title="感谢优秀的 `countup.js`项目地址https://github.com/inorganik/countUp.js"
type="success"
:closable="false"
class="mb15"
></el-alert>
<el-row :gutter="20">
<el-col :sm="6" class="mb15" v-for="(v, k) in topCardItemList" :key="k">
<div class="countup-card-item countup-card-item-box" :style="{ background: v.color }">
<div class="countup-card-item-flex">
<div class="countup-card-item-title pb3">{{ v.title }}</div>
<div class="countup-card-item-title-num pb6" :id="`titleNum${k + 1}`"></div>
<div class="countup-card-item-tip pb3">{{ v.tip }}</div>
<div class="countup-card-item-tip-num" :id="`tipNum${k + 1}`"></div>
</div>
<i :class="v.icon" :style="{ color: v.iconColor }"></i>
</div>
</el-col>
</el-row>
<div class="flex-warp">
<div class="flex-warp-item">
<div class="flex-warp-item-box">
<el-button type="primary" size="small" icon="el-icon-refresh-right" @click="refreshCurrent">重置/刷新数值 </el-button>
</div>
</div>
</div>
</el-card>
</div>
</template>
<script lang="ts">
import { reactive, toRefs, onMounted, nextTick } from "vue";
import { CountUp } from "countup.js";
import { reactive, toRefs, onMounted, nextTick } from 'vue';
import { CountUp } from 'countup.js';
export default {
name: "countup",
setup() {
const state = reactive({
topCardItemList: [
{
title: "今日访问人数",
titleNum: "123",
tip: "在场人数",
tipNum: "911",
color: "#F95959",
iconColor: "#F86C6B",
icon: "iconfont icon-jinridaiban",
},
{
title: "实验室总数",
titleNum: "123",
tip: "使用中",
tipNum: "611",
color: "#8595F4",
iconColor: "#92A1F4",
icon: "iconfont icon-AIshiyanshi",
},
{
title: "申请人数(月)",
titleNum: "123",
tip: "通过人数",
tipNum: "911",
color: "#FEBB50",
iconColor: "#FDC566",
icon: "iconfont icon-shenqingkaiban",
},
{
title: "销售情况",
titleNum: "123",
tip: "销售数",
tipNum: "911",
color: "#41b3c5",
iconColor: "#1dbcd5",
icon: "el-icon-trophy-1",
},
],
});
//
const initNumCountUp = () => {
nextTick(() => {
new CountUp("titleNum1", Math.random() * 10000).start();
new CountUp("titleNum2", Math.random() * 10000).start();
new CountUp("titleNum3", Math.random() * 10000).start();
new CountUp("titleNum4", Math.random() * 10000).start();
new CountUp("tipNum1", Math.random() * 1000).start();
new CountUp("tipNum2", Math.random() * 1000).start();
new CountUp("tipNum3", Math.random() * 1000).start();
new CountUp("tipNum4", Math.random() * 1000).start();
});
};
// /
const refreshCurrent = () => {
initNumCountUp();
};
//
onMounted(() => {
initNumCountUp();
});
return {
refreshCurrent,
...toRefs(state),
};
},
name: 'countup',
setup() {
const state = reactive({
topCardItemList: [
{
title: '今日访问人数',
titleNum: '123',
tip: '在场人数',
tipNum: '911',
color: '#F95959',
iconColor: '#F86C6B',
icon: 'iconfont icon-jinridaiban',
},
{
title: '实验室总数',
titleNum: '123',
tip: '使用中',
tipNum: '611',
color: '#8595F4',
iconColor: '#92A1F4',
icon: 'iconfont icon-AIshiyanshi',
},
{
title: '申请人数(月)',
titleNum: '123',
tip: '通过人数',
tipNum: '911',
color: '#FEBB50',
iconColor: '#FDC566',
icon: 'iconfont icon-shenqingkaiban',
},
{
title: '销售情况',
titleNum: '123',
tip: '销售数',
tipNum: '911',
color: '#41b3c5',
iconColor: '#1dbcd5',
icon: 'el-icon-trophy-1',
},
],
});
//
const initNumCountUp = () => {
nextTick(() => {
new CountUp('titleNum1', Math.random() * 10000).start();
new CountUp('titleNum2', Math.random() * 10000).start();
new CountUp('titleNum3', Math.random() * 10000).start();
new CountUp('titleNum4', Math.random() * 10000).start();
new CountUp('tipNum1', Math.random() * 1000).start();
new CountUp('tipNum2', Math.random() * 1000).start();
new CountUp('tipNum3', Math.random() * 1000).start();
new CountUp('tipNum4', Math.random() * 1000).start();
});
};
// /
const refreshCurrent = () => {
initNumCountUp();
};
//
onMounted(() => {
initNumCountUp();
});
return {
refreshCurrent,
...toRefs(state),
};
},
};
</script>
<style scoped lang="scss">
.countup-card-item {
width: 100%;
height: 103px;
background: gray;
border-radius: 4px;
transition: all ease 0.3s;
&:hover {
box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
transition: all ease 0.3s;
}
width: 100%;
height: 103px;
background: gray;
border-radius: 4px;
transition: all ease 0.3s;
&:hover {
box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
transition: all ease 0.3s;
}
}
.countup-card-item-box {
display: flex;
align-items: center;
position: relative;
overflow: hidden;
&:hover {
i {
right: 0px !important;
bottom: 0px !important;
transition: all ease 0.3s;
}
}
i {
position: absolute;
right: -10px;
bottom: -10px;
font-size: 70px;
transform: rotate(-30deg);
transition: all ease 0.3s;
}
.countup-card-item-flex {
padding: 0 20px;
color: white;
.countup-card-item-title,
.countup-card-item-tip {
font-size: 13px;
}
.countup-card-item-title-num {
font-size: 18px;
}
.countup-card-item-tip-num {
font-size: 13px;
}
}
display: flex;
align-items: center;
position: relative;
overflow: hidden;
&:hover {
i {
right: 0px !important;
bottom: 0px !important;
transition: all ease 0.3s;
}
}
i {
position: absolute;
right: -10px;
bottom: -10px;
font-size: 70px;
transform: rotate(-30deg);
transition: all ease 0.3s;
}
.countup-card-item-flex {
padding: 0 20px;
color: white;
.countup-card-item-title,
.countup-card-item-tip {
font-size: 13px;
}
.countup-card-item-title-num {
font-size: 18px;
}
.countup-card-item-tip-num {
font-size: 13px;
}
}
}
</style>
</style>

View File

@ -1,54 +1,57 @@
<template>
<div class="croppers-container">
<el-card shadow="hover" header="cropper 图片裁剪">
<el-alert title="感谢优秀的 `cropperjs`项目地址https://github.com/fengyuanchen/cropperjs" type="success"
:closable="false" class="mb15"></el-alert>
<div class="cropper-img-warp">
<div class="mb15 mt15">
<img class="cropper-img" :src="cropperImg">
</div>
<el-button type="primary" icon="el-icon-crop" size="small" @click="onCropperDialogOpen">更换头像</el-button>
</div>
</el-card>
<CropperDialog ref="cropperDialogRef" />
</div>
<div class="croppers-container">
<el-card shadow="hover" header="cropper 图片裁剪">
<el-alert
title="感谢优秀的 `cropperjs`项目地址https://github.com/fengyuanchen/cropperjs"
type="success"
:closable="false"
class="mb15"
></el-alert>
<div class="cropper-img-warp">
<div class="mb15 mt15">
<img class="cropper-img" :src="cropperImg" />
</div>
<el-button type="primary" icon="el-icon-crop" size="small" @click="onCropperDialogOpen">更换头像</el-button>
</div>
</el-card>
<CropperDialog ref="cropperDialogRef" />
</div>
</template>
<script lang="ts">
import { ref, toRefs, reactive } from "vue";
import CropperDialog from "/@/components/cropper/index.vue";
import { ref, toRefs, reactive } from 'vue';
import CropperDialog from '/@/components/cropper/index.vue';
export default {
name: "cropper",
components: { CropperDialog },
setup() {
const cropperDialogRef = ref();
const state = reactive({
cropperImg:
"https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1813762643,1914315241&fm=26&gp=0.jpg",
});
//
const onCropperDialogOpen = () => {
cropperDialogRef.value.openDialog(state.cropperImg);
};
return {
cropperDialogRef,
onCropperDialogOpen,
...toRefs(state),
};
},
name: 'cropper',
components: { CropperDialog },
setup() {
const cropperDialogRef = ref();
const state = reactive({
cropperImg: 'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1813762643,1914315241&fm=26&gp=0.jpg',
});
//
const onCropperDialogOpen = () => {
cropperDialogRef.value.openDialog(state.cropperImg);
};
return {
cropperDialogRef,
onCropperDialogOpen,
...toRefs(state),
};
},
};
</script>
<style scoped lang="scss">
.croppers-container {
.cropper-img-warp {
text-align: center;
.cropper-img {
margin: auto;
width: 150px;
height: 150px;
border-radius: 100%;
}
}
.cropper-img-warp {
text-align: center;
.cropper-img {
margin: auto;
width: 150px;
height: 150px;
border-radius: 100%;
}
}
}
</style>
</style>

View File

@ -0,0 +1,130 @@
<template>
<div :style="{height: `calc(100vh - ${initTagViewHeight}`}">
<div class="layout-view-bg-white">
<div id="echartsMap" style="height:100%;"></div>
</div>
</div>
</template>
<script lang="ts">
import { toRefs, reactive, computed, onMounted } from "vue";
import * as echarts from "echarts";
import "echarts/extension/bmap/bmap";
import { useStore } from "/@/store/index.ts";
import { echartsMapList, echartsMapData } from "./mock.ts";
export default {
name: "echartsMap",
setup() {
const store = useStore();
const state = reactive({
echartsMapList,
echartsMapData,
});
//
const initTagViewHeight = computed(() => {
let { isTagsview } = store.state.themeConfig.themeConfig;
if (isTagsview) return `114px`;
else return `80px`;
});
// echartsMap
const convertData = (data) => {
let res = [];
for (let i = 0; i < data.length; i++) {
let geoCoord = state.echartsMapData[data[i].name];
if (geoCoord) {
res.push({
name: data[i].name,
value: geoCoord.concat(data[i].value),
});
}
}
return res;
};
// echartsMap
const initEchartsMap = () => {
const myChart = echarts.init(document.getElementById("echartsMap"));
const option = {
tooltip: {
trigger: "item",
},
color: ["#9a60b4", "#ea7ccc"],
bmap: {
center: [104.114129, 37.550339],
zoom: 5,
roam: true,
mapStyle: {},
},
series: [
{
name: "pm2.5",
type: "scatter",
coordinateSystem: "bmap",
data: convertData(state.echartsMapList),
symbolSize: function (val) {
return val[2] / 10;
},
encode: {
value: 2,
},
label: {
formatter: "{b}",
position: "right",
show: false,
},
emphasis: {
label: {
show: true,
},
},
},
{
name: "Top 5",
type: "effectScatter",
coordinateSystem: "bmap",
data: convertData(
state.echartsMapList
.sort(function (a, b) {
return b.value - a.value;
})
.slice(0, 6)
),
symbolSize: function (val) {
return val[2] / 10;
},
encode: {
value: 2,
},
showEffectOn: "render",
rippleEffect: {
brushType: "stroke",
},
hoverAnimation: true,
label: {
formatter: "{b}",
position: "right",
show: true,
},
itemStyle: {
shadowBlur: 10,
shadowColor: "#333",
},
zlevel: 1,
},
],
};
myChart.setOption(option);
window.addEventListener("resize", () => {
myChart.resize();
});
};
//
onMounted(() => {
initEchartsMap();
});
return {
initTagViewHeight,
...toRefs(state),
};
},
};
</script>

View File

@ -0,0 +1,387 @@
// 地图模拟数据
export const echartsMapList = [
{ name: '海门', value: 9 },
{ name: '鄂尔多斯', value: 12 },
{ name: '招远', value: 12 },
{ name: '舟山', value: 12 },
{ name: '齐齐哈尔', value: 14 },
{ name: '盐城', value: 15 },
{ name: '赤峰', value: 16 },
{ name: '青岛', value: 18 },
{ name: '乳山', value: 18 },
{ name: '金昌', value: 19 },
{ name: '泉州', value: 21 },
{ name: '莱西', value: 21 },
{ name: '日照', value: 21 },
{ name: '胶南', value: 22 },
{ name: '南通', value: 23 },
{ name: '拉萨', value: 24 },
{ name: '云浮', value: 24 },
{ name: '梅州', value: 25 },
{ name: '文登', value: 25 },
{ name: '上海', value: 25 },
{ name: '攀枝花', value: 25 },
{ name: '威海', value: 25 },
{ name: '承德', value: 25 },
{ name: '厦门', value: 26 },
{ name: '汕尾', value: 26 },
{ name: '潮州', value: 26 },
{ name: '丹东', value: 27 },
{ name: '太仓', value: 27 },
{ name: '曲靖', value: 27 },
{ name: '烟台', value: 28 },
{ name: '福州', value: 29 },
{ name: '瓦房店', value: 30 },
{ name: '即墨', value: 30 },
{ name: '抚顺', value: 31 },
{ name: '玉溪', value: 31 },
{ name: '张家口', value: 31 },
{ name: '阳泉', value: 31 },
{ name: '莱州', value: 32 },
{ name: '湖州', value: 32 },
{ name: '汕头', value: 32 },
{ name: '昆山', value: 33 },
{ name: '宁波', value: 33 },
{ name: '湛江', value: 33 },
{ name: '揭阳', value: 34 },
{ name: '荣成', value: 34 },
{ name: '连云港', value: 35 },
{ name: '葫芦岛', value: 35 },
{ name: '常熟', value: 36 },
{ name: '东莞', value: 36 },
{ name: '河源', value: 36 },
{ name: '淮安', value: 36 },
{ name: '泰州', value: 36 },
{ name: '南宁', value: 37 },
{ name: '营口', value: 37 },
{ name: '惠州', value: 37 },
{ name: '江阴', value: 37 },
{ name: '蓬莱', value: 37 },
{ name: '韶关', value: 38 },
{ name: '嘉峪关', value: 38 },
{ name: '广州', value: 38 },
{ name: '延安', value: 38 },
{ name: '太原', value: 39 },
{ name: '清远', value: 39 },
{ name: '中山', value: 39 },
{ name: '昆明', value: 39 },
{ name: '寿光', value: 40 },
{ name: '盘锦', value: 40 },
{ name: '长治', value: 41 },
{ name: '深圳', value: 360 },
{ name: '珠海', value: 42 },
{ name: '宿迁', value: 43 },
{ name: '咸阳', value: 43 },
{ name: '铜川', value: 44 },
{ name: '平度', value: 44 },
{ name: '佛山', value: 44 },
{ name: '海口', value: 44 },
{ name: '江门', value: 45 },
{ name: '章丘', value: 45 },
{ name: '肇庆', value: 46 },
{ name: '大连', value: 47 },
{ name: '临汾', value: 47 },
{ name: '吴江', value: 47 },
{ name: '石嘴山', value: 49 },
{ name: '沈阳', value: 50 },
{ name: '苏州', value: 50 },
{ name: '茂名', value: 50 },
{ name: '嘉兴', value: 51 },
{ name: '长春', value: 51 },
{ name: '胶州', value: 52 },
{ name: '银川', value: 52 },
{ name: '张家港', value: 52 },
{ name: '三门峡', value: 53 },
{ name: '锦州', value: 54 },
{ name: '南昌', value: 54 },
{ name: '柳州', value: 54 },
{ name: '三亚', value: 54 },
{ name: '自贡', value: 56 },
{ name: '吉林', value: 56 },
{ name: '阳江', value: 57 },
{ name: '泸州', value: 57 },
{ name: '西宁', value: 57 },
{ name: '宜宾', value: 58 },
{ name: '呼和浩特', value: 58 },
{ name: '成都', value: 58 },
{ name: '大同', value: 58 },
{ name: '镇江', value: 59 },
{ name: '桂林', value: 59 },
{ name: '张家界', value: 59 },
{ name: '宜兴', value: 59 },
{ name: '北海', value: 60 },
{ name: '西安', value: 61 },
{ name: '金坛', value: 62 },
{ name: '东营', value: 62 },
{ name: '牡丹江', value: 63 },
{ name: '遵义', value: 63 },
{ name: '绍兴', value: 63 },
{ name: '扬州', value: 64 },
{ name: '常州', value: 64 },
{ name: '潍坊', value: 65 },
{ name: '重庆', value: 66 },
{ name: '台州', value: 67 },
{ name: '南京', value: 67 },
{ name: '滨州', value: 70 },
{ name: '贵阳', value: 71 },
{ name: '无锡', value: 71 },
{ name: '本溪', value: 71 },
{ name: '克拉玛依', value: 72 },
{ name: '渭南', value: 72 },
{ name: '马鞍山', value: 72 },
{ name: '宝鸡', value: 72 },
{ name: '焦作', value: 75 },
{ name: '句容', value: 75 },
{ name: '北京', value: 79 },
{ name: '徐州', value: 79 },
{ name: '衡水', value: 80 },
{ name: '包头', value: 80 },
{ name: '绵阳', value: 80 },
{ name: '乌鲁木齐', value: 84 },
{ name: '枣庄', value: 84 },
{ name: '杭州', value: 84 },
{ name: '淄博', value: 85 },
{ name: '鞍山', value: 86 },
{ name: '溧阳', value: 86 },
{ name: '库尔勒', value: 86 },
{ name: '安阳', value: 90 },
{ name: '开封', value: 90 },
{ name: '济南', value: 92 },
{ name: '德阳', value: 93 },
{ name: '温州', value: 95 },
{ name: '九江', value: 96 },
{ name: '邯郸', value: 98 },
{ name: '临安', value: 99 },
{ name: '兰州', value: 99 },
{ name: '沧州', value: 100 },
{ name: '临沂', value: 103 },
{ name: '南充', value: 104 },
{ name: '天津', value: 105 },
{ name: '富阳', value: 106 },
{ name: '泰安', value: 112 },
{ name: '诸暨', value: 112 },
{ name: '郑州', value: 113 },
{ name: '哈尔滨', value: 114 },
{ name: '聊城', value: 116 },
{ name: '芜湖', value: 117 },
{ name: '唐山', value: 119 },
{ name: '平顶山', value: 119 },
{ name: '邢台', value: 119 },
{ name: '德州', value: 120 },
{ name: '济宁', value: 120 },
{ name: '荆州', value: 127 },
{ name: '宜昌', value: 130 },
{ name: '义乌', value: 132 },
{ name: '丽水', value: 133 },
{ name: '洛阳', value: 134 },
{ name: '秦皇岛', value: 136 },
{ name: '株洲', value: 143 },
{ name: '石家庄', value: 147 },
{ name: '莱芜', value: 148 },
{ name: '常德', value: 152 },
{ name: '保定', value: 153 },
{ name: '湘潭', value: 154 },
{ name: '金华', value: 157 },
{ name: '岳阳', value: 169 },
{ name: '长沙', value: 175 },
{ name: '衢州', value: 177 },
{ name: '廊坊', value: 93 },
{ name: '菏泽', value: 194 },
{ name: '合肥', value: 229 },
{ name: '武汉', value: 273 },
{ name: '大庆', value: 279 }
]
// 地图经纬度数据
export const echartsMapData = {
'海门': [121.15, 31.89],
'鄂尔多斯': [109.781327, 39.608266],
'招远': [120.38, 37.35],
'舟山': [122.207216, 29.985295],
'齐齐哈尔': [123.97, 47.33],
'盐城': [120.13, 33.38],
'赤峰': [118.87, 42.28],
'青岛': [120.33, 36.07],
'乳山': [121.52, 36.89],
'金昌': [102.188043, 38.520089],
'泉州': [118.58, 24.93],
'莱西': [120.53, 36.86],
'日照': [119.46, 35.42],
'胶南': [119.97, 35.88],
'南通': [121.05, 32.08],
'拉萨': [91.11, 29.97],
'云浮': [112.02, 22.93],
'梅州': [116.1, 24.55],
'文登': [122.05, 37.2],
'上海': [121.48, 31.22],
'攀枝花': [101.718637, 26.582347],
'威海': [122.1, 37.5],
'承德': [117.93, 40.97],
'厦门': [118.1, 24.46],
'汕尾': [115.375279, 22.786211],
'潮州': [116.63, 23.68],
'丹东': [124.37, 40.13],
'太仓': [121.1, 31.45],
'曲靖': [103.79, 25.51],
'烟台': [121.39, 37.52],
'福州': [119.3, 26.08],
'瓦房店': [121.979603, 39.627114],
'即墨': [120.45, 36.38],
'抚顺': [123.97, 41.97],
'玉溪': [102.52, 24.35],
'张家口': [114.87, 40.82],
'阳泉': [113.57, 37.85],
'莱州': [119.942327, 37.177017],
'湖州': [120.1, 30.86],
'汕头': [116.69, 23.39],
'昆山': [120.95, 31.39],
'宁波': [121.56, 29.86],
'湛江': [110.359377, 21.270708],
'揭阳': [116.35, 23.55],
'荣成': [122.41, 37.16],
'连云港': [119.16, 34.59],
'葫芦岛': [120.836932, 40.711052],
'常熟': [120.74, 31.64],
'东莞': [113.75, 23.04],
'河源': [114.68, 23.73],
'淮安': [119.15, 33.5],
'泰州': [119.9, 32.49],
'南宁': [108.33, 22.84],
'营口': [122.18, 40.65],
'惠州': [114.4, 23.09],
'江阴': [120.26, 31.91],
'蓬莱': [120.75, 37.8],
'韶关': [113.62, 24.84],
'嘉峪关': [98.289152, 39.77313],
'广州': [113.23, 23.16],
'延安': [109.47, 36.6],
'太原': [112.53, 37.87],
'清远': [113.01, 23.7],
'中山': [113.38, 22.52],
'昆明': [102.73, 25.04],
'寿光': [118.73, 36.86],
'盘锦': [122.070714, 41.119997],
'长治': [113.08, 36.18],
'深圳': [114.07, 22.62],
'珠海': [113.52, 22.3],
'宿迁': [118.3, 33.96],
'咸阳': [108.72, 34.36],
'铜川': [109.11, 35.09],
'平度': [119.97, 36.77],
'佛山': [113.11, 23.05],
'海口': [110.35, 20.02],
'江门': [113.06, 22.61],
'章丘': [117.53, 36.72],
'肇庆': [112.44, 23.05],
'大连': [121.62, 38.92],
'临汾': [111.5, 36.08],
'吴江': [120.63, 31.16],
'石嘴山': [106.39, 39.04],
'沈阳': [123.38, 41.8],
'苏州': [120.62, 31.32],
'茂名': [110.88, 21.68],
'嘉兴': [120.76, 30.77],
'长春': [125.35, 43.88],
'胶州': [120.03336, 36.264622],
'银川': [106.27, 38.47],
'张家港': [120.555821, 31.875428],
'三门峡': [111.19, 34.76],
'锦州': [121.15, 41.13],
'南昌': [115.89, 28.68],
'柳州': [109.4, 24.33],
'三亚': [109.511909, 18.252847],
'自贡': [104.778442, 29.33903],
'吉林': [126.57, 43.87],
'阳江': [111.95, 21.85],
'泸州': [105.39, 28.91],
'西宁': [101.74, 36.56],
'宜宾': [104.56, 29.77],
'呼和浩特': [111.65, 40.82],
'成都': [104.06, 30.67],
'大同': [113.3, 40.12],
'镇江': [119.44, 32.2],
'桂林': [110.28, 25.29],
'张家界': [110.479191, 29.117096],
'宜兴': [119.82, 31.36],
'北海': [109.12, 21.49],
'西安': [108.95, 34.27],
'金坛': [119.56, 31.74],
'东营': [118.49, 37.46],
'牡丹江': [129.58, 44.6],
'遵义': [106.9, 27.7],
'绍兴': [120.58, 30.01],
'扬州': [119.42, 32.39],
'常州': [119.95, 31.79],
'潍坊': [119.1, 36.62],
'重庆': [106.54, 29.59],
'台州': [121.420757, 28.656386],
'南京': [118.78, 32.04],
'滨州': [118.03, 37.36],
'贵阳': [106.71, 26.57],
'无锡': [120.29, 31.59],
'本溪': [123.73, 41.3],
'克拉玛依': [84.77, 45.59],
'渭南': [109.5, 34.52],
'马鞍山': [118.48, 31.56],
'宝鸡': [107.15, 34.38],
'焦作': [113.21, 35.24],
'句容': [119.16, 31.95],
'北京': [116.46, 39.92],
'徐州': [117.2, 34.26],
'衡水': [115.72, 37.72],
'包头': [110, 40.58],
'绵阳': [104.73, 31.48],
'乌鲁木齐': [87.68, 43.77],
'枣庄': [117.57, 34.86],
'杭州': [120.19, 30.26],
'淄博': [118.05, 36.78],
'鞍山': [122.85, 41.12],
'溧阳': [119.48, 31.43],
'库尔勒': [86.06, 41.68],
'安阳': [114.35, 36.1],
'开封': [114.35, 34.79],
'济南': [117, 36.65],
'德阳': [104.37, 31.13],
'温州': [120.65, 28.01],
'九江': [115.97, 29.71],
'邯郸': [114.47, 36.6],
'临安': [119.72, 30.23],
'兰州': [103.73, 36.03],
'沧州': [116.83, 38.33],
'临沂': [118.35, 35.05],
'南充': [106.110698, 30.837793],
'天津': [117.2, 39.13],
'富阳': [119.95, 30.07],
'泰安': [117.13, 36.18],
'诸暨': [120.23, 29.71],
'郑州': [113.65, 34.76],
'哈尔滨': [126.63, 45.75],
'聊城': [115.97, 36.45],
'芜湖': [118.38, 31.33],
'唐山': [118.02, 39.63],
'平顶山': [113.29, 33.75],
'邢台': [114.48, 37.05],
'德州': [116.29, 37.45],
'济宁': [116.59, 35.38],
'荆州': [112.239741, 30.335165],
'宜昌': [111.3, 30.7],
'义乌': [120.06, 29.32],
'丽水': [119.92, 28.45],
'洛阳': [112.44, 34.7],
'秦皇岛': [119.57, 39.95],
'株洲': [113.16, 27.83],
'石家庄': [114.48, 38.03],
'莱芜': [117.67, 36.19],
'常德': [111.69, 29.05],
'保定': [115.48, 38.85],
'湘潭': [112.91, 27.87],
'金华': [119.64, 29.12],
'岳阳': [113.09, 29.37],
'长沙': [113, 28.21],
'衢州': [118.88, 28.97],
'廊坊': [116.7, 39.53],
'菏泽': [115.480656, 35.23375],
'合肥': [117.27, 31.86],
'武汉': [114.31, 30.52],
'大庆': [125.03, 46.58]
}

File diff suppressed because it is too large Load Diff

View File

@ -1,67 +1,73 @@
<template>
<div class="qrcode-container">
<el-card shadow="hover" header="qrcodejs2 二维码生成">
<el-alert title="感谢优秀的 `qrcodejs2`项目地址https://github.com/davidshimjs/qrcodejs" type="success" :closable="false"
class="mb15"></el-alert>
<div class="qrcode-img-warp">
<div class="mb30 mt30 qrcode-img">
<div id="qrcode"></div>
</div>
<el-button type="primary" icon="el-icon-refresh" size="small" @click="onInitQrcode">重新生成</el-button>
</div>
</el-card>
</div>
<div class="qrcode-container">
<el-card shadow="hover" header="qrcodejs2 二维码生成">
<el-alert
title="感谢优秀的 `qrcodejs2`项目地址https://github.com/davidshimjs/qrcodejs"
type="success"
:closable="false"
class="mb15"
></el-alert>
<div class="qrcode-img-warp">
<div class="mb30 mt30 qrcode-img">
<div class="qrcode" ref="qrcodeRef"></div>
</div>
<el-button type="primary" icon="el-icon-refresh" size="small" @click="onInitQrcode">重新生成</el-button>
</div>
</el-card>
</div>
</template>
<script lang="ts">
import { toRefs, reactive, onMounted } from "vue";
import { toRefs, reactive, onMounted, getCurrentInstance } from 'vue';
import QRCode from 'qrcodejs2-fixes';
export default {
name: "qrcode",
setup() {
const state = reactive({
qrcode: "",
});
//
const initQrcode = () => {
new QRCode(document.getElementById("qrcode"), {
text: `https://lyt-top.gitee.io/vue-next-admin-preview/#/login?t=${new Date().getTime()}`,
width: 125,
height: 125,
colorDark: "#000000",
colorLight: "#ffffff",
});
};
//
const onInitQrcode = () => {
document.getElementById("qrcode").innerHTML = "";
initQrcode();
};
//
onMounted(() => {
initQrcode();
});
return {
onInitQrcode,
...toRefs(state),
};
},
name: 'qrcode',
setup() {
const { proxy } = getCurrentInstance() as any;
const state = reactive({
qrcode: '',
});
//
const initQrcode = () => {
new QRCode(proxy.$refs.qrcodeRef, {
text: `https://lyt-top.gitee.io/vue-next-admin-preview/#/login?t=${new Date().getTime()}`,
width: 125,
height: 125,
colorDark: '#000000',
colorLight: '#ffffff',
});
};
//
const onInitQrcode = () => {
proxy.$refs.qrcodeRef.innerHTML = '';
initQrcode();
};
//
onMounted(() => {
initQrcode();
});
return {
onInitQrcode,
...toRefs(state),
};
},
};
</script>
<style scoped lang="scss">
.qrcode-container {
.qrcode-img-warp {
text-align: center;
.qrcode-img {
display: flex;
width: 100%;
height: 125px;
#qrcode {
margin: auto;
width: 125px;
height: 125px;
}
}
}
.qrcode-img-warp {
text-align: center;
.qrcode-img {
display: flex;
width: 100%;
height: 125px;
.qrcode {
margin: auto;
width: 125px;
height: 125px;
}
}
}
}
</style>
</style>

View File

@ -1,30 +1,30 @@
<template>
<div class="selector-container">
<el-card shadow="hover" header="1、图标选择器(宽度自动):简单版本">
<IconSelector @get="ongetCurrentIcon" />
</el-card>
<el-card shadow="hover" header="2、图标选择器(宽度自动):高级版本" class="mt15">
<IconSelector @get="ongetCurrentIcon" :isAllOn="true" />
</el-card>
</div>
<div class="selector-container">
<el-card shadow="hover" header="1、图标选择器(宽度自动):简单版本">
<IconSelector @get="ongetCurrentIcon" />
</el-card>
<el-card shadow="hover" header="2、图标选择器(宽度自动):高级版本" class="mt15">
<IconSelector @get="ongetCurrentIcon" :isAllOn="true" />
</el-card>
</div>
</template>
<script lang="ts">
import { toRefs, reactive } from "vue";
import IconSelector from "/@/components/iconSelector/index.vue";
import { toRefs, reactive } from 'vue';
import IconSelector from '/@/components/iconSelector/index.vue';
export default {
name: "selector",
components: { IconSelector },
setup() {
const state = reactive({});
// icon
const ongetCurrentIcon = (v) => {
console.log(v);
};
return {
ongetCurrentIcon,
...toRefs(state),
};
},
name: 'selector',
components: { IconSelector },
setup() {
const state = reactive({});
// icon
const ongetCurrentIcon = (v: string) => {
console.log(v);
};
return {
ongetCurrentIcon,
...toRefs(state),
};
},
};
</script>
</script>

View File

@ -1,153 +1,148 @@
<template>
<div>
<el-card shadow="hover" header="tagsView 非当前页演示">
<el-form :model="formInline" size="small" label-width="40px" class="tags-view-form">
<el-row :gutter="35">
<el-col :xs="24" :sm="8" :md="8" :lg="6" :xl="4" class="tags-view-form-col">
<el-form-item label="功能">
<el-select v-model="formInline.selectId" placeholder="请选择" class="w100">
<el-option v-for="item in selectOptions" :key="item.value" :label="item.label" :value="item.value">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="8" :md="8" :lg="6" :xl="4" class="tags-view-form-col">
<el-form-item label="路径">
<el-input v-model="formInline.path" placeholder="路径如:/fun/tagsView"></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="8" :md="8" :lg="6" :xl="4">
<el-form-item>
<el-button type="primary" @click="onImplementClick" icon="el-icon-thumb">点击执行</el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
<el-card shadow="hover" header="tagsView 当前页演示" class="mt15">
<div class="flex-warp">
<div class="flex-warp-item">
<div class="flex-warp-item-box">
<el-button type="primary" size="small" icon="el-icon-refresh-right" @click="refreshCurrentTagsView">刷新当前页
</el-button>
</div>
</div>
<div class="flex-warp-item">
<div class="flex-warp-item-box">
<el-button type="info" size="small" icon="el-icon-close" @click="closeCurrentTagsView">关闭当前页</el-button>
</div>
</div>
<div class="flex-warp-item">
<div class="flex-warp-item-box">
<el-button type="warning" size="small" icon="el-icon-circle-close" @click="closeOtherTagsView">关闭其它
</el-button>
</div>
</div>
<div class="flex-warp-item">
<div class="flex-warp-item-box">
<el-button type="danger" size="small" icon="el-icon-folder-delete" @click="closeAllTagsView">全部关闭
</el-button>
</div>
</div>
<div class="flex-warp-item">
<div class="flex-warp-item-box">
<el-button type="success" size="small" icon="el-icon-full-screen" @click="openCurrenFullscreen">当前页全屏
</el-button>
</div>
</div>
</div>
</el-card>
</div>
<div>
<el-card shadow="hover" header="tagsView 非当前页演示">
<el-form :model="formInline" size="small" label-width="40px" class="tags-view-form">
<el-row :gutter="35">
<el-col :xs="24" :sm="8" :md="8" :lg="6" :xl="4" class="tags-view-form-col">
<el-form-item label="功能">
<el-select v-model="formInline.selectId" placeholder="请选择" class="w100">
<el-option v-for="item in selectOptions" :key="item.value" :label="item.label" :value="item.value"> </el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="8" :md="8" :lg="6" :xl="4" class="tags-view-form-col">
<el-form-item label="路径">
<el-input v-model="formInline.path" placeholder="路径如:/fun/tagsView"></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="8" :md="8" :lg="6" :xl="4">
<el-form-item>
<el-button type="primary" @click="onImplementClick" icon="el-icon-thumb">点击执行</el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
<el-card shadow="hover" header="tagsView 当前页演示" class="mt15">
<div class="flex-warp">
<div class="flex-warp-item">
<div class="flex-warp-item-box">
<el-button type="primary" size="small" icon="el-icon-refresh-right" @click="refreshCurrentTagsView">刷新当前页 </el-button>
</div>
</div>
<div class="flex-warp-item">
<div class="flex-warp-item-box">
<el-button type="info" size="small" icon="el-icon-close" @click="closeCurrentTagsView">关闭当前页</el-button>
</div>
</div>
<div class="flex-warp-item">
<div class="flex-warp-item-box">
<el-button type="warning" size="small" icon="el-icon-circle-close" @click="closeOtherTagsView">关闭其它 </el-button>
</div>
</div>
<div class="flex-warp-item">
<div class="flex-warp-item-box">
<el-button type="danger" size="small" icon="el-icon-folder-delete" @click="closeAllTagsView">全部关闭 </el-button>
</div>
</div>
<div class="flex-warp-item">
<div class="flex-warp-item-box">
<el-button type="success" size="small" icon="el-icon-full-screen" @click="openCurrenFullscreen">当前页全屏 </el-button>
</div>
</div>
</div>
</el-card>
</div>
</template>
<script lang="ts">
import { getCurrentInstance, reactive, toRefs } from "vue";
import { useRoute } from "vue-router";
import { getCurrentInstance, reactive, toRefs } from 'vue';
import { useRoute } from 'vue-router';
export default {
name: "funTagsView",
setup() {
const { proxy } = getCurrentInstance();
const route = useRoute();
const state = reactive({
formInline: {
path: "",
selectId: 0,
},
selectOptions: [
{
value: 0,
label: "刷新当前",
},
{
value: 1,
label: "关闭当前",
},
{
value: 2,
label: "关闭其它",
},
{
value: 3,
label: "关闭全部",
},
{
value: 4,
label: "当前页全屏",
},
],
});
// 0 1 2 3 4
// 1 tagsView
const refreshCurrentTagsView = () => {
proxy.mittBus.emit("onCurrentContextmenuClick", {
id: 0,
path: route.path,
});
};
// 2 tagsView
const closeCurrentTagsView = () => {
proxy.mittBus.emit("onCurrentContextmenuClick", {
id: 1,
path: route.path,
});
};
// 3 tagsView
const closeOtherTagsView = () => {
proxy.mittBus.emit("onCurrentContextmenuClick", {
id: 2,
path: route.path,
});
};
// 4 tagsView
const closeAllTagsView = () => {
proxy.mittBus.emit("onCurrentContextmenuClick", {
id: 3,
path: route.path,
});
};
// 5
const openCurrenFullscreen = () => {
proxy.mittBus.emit("onCurrentContextmenuClick", {
id: 4,
path: route.path,
});
};
//
const onImplementClick = () => {
proxy.mittBus.emit("onCurrentContextmenuClick", {
id: state.formInline.selectId,
path: state.formInline.path,
});
};
return {
refreshCurrentTagsView,
closeCurrentTagsView,
closeOtherTagsView,
closeAllTagsView,
openCurrenFullscreen,
onImplementClick,
...toRefs(state),
};
},
name: 'funTagsView',
setup() {
const { proxy } = getCurrentInstance() as any;
const route = useRoute();
const state = reactive({
formInline: {
path: '',
selectId: 0,
},
selectOptions: [
{
value: 0,
label: '刷新当前',
},
{
value: 1,
label: '关闭当前',
},
{
value: 2,
label: '关闭其它',
},
{
value: 3,
label: '关闭全部',
},
{
value: 4,
label: '当前页全屏',
},
],
});
// 0 1 2 3 4
// 1 tagsView
const refreshCurrentTagsView = () => {
proxy.mittBus.emit('onCurrentContextmenuClick', {
id: 0,
path: route.path,
});
};
// 2 tagsView
const closeCurrentTagsView = () => {
proxy.mittBus.emit('onCurrentContextmenuClick', {
id: 1,
path: route.path,
});
};
// 3 tagsView
const closeOtherTagsView = () => {
proxy.mittBus.emit('onCurrentContextmenuClick', {
id: 2,
path: route.path,
});
};
// 4 tagsView
const closeAllTagsView = () => {
proxy.mittBus.emit('onCurrentContextmenuClick', {
id: 3,
path: route.path,
});
};
// 5
const openCurrenFullscreen = () => {
proxy.mittBus.emit('onCurrentContextmenuClick', {
id: 4,
path: route.path,
});
};
//
const onImplementClick = () => {
proxy.mittBus.emit('onCurrentContextmenuClick', {
id: state.formInline.selectId,
path: state.formInline.path,
});
};
return {
refreshCurrentTagsView,
closeCurrentTagsView,
closeOtherTagsView,
closeAllTagsView,
openCurrenFullscreen,
onImplementClick,
...toRefs(state),
};
},
};
</script>
</script>

View File

@ -1,85 +1,86 @@
<template>
<div :style="{height: `calc(100vh - ${initTagViewHeight}`}">
<div class="layout-view-bg-white">
<div id="echartsTree" style="height:100%;"></div>
</div>
</div>
<div :style="{ height: `calc(100vh - ${initTagViewHeight}` }">
<div class="layout-view-bg-white">
<div style="height: 100%" ref="echartsTreeRef"></div>
</div>
</div>
</template>
<script lang="ts">
import { toRefs, reactive, computed, onMounted } from "vue";
import * as echarts from "echarts";
import { useStore } from "/@/store/index.ts";
import { echartsTreeList } from "./mock.ts";
import { toRefs, reactive, computed, onMounted, getCurrentInstance } from 'vue';
import * as echarts from 'echarts';
import { useStore } from '/@/store/index.ts';
import { echartsTreeList } from './mock.ts';
export default {
name: "echartsTree",
setup() {
const store = useStore();
const state = reactive({
tagViewHeight: "",
echartsTreeList,
});
//
const initTagViewHeight = computed(() => {
let { isTagsview } = store.state.themeConfig;
if (isTagsview) return `114px`;
else return `80px`;
});
//
const initEchartsTree = () => {
const myChart = echarts.init(document.getElementById("echartsTree"));
state.echartsTreeList.children.forEach((datum, index) => {
index % 2 === 0 && (datum.collapsed = true);
});
const option = {
tooltip: {
trigger: "item",
triggerOn: "mousemove",
},
series: [
{
type: "tree",
data: [state.echartsTreeList],
top: "1%",
left: "7%",
bottom: "1%",
right: "20%",
symbolSize: 7,
label: {
position: "left",
verticalAlign: "middle",
align: "right",
fontSize: 9,
},
leaves: {
label: {
position: "right",
verticalAlign: "middle",
align: "left",
},
},
emphasis: {
focus: "descendant",
},
expandAndCollapse: true,
animationDuration: 550,
animationDurationUpdate: 750,
},
],
};
myChart.setOption(option);
window.addEventListener("resize", () => {
myChart.resize();
});
};
//
onMounted(() => {
initEchartsTree();
});
return {
initTagViewHeight,
...toRefs(state),
};
},
name: 'echartsTree',
setup() {
const { proxy } = getCurrentInstance() as any;
const store = useStore();
const state = reactive({
tagViewHeight: '',
echartsTreeList,
});
//
const initTagViewHeight = computed(() => {
let { isTagsview } = store.state.themeConfig.themeConfig;
if (isTagsview) return `114px`;
else return `80px`;
});
//
const initEchartsTree = () => {
const myChart = echarts.init(proxy.$refs.echartsTreeRef);
state.echartsTreeList.children.forEach((datum: any, index: number) => {
index % 2 === 0 && (datum.collapsed = true);
});
const option = {
tooltip: {
trigger: 'item',
triggerOn: 'mousemove',
},
series: [
{
type: 'tree',
data: [state.echartsTreeList],
top: '1%',
left: '7%',
bottom: '1%',
right: '20%',
symbolSize: 7,
label: {
position: 'left',
verticalAlign: 'middle',
align: 'right',
fontSize: 9,
},
leaves: {
label: {
position: 'right',
verticalAlign: 'middle',
align: 'left',
},
},
emphasis: {
focus: 'descendant',
},
expandAndCollapse: true,
animationDuration: 550,
animationDurationUpdate: 750,
},
],
};
myChart.setOption(option);
window.addEventListener('resize', () => {
myChart.resize();
});
};
//
onMounted(() => {
initEchartsTree();
});
return {
initTagViewHeight,
...toRefs(state),
};
},
};
</script>
</script>

View File

@ -1,381 +1,377 @@
// 模拟数据
export const echartsTreeList = {
"name": "flare",
"children": [
{
"name": "analytics",
"children": [
{
"name": "cluster",
"children": [
{ "name": "AgglomerativeCluster", "value": 3938 },
{ "name": "CommunityStructure", "value": 3812 },
{ "name": "HierarchicalCluster", "value": 6714 },
{ "name": "MergeEdge", "value": 743 }
]
},
{
"name": "graph",
"children": [
{ "name": "BetweennessCentrality", "value": 3534 },
{ "name": "LinkDistance", "value": 5731 },
{ "name": "MaxFlowMinCut", "value": 7840 },
{ "name": "ShortestPaths", "value": 5914 },
{ "name": "SpanningTree", "value": 3416 }
]
},
{
"name": "optimization",
"children": [
{ "name": "AspectRatioBanker", "value": 7074 }
]
}
]
},
{
"name": "animate",
"children": [
{ "name": "Easing", "value": 17010 },
{ "name": "FunctionSequence", "value": 5842 },
{
"name": "interpolate",
"children": [
{ "name": "ArrayInterpolator", "value": 1983 },
{ "name": "ColorInterpolator", "value": 2047 },
{ "name": "DateInterpolator", "value": 1375 },
{ "name": "Interpolator", "value": 8746 },
{ "name": "MatrixInterpolator", "value": 2202 },
{ "name": "NumberInterpolator", "value": 1382 },
{ "name": "ObjectInterpolator", "value": 1629 },
{ "name": "PointInterpolator", "value": 1675 },
{ "name": "RectangleInterpolator", "value": 2042 }
]
},
{ "name": "ISchedulable", "value": 1041 },
{ "name": "Parallel", "value": 5176 },
{ "name": "Pause", "value": 449 },
{ "name": "Scheduler", "value": 5593 },
{ "name": "Sequence", "value": 5534 },
{ "name": "Transition", "value": 9201 },
{ "name": "Transitioner", "value": 19975 },
{ "name": "TransitionEvent", "value": 1116 },
{ "name": "Tween", "value": 6006 }
]
},
{
"name": "data",
"children": [
{
"name": "converters",
"children": [
{ "name": "Converters", "value": 721 },
{ "name": "DelimitedTextConverter", "value": 4294 },
{ "name": "GraphMLConverter", "value": 9800 },
{ "name": "IDataConverter", "value": 1314 },
{ "name": "JSONConverter", "value": 2220 }
]
},
{ "name": "DataField", "value": 1759 },
{ "name": "DataSchema", "value": 2165 },
{ "name": "DataSet", "value": 586 },
{ "name": "DataSource", "value": 3331 },
{ "name": "DataTable", "value": 772 },
{ "name": "DataUtil", "value": 3322 }
]
},
{
"name": "display",
"children": [
{ "name": "DirtySprite", "value": 8833 },
{ "name": "LineSprite", "value": 1732 },
{ "name": "RectSprite", "value": 3623 },
{ "name": "TextSprite", "value": 10066 }
]
},
{
"name": "flex",
"children": [
{ "name": "FlareVis", "value": 4116 }
]
},
{
"name": "physics",
"children": [
{ "name": "DragForce", "value": 1082 },
{ "name": "GravityForce", "value": 1336 },
{ "name": "IForce", "value": 319 },
{ "name": "NBodyForce", "value": 10498 },
{ "name": "Particle", "value": 2822 },
{ "name": "Simulation", "value": 9983 },
{ "name": "Spring", "value": 2213 },
{ "name": "SpringForce", "value": 1681 }
]
},
{
"name": "query",
"children": [
{ "name": "AggregateExpression", "value": 1616 },
{ "name": "And", "value": 1027 },
{ "name": "Arithmetic", "value": 3891 },
{ "name": "Average", "value": 891 },
{ "name": "BinaryExpression", "value": 2893 },
{ "name": "Comparison", "value": 5103 },
{ "name": "CompositeExpression", "value": 3677 },
{ "name": "Count", "value": 781 },
{ "name": "DateUtil", "value": 4141 },
{ "name": "Distinct", "value": 933 },
{ "name": "Expression", "value": 5130 },
{ "name": "ExpressionIterator", "value": 3617 },
{ "name": "Fn", "value": 3240 },
{ "name": "If", "value": 2732 },
{ "name": "IsA", "value": 2039 },
{ "name": "Literal", "value": 1214 },
{ "name": "Match", "value": 3748 },
{ "name": "Maximum", "value": 843 },
{
"name": "methods",
"children": [
{ "name": "add", "value": 593 },
{ "name": "and", "value": 330 },
{ "name": "average", "value": 287 },
{ "name": "count", "value": 277 },
{ "name": "distinct", "value": 292 },
{ "name": "div", "value": 595 },
{ "name": "eq", "value": 594 },
{ "name": "fn", "value": 460 },
{ "name": "gt", "value": 603 },
{ "name": "gte", "value": 625 },
{ "name": "iff", "value": 748 },
{ "name": "isa", "value": 461 },
{ "name": "lt", "value": 597 },
{ "name": "lte", "value": 619 },
{ "name": "max", "value": 283 },
{ "name": "min", "value": 283 },
{ "name": "mod", "value": 591 },
{ "name": "mul", "value": 603 },
{ "name": "neq", "value": 599 },
{ "name": "not", "value": 386 },
{ "name": "or", "value": 323 },
{ "name": "orderby", "value": 307 },
{ "name": "range", "value": 772 },
{ "name": "select", "value": 296 },
{ "name": "stddev", "value": 363 },
{ "name": "sub", "value": 600 },
{ "name": "sum", "value": 280 },
{ "name": "update", "value": 307 },
{ "name": "variance", "value": 335 },
{ "name": "where", "value": 299 },
{ "name": "xor", "value": 354 },
{ "name": "-", "value": 264 }
]
},
{ "name": "Minimum", "value": 843 },
{ "name": "Not", "value": 1554 },
{ "name": "Or", "value": 970 },
{ "name": "Query", "value": 13896 },
{ "name": "Range", "value": 1594 },
{ "name": "StringUtil", "value": 4130 },
{ "name": "Sum", "value": 791 },
{ "name": "Variable", "value": 1124 },
{ "name": "Variance", "value": 1876 },
{ "name": "Xor", "value": 1101 }
]
},
{
"name": "scale",
"children": [
{ "name": "IScaleMap", "value": 2105 },
{ "name": "LinearScale", "value": 1316 },
{ "name": "LogScale", "value": 3151 },
{ "name": "OrdinalScale", "value": 3770 },
{ "name": "QuantileScale", "value": 2435 },
{ "name": "QuantitativeScale", "value": 4839 },
{ "name": "RootScale", "value": 1756 },
{ "name": "Scale", "value": 4268 },
{ "name": "ScaleType", "value": 1821 },
{ "name": "TimeScale", "value": 5833 }
]
},
{
"name": "util",
"children": [
{ "name": "Arrays", "value": 8258 },
{ "name": "Colors", "value": 10001 },
{ "name": "Dates", "value": 8217 },
{ "name": "Displays", "value": 12555 },
{ "name": "Filter", "value": 2324 },
{ "name": "Geometry", "value": 10993 },
{
"name": "heap",
"children": [
{ "name": "FibonacciHeap", "value": 9354 },
{ "name": "HeapNode", "value": 1233 }
]
},
{ "name": "IEvaluable", "value": 335 },
{ "name": "IPredicate", "value": 383 },
{ "name": "IValueProxy", "value": 874 },
{
"name": "math",
"children": [
{ "name": "DenseMatrix", "value": 3165 },
{ "name": "IMatrix", "value": 2815 },
{ "name": "SparseMatrix", "value": 3366 }
]
},
{ "name": "Maths", "value": 17705 },
{ "name": "Orientation", "value": 1486 },
{
"name": "palette",
"children": [
{ "name": "ColorPalette", "value": 6367 },
{ "name": "Palette", "value": 1229 },
{ "name": "ShapePalette", "value": 2059 },
{ "name": "SizePalette", "value": 2291 }
]
},
{ "name": "Property", "value": 5559 },
{ "name": "Shapes", "value": 19118 },
{ "name": "Sort", "value": 6887 },
{ "name": "Stats", "value": 6557 },
{ "name": "Strings", "value": 22026 }
]
},
{
"name": "vis",
"children": [
{
"name": "axis",
"children": [
{ "name": "Axes", "value": 1302 },
{ "name": "Axis", "value": 24593 },
{ "name": "AxisGridLine", "value": 652 },
{ "name": "AxisLabel", "value": 636 },
{ "name": "CartesianAxes", "value": 6703 }
]
},
{
"name": "controls",
"children": [
{ "name": "AnchorControl", "value": 2138 },
{ "name": "ClickControl", "value": 3824 },
{ "name": "Control", "value": 1353 },
{ "name": "ControlList", "value": 4665 },
{ "name": "DragControl", "value": 2649 },
{ "name": "ExpandControl", "value": 2832 },
{ "name": "HoverControl", "value": 4896 },
{ "name": "IControl", "value": 763 },
{ "name": "PanZoomControl", "value": 5222 },
{ "name": "SelectionControl", "value": 7862 },
{ "name": "TooltipControl", "value": 8435 }
]
},
{
"name": "data",
"children": [
{ "name": "Data", "value": 20544 },
{ "name": "DataList", "value": 19788 },
{ "name": "DataSprite", "value": 10349 },
{ "name": "EdgeSprite", "value": 3301 },
{ "name": "NodeSprite", "value": 19382 },
{
"name": "render",
"children": [
{ "name": "ArrowType", "value": 698 },
{ "name": "EdgeRenderer", "value": 5569 },
{ "name": "IRenderer", "value": 353 },
{ "name": "ShapeRenderer", "value": 2247 }
]
},
{ "name": "ScaleBinding", "value": 11275 },
{ "name": "Tree", "value": 7147 },
{ "name": "TreeBuilder", "value": 9930 }
]
},
{
"name": "events",
"children": [
{ "name": "DataEvent", "value": 2313 },
{ "name": "SelectionEvent", "value": 1880 },
{ "name": "TooltipEvent", "value": 1701 },
{ "name": "VisualizationEvent", "value": 1117 }
]
},
{
"name": "legend",
"children": [
{ "name": "Legend", "value": 20859 },
{ "name": "LegendItem", "value": 4614 },
{ "name": "LegendRange", "value": 10530 }
]
},
{
"name": "operator",
"children": [
{
"name": "distortion",
"children": [
{ "name": "BifocalDistortion", "value": 4461 },
{ "name": "Distortion", "value": 6314 },
{ "name": "FisheyeDistortion", "value": 3444 }
]
},
{
"name": "encoder",
"children": [
{ "name": "ColorEncoder", "value": 3179 },
{ "name": "Encoder", "value": 4060 },
{ "name": "PropertyEncoder", "value": 4138 },
{ "name": "ShapeEncoder", "value": 1690 },
{ "name": "SizeEncoder", "value": 1830 }
]
},
{
"name": "filter",
"children": [
{ "name": "FisheyeTreeFilter", "value": 5219 },
{ "name": "GraphDistanceFilter", "value": 3165 },
{ "name": "VisibilityFilter", "value": 3509 }
]
},
{ "name": "IOperator", "value": 1286 },
{
"name": "label",
"children": [
{ "name": "Labeler", "value": 9956 },
{ "name": "RadialLabeler", "value": 3899 },
{ "name": "StackedAreaLabeler", "value": 3202 }
]
},
{
"name": "layout",
"children": [
{ "name": "AxisLayout", "value": 6725 },
{ "name": "BundledEdgeRouter", "value": 3727 },
{ "name": "CircleLayout", "value": 9317 },
{ "name": "CirclePackingLayout", "value": 12003 },
{ "name": "DendrogramLayout", "value": 4853 },
{ "name": "ForceDirectedLayout", "value": 8411 },
{ "name": "IcicleTreeLayout", "value": 4864 },
{ "name": "IndentedTreeLayout", "value": 3174 },
{ "name": "Layout", "value": 7881 },
{ "name": "NodeLinkTreeLayout", "value": 12870 },
{ "name": "PieLayout", "value": 2728 },
{ "name": "RadialTreeLayout", "value": 12348 },
{ "name": "RandomLayout", "value": 870 },
{ "name": "StackedAreaLayout", "value": 9121 },
{ "name": "TreeMapLayout", "value": 9191 }
]
},
{ "name": "Operator", "value": 2490 },
{ "name": "OperatorList", "value": 5248 },
{ "name": "OperatorSequence", "value": 4190 },
{ "name": "OperatorSwitch", "value": 2581 },
{ "name": "SortOperator", "value": 2023 }
]
},
{ "name": "Visualization", "value": 16540 }
]
}
]
}
name: 'flare',
children: [
{
name: 'analytics',
children: [
{
name: 'cluster',
children: [
{ name: 'AgglomerativeCluster', value: 3938 },
{ name: 'CommunityStructure', value: 3812 },
{ name: 'HierarchicalCluster', value: 6714 },
{ name: 'MergeEdge', value: 743 },
],
},
{
name: 'graph',
children: [
{ name: 'BetweennessCentrality', value: 3534 },
{ name: 'LinkDistance', value: 5731 },
{ name: 'MaxFlowMinCut', value: 7840 },
{ name: 'ShortestPaths', value: 5914 },
{ name: 'SpanningTree', value: 3416 },
],
},
{
name: 'optimization',
children: [{ name: 'AspectRatioBanker', value: 7074 }],
},
],
},
{
name: 'animate',
children: [
{ name: 'Easing', value: 17010 },
{ name: 'FunctionSequence', value: 5842 },
{
name: 'interpolate',
children: [
{ name: 'ArrayInterpolator', value: 1983 },
{ name: 'ColorInterpolator', value: 2047 },
{ name: 'DateInterpolator', value: 1375 },
{ name: 'Interpolator', value: 8746 },
{ name: 'MatrixInterpolator', value: 2202 },
{ name: 'NumberInterpolator', value: 1382 },
{ name: 'ObjectInterpolator', value: 1629 },
{ name: 'PointInterpolator', value: 1675 },
{ name: 'RectangleInterpolator', value: 2042 },
],
},
{ name: 'ISchedulable', value: 1041 },
{ name: 'Parallel', value: 5176 },
{ name: 'Pause', value: 449 },
{ name: 'Scheduler', value: 5593 },
{ name: 'Sequence', value: 5534 },
{ name: 'Transition', value: 9201 },
{ name: 'Transitioner', value: 19975 },
{ name: 'TransitionEvent', value: 1116 },
{ name: 'Tween', value: 6006 },
],
},
{
name: 'data',
children: [
{
name: 'converters',
children: [
{ name: 'Converters', value: 721 },
{ name: 'DelimitedTextConverter', value: 4294 },
{ name: 'GraphMLConverter', value: 9800 },
{ name: 'IDataConverter', value: 1314 },
{ name: 'JSONConverter', value: 2220 },
],
},
{ name: 'DataField', value: 1759 },
{ name: 'DataSchema', value: 2165 },
{ name: 'DataSet', value: 586 },
{ name: 'DataSource', value: 3331 },
{ name: 'DataTable', value: 772 },
{ name: 'DataUtil', value: 3322 },
],
},
{
name: 'display',
children: [
{ name: 'DirtySprite', value: 8833 },
{ name: 'LineSprite', value: 1732 },
{ name: 'RectSprite', value: 3623 },
{ name: 'TextSprite', value: 10066 },
],
},
{
name: 'flex',
children: [{ name: 'FlareVis', value: 4116 }],
},
{
name: 'physics',
children: [
{ name: 'DragForce', value: 1082 },
{ name: 'GravityForce', value: 1336 },
{ name: 'IForce', value: 319 },
{ name: 'NBodyForce', value: 10498 },
{ name: 'Particle', value: 2822 },
{ name: 'Simulation', value: 9983 },
{ name: 'Spring', value: 2213 },
{ name: 'SpringForce', value: 1681 },
],
},
{
name: 'query',
children: [
{ name: 'AggregateExpression', value: 1616 },
{ name: 'And', value: 1027 },
{ name: 'Arithmetic', value: 3891 },
{ name: 'Average', value: 891 },
{ name: 'BinaryExpression', value: 2893 },
{ name: 'Comparison', value: 5103 },
{ name: 'CompositeExpression', value: 3677 },
{ name: 'Count', value: 781 },
{ name: 'DateUtil', value: 4141 },
{ name: 'Distinct', value: 933 },
{ name: 'Expression', value: 5130 },
{ name: 'ExpressionIterator', value: 3617 },
{ name: 'Fn', value: 3240 },
{ name: 'If', value: 2732 },
{ name: 'IsA', value: 2039 },
{ name: 'Literal', value: 1214 },
{ name: 'Match', value: 3748 },
{ name: 'Maximum', value: 843 },
{
name: 'methods',
children: [
{ name: 'add', value: 593 },
{ name: 'and', value: 330 },
{ name: 'average', value: 287 },
{ name: 'count', value: 277 },
{ name: 'distinct', value: 292 },
{ name: 'div', value: 595 },
{ name: 'eq', value: 594 },
{ name: 'fn', value: 460 },
{ name: 'gt', value: 603 },
{ name: 'gte', value: 625 },
{ name: 'iff', value: 748 },
{ name: 'isa', value: 461 },
{ name: 'lt', value: 597 },
{ name: 'lte', value: 619 },
{ name: 'max', value: 283 },
{ name: 'min', value: 283 },
{ name: 'mod', value: 591 },
{ name: 'mul', value: 603 },
{ name: 'neq', value: 599 },
{ name: 'not', value: 386 },
{ name: 'or', value: 323 },
{ name: 'orderby', value: 307 },
{ name: 'range', value: 772 },
{ name: 'select', value: 296 },
{ name: 'stddev', value: 363 },
{ name: 'sub', value: 600 },
{ name: 'sum', value: 280 },
{ name: 'update', value: 307 },
{ name: 'variance', value: 335 },
{ name: 'where', value: 299 },
{ name: 'xor', value: 354 },
{ name: '-', value: 264 },
],
},
{ name: 'Minimum', value: 843 },
{ name: 'Not', value: 1554 },
{ name: 'Or', value: 970 },
{ name: 'Query', value: 13896 },
{ name: 'Range', value: 1594 },
{ name: 'StringUtil', value: 4130 },
{ name: 'Sum', value: 791 },
{ name: 'Variable', value: 1124 },
{ name: 'Variance', value: 1876 },
{ name: 'Xor', value: 1101 },
],
},
{
name: 'scale',
children: [
{ name: 'IScaleMap', value: 2105 },
{ name: 'LinearScale', value: 1316 },
{ name: 'LogScale', value: 3151 },
{ name: 'OrdinalScale', value: 3770 },
{ name: 'QuantileScale', value: 2435 },
{ name: 'QuantitativeScale', value: 4839 },
{ name: 'RootScale', value: 1756 },
{ name: 'Scale', value: 4268 },
{ name: 'ScaleType', value: 1821 },
{ name: 'TimeScale', value: 5833 },
],
},
{
name: 'util',
children: [
{ name: 'Arrays', value: 8258 },
{ name: 'Colors', value: 10001 },
{ name: 'Dates', value: 8217 },
{ name: 'Displays', value: 12555 },
{ name: 'Filter', value: 2324 },
{ name: 'Geometry', value: 10993 },
{
name: 'heap',
children: [
{ name: 'FibonacciHeap', value: 9354 },
{ name: 'HeapNode', value: 1233 },
],
},
{ name: 'IEvaluable', value: 335 },
{ name: 'IPredicate', value: 383 },
{ name: 'IValueProxy', value: 874 },
{
name: 'math',
children: [
{ name: 'DenseMatrix', value: 3165 },
{ name: 'IMatrix', value: 2815 },
{ name: 'SparseMatrix', value: 3366 },
],
},
{ name: 'Maths', value: 17705 },
{ name: 'Orientation', value: 1486 },
{
name: 'palette',
children: [
{ name: 'ColorPalette', value: 6367 },
{ name: 'Palette', value: 1229 },
{ name: 'ShapePalette', value: 2059 },
{ name: 'SizePalette', value: 2291 },
],
},
{ name: 'Property', value: 5559 },
{ name: 'Shapes', value: 19118 },
{ name: 'Sort', value: 6887 },
{ name: 'Stats', value: 6557 },
{ name: 'Strings', value: 22026 },
],
},
{
name: 'vis',
children: [
{
name: 'axis',
children: [
{ name: 'Axes', value: 1302 },
{ name: 'Axis', value: 24593 },
{ name: 'AxisGridLine', value: 652 },
{ name: 'AxisLabel', value: 636 },
{ name: 'CartesianAxes', value: 6703 },
],
},
{
name: 'controls',
children: [
{ name: 'AnchorControl', value: 2138 },
{ name: 'ClickControl', value: 3824 },
{ name: 'Control', value: 1353 },
{ name: 'ControlList', value: 4665 },
{ name: 'DragControl', value: 2649 },
{ name: 'ExpandControl', value: 2832 },
{ name: 'HoverControl', value: 4896 },
{ name: 'IControl', value: 763 },
{ name: 'PanZoomControl', value: 5222 },
{ name: 'SelectionControl', value: 7862 },
{ name: 'TooltipControl', value: 8435 },
],
},
{
name: 'data',
children: [
{ name: 'Data', value: 20544 },
{ name: 'DataList', value: 19788 },
{ name: 'DataSprite', value: 10349 },
{ name: 'EdgeSprite', value: 3301 },
{ name: 'NodeSprite', value: 19382 },
{
name: 'render',
children: [
{ name: 'ArrowType', value: 698 },
{ name: 'EdgeRenderer', value: 5569 },
{ name: 'IRenderer', value: 353 },
{ name: 'ShapeRenderer', value: 2247 },
],
},
{ name: 'ScaleBinding', value: 11275 },
{ name: 'Tree', value: 7147 },
{ name: 'TreeBuilder', value: 9930 },
],
},
{
name: 'events',
children: [
{ name: 'DataEvent', value: 2313 },
{ name: 'SelectionEvent', value: 1880 },
{ name: 'TooltipEvent', value: 1701 },
{ name: 'VisualizationEvent', value: 1117 },
],
},
{
name: 'legend',
children: [
{ name: 'Legend', value: 20859 },
{ name: 'LegendItem', value: 4614 },
{ name: 'LegendRange', value: 10530 },
],
},
{
name: 'operator',
children: [
{
name: 'distortion',
children: [
{ name: 'BifocalDistortion', value: 4461 },
{ name: 'Distortion', value: 6314 },
{ name: 'FisheyeDistortion', value: 3444 },
],
},
{
name: 'encoder',
children: [
{ name: 'ColorEncoder', value: 3179 },
{ name: 'Encoder', value: 4060 },
{ name: 'PropertyEncoder', value: 4138 },
{ name: 'ShapeEncoder', value: 1690 },
{ name: 'SizeEncoder', value: 1830 },
],
},
{
name: 'filter',
children: [
{ name: 'FisheyeTreeFilter', value: 5219 },
{ name: 'GraphDistanceFilter', value: 3165 },
{ name: 'VisibilityFilter', value: 3509 },
],
},
{ name: 'IOperator', value: 1286 },
{
name: 'label',
children: [
{ name: 'Labeler', value: 9956 },
{ name: 'RadialLabeler', value: 3899 },
{ name: 'StackedAreaLabeler', value: 3202 },
],
},
{
name: 'layout',
children: [
{ name: 'AxisLayout', value: 6725 },
{ name: 'BundledEdgeRouter', value: 3727 },
{ name: 'CircleLayout', value: 9317 },
{ name: 'CirclePackingLayout', value: 12003 },
{ name: 'DendrogramLayout', value: 4853 },
{ name: 'ForceDirectedLayout', value: 8411 },
{ name: 'IcicleTreeLayout', value: 4864 },
{ name: 'IndentedTreeLayout', value: 3174 },
{ name: 'Layout', value: 7881 },
{ name: 'NodeLinkTreeLayout', value: 12870 },
{ name: 'PieLayout', value: 2728 },
{ name: 'RadialTreeLayout', value: 12348 },
{ name: 'RandomLayout', value: 870 },
{ name: 'StackedAreaLayout', value: 9121 },
{ name: 'TreeMapLayout', value: 9191 },
],
},
{ name: 'Operator', value: 2490 },
{ name: 'OperatorList', value: 5248 },
{ name: 'OperatorSequence', value: 4190 },
{ name: 'OperatorSwitch', value: 2581 },
{ name: 'SortOperator', value: 2023 },
],
},
{ name: 'Visualization', value: 16540 },
],
},
],
};

View File

@ -1,39 +1,43 @@
<template>
<div class="editor-container">
<el-card shadow="hover" header="wangeditor富文本编辑器">
<el-alert title="感谢优秀的 `wangeditor`项目地址https://github.com/wangeditor-team/wangEditor" type="success"
:closable="false" class="mb15"></el-alert>
<div id="wangeditor"></div>
</el-card>
</div>
<div class="editor-container">
<el-card shadow="hover" header="wangeditor富文本编辑器">
<el-alert
title="感谢优秀的 `wangeditor`项目地址https://github.com/wangeditor-team/wangEditor"
type="success"
:closable="false"
class="mb15"
></el-alert>
<div id="wangeditor"></div>
</el-card>
</div>
</template>
<script lang="ts">
import { toRefs, reactive, onMounted } from "vue";
import wangeditor from "wangeditor";
import { toRefs, reactive, onMounted } from 'vue';
import wangeditor from 'wangeditor';
export default {
name: "wangeditor",
setup() {
const state = reactive({});
//
// https://doc.wangeditor.com/
const initWangeditor = () => {
const editor = new wangeditor("#wangeditor");
editor.config.placeholder = "请输入内容";
editor.config.onchange = (html) => {
console.log(html);
// console.log(editor.txt.html());
// console.log(editor.txt.text());
};
editor.create();
};
//
onMounted(() => {
initWangeditor();
});
return {
...toRefs(state),
};
},
name: 'wangeditor',
setup() {
const state = reactive({});
//
// https://doc.wangeditor.com/
const initWangeditor = () => {
const editor = new wangeditor('#wangeditor');
editor.config.placeholder = '请输入内容';
editor.config.onchange = (html: string) => {
console.log(html);
// console.log(editor.txt.html());
// console.log(editor.txt.text());
};
editor.create();
};
//
onMounted(() => {
initWangeditor();
});
return {
...toRefs(state),
};
},
};
</script>
</script>

View File

@ -1,418 +1,406 @@
<template>
<div class="home-container">
<el-row :gutter="15">
<el-col :sm="6" class="mb15">
<div class="home-card-item home-card-first">
<div class="flex-margin flex">
<img src="https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1813762643,1914315241&fm=26&gp=0.jpg">
<div class="home-card-first-right ml15">
<div class="flex-margin">
<div class="home-card-first-right-title">{{currentTime}}admin</div>
<div class="home-card-first-right-msg mt5">超级管理</div>
</div>
</div>
</div>
</div>
</el-col>
<el-col :sm="6" class="mb15" v-for="(v,k) in topCardItemList" :key="k">
<div class="home-card-item home-card-item-box" :style="{background:v.color}">
<div class="home-card-item-flex">
<div class="home-card-item-title pb3">{{v.title}}</div>
<div class="home-card-item-title-num pb6" :id="`titleNum${k+1}`"></div>
<div class="home-card-item-tip pb3">{{v.tip}}</div>
<div class="home-card-item-tip-num" :id="`tipNum${k+1}`"></div>
</div>
<i :class="v.icon" :style="{'color': v.iconColor}"></i>
</div>
</el-col>
</el-row>
<el-row :gutter="15">
<el-col :xs="24" :sm="14" :md="14" :lg="16" :xl="16" class="mb15">
<el-card shadow="hover" header="商品销售情况">
<div id="homeLaboratory" style="height:200px;"></div>
</el-card>
</el-col>
<el-col :xs="24" :sm="10" :md="10" :lg="8" :xl="8">
<el-card shadow="hover" header="环境监测">
<div class="home-monitor">
<div class="flex-warp">
<div class="flex-warp-item" v-for="(v,k) in environmentList" :key="k">
<div class="flex-warp-item-box">
<i :class="v.icon" :style="{color:v.iconColor}"></i>
<span class="pl5">{{v.label}}</span>
<div class="mt10">{{v.value}}</div>
</div>
</div>
</div>
</div>
</el-card>
</el-col>
</el-row>
<el-row :gutter="15">
<el-col :xs="24" :sm="14" :md="14" :lg="16" :xl="16" class="home-warning-media">
<el-card shadow="hover" header="预警信息" class="home-warning-card">
<el-table :data="tableData.data" style="width: 100%;" stripe>
<el-table-column prop="date" label="时间"></el-table-column>
<el-table-column prop="name" label="实验室名称"></el-table-column>
<el-table-column prop="address" label="报警内容"></el-table-column>
</el-table>
</el-card>
</el-col>
<el-col :xs="24" :sm="10" :md="10" :lg="8" :xl="8" class="home-dynamic-media">
<el-card shadow="hover" header="动态信息">
<div class="home-dynamic">
<el-scrollbar>
<div class="home-dynamic-item" v-for="(v,k) in activitiesList" :key="k">
<div class="home-dynamic-item-left">
<div class="home-dynamic-item-left-time1 mb5">{{v.time1}}</div>
<div class="home-dynamic-item-left-time2">{{v.time2}}</div>
</div>
<div class="home-dynamic-item-line">
<i class="iconfont icon-fangkuang"></i>
</div>
<div class="home-dynamic-item-right">
<div class="home-dynamic-item-right-title mb5">
<i class="el-icon-s-comment"></i>
<span>{{v.title}}</span>
</div>
<div class="home-dynamic-item-right-label">{{v.label}}</div>
</div>
</div>
</el-scrollbar>
</div>
</el-card>
</el-col>
</el-row>
<el-row>
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mt15">
<el-card shadow="hover" header="履约超时预警">
<div id="homeOvertime" style="height:200px;"></div>
</el-card>
</el-col>
</el-row>
</div>
<div class="home-container">
<el-row :gutter="15">
<el-col :sm="6" class="mb15">
<div class="home-card-item home-card-first">
<div class="flex-margin flex">
<img src="https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1813762643,1914315241&fm=26&gp=0.jpg" />
<div class="home-card-first-right ml15">
<div class="flex-margin">
<div class="home-card-first-right-title">{{ currentTime }}admin</div>
<div class="home-card-first-right-msg mt5">超级管理</div>
</div>
</div>
</div>
</div>
</el-col>
<el-col :sm="6" class="mb15" v-for="(v, k) in topCardItemList" :key="k">
<div class="home-card-item home-card-item-box" :style="{ background: v.color }">
<div class="home-card-item-flex">
<div class="home-card-item-title pb3">{{ v.title }}</div>
<div class="home-card-item-title-num pb6" :id="`titleNum${k + 1}`"></div>
<div class="home-card-item-tip pb3">{{ v.tip }}</div>
<div class="home-card-item-tip-num" :id="`tipNum${k + 1}`"></div>
</div>
<i :class="v.icon" :style="{ color: v.iconColor }"></i>
</div>
</el-col>
</el-row>
<el-row :gutter="15">
<el-col :xs="24" :sm="14" :md="14" :lg="16" :xl="16" class="mb15">
<el-card shadow="hover" header="商品销售情况">
<div style="height: 200px" ref="homeLaboratoryRef"></div>
</el-card>
</el-col>
<el-col :xs="24" :sm="10" :md="10" :lg="8" :xl="8">
<el-card shadow="hover" header="环境监测">
<div class="home-monitor">
<div class="flex-warp">
<div class="flex-warp-item" v-for="(v, k) in environmentList" :key="k">
<div class="flex-warp-item-box">
<i :class="v.icon" :style="{ color: v.iconColor }"></i>
<span class="pl5">{{ v.label }}</span>
<div class="mt10">{{ v.value }}</div>
</div>
</div>
</div>
</div>
</el-card>
</el-col>
</el-row>
<el-row :gutter="15">
<el-col :xs="24" :sm="14" :md="14" :lg="16" :xl="16" class="home-warning-media">
<el-card shadow="hover" header="预警信息" class="home-warning-card">
<el-table :data="tableData.data" style="width: 100%" stripe>
<el-table-column prop="date" label="时间"></el-table-column>
<el-table-column prop="name" label="实验室名称"></el-table-column>
<el-table-column prop="address" label="报警内容"></el-table-column>
</el-table>
</el-card>
</el-col>
<el-col :xs="24" :sm="10" :md="10" :lg="8" :xl="8" class="home-dynamic-media">
<el-card shadow="hover" header="动态信息">
<div class="home-dynamic">
<el-scrollbar>
<div class="home-dynamic-item" v-for="(v, k) in activitiesList" :key="k">
<div class="home-dynamic-item-left">
<div class="home-dynamic-item-left-time1 mb5">{{ v.time1 }}</div>
<div class="home-dynamic-item-left-time2">{{ v.time2 }}</div>
</div>
<div class="home-dynamic-item-line">
<i class="iconfont icon-fangkuang"></i>
</div>
<div class="home-dynamic-item-right">
<div class="home-dynamic-item-right-title mb5">
<i class="el-icon-s-comment"></i>
<span>{{ v.title }}</span>
</div>
<div class="home-dynamic-item-right-label">{{ v.label }}</div>
</div>
</div>
</el-scrollbar>
</div>
</el-card>
</el-col>
</el-row>
<el-row>
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mt15">
<el-card shadow="hover" header="履约超时预警">
<div style="height: 200px" ref="homeOvertimeRef"></div>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script lang="ts">
import { toRefs, reactive, onMounted, nextTick, computed } from "vue";
import * as echarts from "echarts";
import { CountUp } from "countup.js";
import { formatAxis } from "/@/utils/formatTime";
import { topCardItemList, environmentList, activitiesList } from "./mock.ts";
import { toRefs, reactive, onMounted, nextTick, computed, getCurrentInstance } from 'vue';
import * as echarts from 'echarts';
import { CountUp } from 'countup.js';
import { formatAxis } from '/@/utils/formatTime.ts';
import { topCardItemList, environmentList, activitiesList } from './mock.ts';
export default {
name: "home",
setup() {
const state = reactive({
topCardItemList,
environmentList,
activitiesList,
tableData: {
data: [
{
date: "2016-05-02",
name: "1号实验室",
address: "烟感2.1%OBS/M",
},
{
date: "2016-05-04",
name: "2号实验室",
address: "温度30℃",
},
{
date: "2016-05-01",
name: "3号实验室",
address: "湿度57%RH",
},
],
},
});
//
const currentTime = computed(() => {
return formatAxis(new Date());
});
//
const initNumCountUp = () => {
nextTick(() => {
new CountUp("titleNum1", Math.random() * 10000).start();
new CountUp("titleNum2", Math.random() * 10000).start();
new CountUp("titleNum3", Math.random() * 10000).start();
new CountUp("tipNum1", Math.random() * 1000).start();
new CountUp("tipNum2", Math.random() * 1000).start();
new CountUp("tipNum3", Math.random() * 1000).start();
});
};
// 使
const initHomeLaboratory = () => {
const myChart = echarts.init(document.getElementById("homeLaboratory"));
const option = {
grid: {
top: 50,
right: 20,
bottom: 30,
left: 30,
},
tooltip: {
trigger: "axis",
},
legend: {
data: ["预购队列", "最新成交价"],
right: 13,
},
xAxis: {
data: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"],
},
yAxis: [
{
type: "value",
name: "价格",
},
],
series: [
{
name: "预购队列",
type: "bar",
data: [5, 20, 36, 10, 10, 20],
},
{
name: "最新成交价",
type: "line",
data: [15, 20, 16, 20, 30, 8],
},
],
};
myChart.setOption(option);
window.addEventListener("resize", () => {
myChart.resize();
});
};
//
const initHomeOvertime = () => {
const myChart = echarts.init(document.getElementById("homeOvertime"));
const option = {
grid: {
top: 50,
right: 20,
bottom: 30,
left: 30,
},
tooltip: {
trigger: "axis",
},
legend: {
data: ["订单数量", "超时数量", "在线数量", "预警数量"],
right: 13,
},
xAxis: {
data: [
"1月",
"2月",
"3月",
"4月",
"5月",
"6月",
"7月",
"8月",
"9月",
"10月",
"11月",
"12月",
],
},
yAxis: [
{
type: "value",
name: "数量",
},
],
series: [
{
name: "订单数量",
type: "bar",
data: [5, 20, 36, 10, 10, 20, 11, 13, 10, 9, 17, 19],
},
{
name: "超时数量",
type: "bar",
data: [15, 12, 26, 15, 11, 16, 31, 13, 5, 16, 13, 15],
},
{
name: "在线数量",
type: "line",
data: [15, 20, 16, 20, 30, 8, 16, 19, 12, 18, 19, 14],
},
{
name: "预警数量",
type: "line",
data: [10, 10, 13, 12, 15, 18, 19, 10, 12, 15, 11, 17],
},
],
};
myChart.setOption(option);
window.addEventListener("resize", () => {
myChart.resize();
});
};
//
onMounted(() => {
initNumCountUp();
initHomeLaboratory();
initHomeOvertime();
});
return {
currentTime,
...toRefs(state),
};
},
name: 'home',
setup() {
const { proxy } = getCurrentInstance() as any;
const state = reactive({
topCardItemList,
environmentList,
activitiesList,
tableData: {
data: [
{
date: '2016-05-02',
name: '1号实验室',
address: '烟感2.1%OBS/M',
},
{
date: '2016-05-04',
name: '2号实验室',
address: '温度30℃',
},
{
date: '2016-05-01',
name: '3号实验室',
address: '湿度57%RH',
},
],
},
});
//
const currentTime = computed(() => {
return formatAxis(new Date());
});
//
const initNumCountUp = () => {
nextTick(() => {
new CountUp('titleNum1', Math.random() * 10000).start();
new CountUp('titleNum2', Math.random() * 10000).start();
new CountUp('titleNum3', Math.random() * 10000).start();
new CountUp('tipNum1', Math.random() * 1000).start();
new CountUp('tipNum2', Math.random() * 1000).start();
new CountUp('tipNum3', Math.random() * 1000).start();
});
};
// 使
const initHomeLaboratory = () => {
const myChart = echarts.init(proxy.$refs.homeLaboratoryRef);
const option = {
grid: {
top: 50,
right: 20,
bottom: 30,
left: 30,
},
tooltip: {
trigger: 'axis',
},
legend: {
data: ['预购队列', '最新成交价'],
right: 13,
},
xAxis: {
data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'],
},
yAxis: [
{
type: 'value',
name: '价格',
},
],
series: [
{
name: '预购队列',
type: 'bar',
data: [5, 20, 36, 10, 10, 20],
},
{
name: '最新成交价',
type: 'line',
data: [15, 20, 16, 20, 30, 8],
},
],
};
myChart.setOption(option);
window.addEventListener('resize', () => {
myChart.resize();
});
};
//
const initHomeOvertime = () => {
const myChart = echarts.init(proxy.$refs.homeOvertimeRef);
const option = {
grid: {
top: 50,
right: 20,
bottom: 30,
left: 30,
},
tooltip: {
trigger: 'axis',
},
legend: {
data: ['订单数量', '超时数量', '在线数量', '预警数量'],
right: 13,
},
xAxis: {
data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
},
yAxis: [
{
type: 'value',
name: '数量',
},
],
series: [
{
name: '订单数量',
type: 'bar',
data: [5, 20, 36, 10, 10, 20, 11, 13, 10, 9, 17, 19],
},
{
name: '超时数量',
type: 'bar',
data: [15, 12, 26, 15, 11, 16, 31, 13, 5, 16, 13, 15],
},
{
name: '在线数量',
type: 'line',
data: [15, 20, 16, 20, 30, 8, 16, 19, 12, 18, 19, 14],
},
{
name: '预警数量',
type: 'line',
data: [10, 10, 13, 12, 15, 18, 19, 10, 12, 15, 11, 17],
},
],
};
myChart.setOption(option);
window.addEventListener('resize', () => {
myChart.resize();
});
};
//
onMounted(() => {
initNumCountUp();
initHomeLaboratory();
initHomeOvertime();
});
return {
currentTime,
...toRefs(state),
};
},
};
</script>
<style scoped lang="scss">
.home-container {
overflow-x: hidden;
.home-card-item {
width: 100%;
height: 103px;
background: gray;
border-radius: 4px;
transition: all ease 0.3s;
&:hover {
box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
transition: all ease 0.3s;
}
}
.home-card-item-box {
display: flex;
align-items: center;
position: relative;
overflow: hidden;
&:hover {
i {
right: 0px !important;
bottom: 0px !important;
transition: all ease 0.3s;
}
}
i {
position: absolute;
right: -10px;
bottom: -10px;
font-size: 70px;
transform: rotate(-30deg);
transition: all ease 0.3s;
}
.home-card-item-flex {
padding: 0 20px;
color: white;
.home-card-item-title,
.home-card-item-tip {
font-size: 13px;
}
.home-card-item-title-num {
font-size: 18px;
}
.home-card-item-tip-num {
font-size: 13px;
}
}
}
.home-card-first {
background: white;
border: 1px solid #ebeef5;
display: flex;
align-items: center;
img {
width: 60px;
height: 60px;
border-radius: 100%;
border: 2px solid var(--color-primary-light-5);
}
.home-card-first-right {
flex: 1;
display: flex;
flex-direction: column;
.home-card-first-right-msg {
font-size: 13px;
color: gray;
}
}
}
.home-monitor {
height: 200px;
.flex-warp-item {
width: 50%;
height: 100px;
display: flex;
.flex-warp-item-box {
margin: auto;
height: auto;
text-align: center;
}
}
}
.home-warning-card {
height: 292px;
::v-deep(.el-card) {
height: 100%;
}
}
.home-dynamic {
height: 200px;
.home-dynamic-item {
display: flex;
width: 100%;
height: 60px;
overflow: hidden;
&:first-of-type {
.home-dynamic-item-line {
i {
color: orange !important;
}
}
}
.home-dynamic-item-left {
text-align: right;
.home-dynamic-item-left-time1 {
}
.home-dynamic-item-left-time2 {
font-size: 13px;
color: gray;
}
}
.home-dynamic-item-line {
height: 60px;
border-right: 2px dashed #dfdfdf;
margin: 0 20px;
position: relative;
i {
color: var(--color-primary);
font-size: 12px;
position: absolute;
top: 1px;
left: -6px;
transform: rotate(46deg);
background: white;
}
}
.home-dynamic-item-right {
flex: 1;
.home-dynamic-item-right-title {
i {
margin-right: 5px;
border: 1px solid #dfdfdf;
width: 20px;
height: 20px;
border-radius: 100%;
padding: 3px 2px 2px;
text-align: center;
color: var(--color-primary);
}
}
.home-dynamic-item-right-label {
font-size: 13px;
color: gray;
}
}
}
}
overflow-x: hidden;
.home-card-item {
width: 100%;
height: 103px;
background: gray;
border-radius: 4px;
transition: all ease 0.3s;
&:hover {
box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
transition: all ease 0.3s;
}
}
.home-card-item-box {
display: flex;
align-items: center;
position: relative;
overflow: hidden;
&:hover {
i {
right: 0px !important;
bottom: 0px !important;
transition: all ease 0.3s;
}
}
i {
position: absolute;
right: -10px;
bottom: -10px;
font-size: 70px;
transform: rotate(-30deg);
transition: all ease 0.3s;
}
.home-card-item-flex {
padding: 0 20px;
color: white;
.home-card-item-title,
.home-card-item-tip {
font-size: 13px;
}
.home-card-item-title-num {
font-size: 18px;
}
.home-card-item-tip-num {
font-size: 13px;
}
}
}
.home-card-first {
background: white;
border: 1px solid #ebeef5;
display: flex;
align-items: center;
img {
width: 60px;
height: 60px;
border-radius: 100%;
border: 2px solid var(--color-primary-light-5);
}
.home-card-first-right {
flex: 1;
display: flex;
flex-direction: column;
.home-card-first-right-msg {
font-size: 13px;
color: gray;
}
}
}
.home-monitor {
height: 200px;
.flex-warp-item {
width: 50%;
height: 100px;
display: flex;
.flex-warp-item-box {
margin: auto;
height: auto;
text-align: center;
}
}
}
.home-warning-card {
height: 292px;
::v-deep(.el-card) {
height: 100%;
}
}
.home-dynamic {
height: 200px;
.home-dynamic-item {
display: flex;
width: 100%;
height: 60px;
overflow: hidden;
&:first-of-type {
.home-dynamic-item-line {
i {
color: orange !important;
}
}
}
.home-dynamic-item-left {
text-align: right;
.home-dynamic-item-left-time1 {
}
.home-dynamic-item-left-time2 {
font-size: 13px;
color: gray;
}
}
.home-dynamic-item-line {
height: 60px;
border-right: 2px dashed #dfdfdf;
margin: 0 20px;
position: relative;
i {
color: var(--color-primary);
font-size: 12px;
position: absolute;
top: 1px;
left: -6px;
transform: rotate(46deg);
background: white;
}
}
.home-dynamic-item-right {
flex: 1;
.home-dynamic-item-right-title {
i {
margin-right: 5px;
border: 1px solid #dfdfdf;
width: 20px;
height: 20px;
border-radius: 100%;
padding: 3px 2px 2px;
text-align: center;
color: var(--color-primary);
}
}
.home-dynamic-item-right-label {
font-size: 13px;
color: gray;
}
}
}
}
}
</style>
</style>

View File

@ -1,80 +1,80 @@
// 最顶部 card
export const topCardItemList = [
{
title: '今日访问人数',
titleNum: '123',
tip: '在场人数',
tipNum: '911',
color: '#F95959',
iconColor: '#F86C6B',
icon: 'iconfont icon-jinridaiban'
},
{
title: '实验室总数',
titleNum: '123',
tip: '使用中',
tipNum: '611',
color: '#8595F4',
iconColor: '#92A1F4',
icon: 'iconfont icon-AIshiyanshi'
},
{
title: '申请人数(月)',
titleNum: '123',
tip: '通过人数',
tipNum: '911',
color: '#FEBB50',
iconColor: '#FDC566',
icon: 'iconfont icon-shenqingkaiban'
}
]
{
title: '今日访问人数',
titleNum: '123',
tip: '在场人数',
tipNum: '911',
color: '#F95959',
iconColor: '#F86C6B',
icon: 'iconfont icon-jinridaiban',
},
{
title: '实验室总数',
titleNum: '123',
tip: '使用中',
tipNum: '611',
color: '#8595F4',
iconColor: '#92A1F4',
icon: 'iconfont icon-AIshiyanshi',
},
{
title: '申请人数(月)',
titleNum: '123',
tip: '通过人数',
tipNum: '911',
color: '#FEBB50',
iconColor: '#FDC566',
icon: 'iconfont icon-shenqingkaiban',
},
];
// 环境监测
export const environmentList = [
{
icon: 'iconfont icon-yangan',
label: '烟感',
value: '2.1%OBS/M',
iconColor: '#F72B3F'
},
{
icon: 'iconfont icon-wendu',
label: '温度',
value: '30℃',
iconColor: '#91BFF8'
},
{
icon: 'iconfont icon-shidu',
label: '湿度',
value: '57%RH',
iconColor: '#88D565'
},
{
icon: 'iconfont icon-zaosheng',
label: '噪声',
value: '57DB',
iconColor: '#FBD4A0'
}
]
{
icon: 'iconfont icon-yangan',
label: '烟感',
value: '2.1%OBS/M',
iconColor: '#F72B3F',
},
{
icon: 'iconfont icon-wendu',
label: '温度',
value: '30℃',
iconColor: '#91BFF8',
},
{
icon: 'iconfont icon-shidu',
label: '湿度',
value: '57%RH',
iconColor: '#88D565',
},
{
icon: 'iconfont icon-zaosheng',
label: '噪声',
value: '57DB',
iconColor: '#FBD4A0',
},
];
// 动态信息
export const activitiesList = [
{
time1: '今天',
time2: '12:20:30',
title: '更名',
label: '正式更名为 vue-next-admin'
},
{
time1: '02-17',
time2: '12:20:30',
title: '页面',
label: '完成对首页的开发'
},
{
time1: '02-14',
time2: '12:20:30',
title: '页面',
label: '新增个人中心'
}
]
{
time1: '今天',
time2: '12:20:30',
title: '更名',
label: '正式更名为 vue-next-admin',
},
{
time1: '02-17',
time2: '12:20:30',
title: '页面',
label: '完成对首页的开发',
},
{
time1: '02-14',
time2: '12:20:30',
title: '页面',
label: '新增个人中心',
},
];

View File

@ -1,151 +1,131 @@
<template>
<el-aside class="layout-aside" :class="setCollapseWidth" v-if="clientWidth > 1000">
<Logo v-if="setShowLogo" />
<el-scrollbar class="flex-auto" ref="layoutAsideScrollbarRef">
<Vertical :menuList="menuList" :class="setCollapseWidth" />
</el-scrollbar>
</el-aside>
<el-drawer v-model="getThemeConfig.isCollapse" :with-header="false" direction="ltr" size="220px" v-else>
<el-aside class="layout-aside w100 h100">
<Logo v-if="setShowLogo" />
<el-scrollbar class="flex-auto" ref="layoutAsideScrollbarRef">
<Vertical :menuList="menuList" />
</el-scrollbar>
</el-aside>
</el-drawer>
<el-aside class="layout-aside" :class="setCollapseWidth" v-if="clientWidth > 1000">
<Logo v-if="setShowLogo" />
<el-scrollbar class="flex-auto" ref="layoutAsideScrollbarRef">
<Vertical :menuList="menuList" :class="setCollapseWidth" />
</el-scrollbar>
</el-aside>
<el-drawer v-model="getThemeConfig.isCollapse" :with-header="false" direction="ltr" size="220px" v-else>
<el-aside class="layout-aside w100 h100">
<Logo v-if="setShowLogo" />
<el-scrollbar class="flex-auto" ref="layoutAsideScrollbarRef">
<Vertical :menuList="menuList" />
</el-scrollbar>
</el-aside>
</el-drawer>
</template>
<script lang="ts">
import {
toRefs,
reactive,
computed,
watch,
getCurrentInstance,
ref,
onBeforeMount,
onUnmounted,
nextTick,
} from "vue";
import { useStore } from "/@/store/index.ts";
import Logo from "/@/views/layout/logo/index.vue";
import Vertical from "/@/views/layout/navMenu/vertical.vue";
import { stat } from "fs";
import { toRefs, reactive, computed, watch, getCurrentInstance, onBeforeMount, onUnmounted } from 'vue';
import { useStore } from '/@/store/index.ts';
import Logo from '/@/views/layout/logo/index.vue';
import Vertical from '/@/views/layout/navMenu/vertical.vue';
export default {
name: "layoutAside",
components: { Logo, Vertical },
setup() {
const { proxy } = getCurrentInstance();
const store = useStore();
const state = reactive({
menuList: [],
clientWidth: "",
});
//
const getThemeConfig = computed(() => {
return store.state.themeConfig;
});
// /
const setCollapseWidth = computed(() => {
let { layout, isCollapse, menuBar } = store.state.themeConfig;
let asideBrColor =
menuBar === "#FFFFFF" ||
menuBar === "#FFF" ||
menuBar === "#fff" ||
menuBar === "#ffffff"
? "layout-el-aside-br-color"
: "";
if (layout === "columns") {
// 1px
if (isCollapse) {
return ["layout-aside-width1", asideBrColor];
} else {
return ["layout-aside-width-default", asideBrColor];
}
} else {
// 64px
if (isCollapse) {
return ["layout-aside-width64", asideBrColor];
} else {
return ["layout-aside-width-default", asideBrColor];
}
}
});
// / logo
const setShowLogo = computed(() => {
let { layout, isShowLogo } = store.state.themeConfig;
return (
(isShowLogo && layout === "defaults") ||
(isShowLogo && layout === "columns")
);
});
// //
const setFilterRoutes = () => {
if (store.state.themeConfig.layout === "columns") return false;
state.menuList = filterRoutesFun(store.state.routes);
};
//
const filterRoutesFun = (arr: Array<object>) => {
return arr
.filter((item) => !item.meta.isHide)
.map((item) => {
item = Object.assign({}, item);
if (item.children) item.children = filterRoutesFun(item.children);
return item;
});
};
//
const initMenuFixed = (clientWidth: number) => {
state.clientWidth = clientWidth;
};
// themeConfig el-scrollbar
watch(store.state.themeConfig, (val) => {
if (val.isShowLogoChange !== val.isShowLogo) {
if (!proxy.$refs.layoutAsideScrollbarRef) return false;
proxy.$refs.layoutAsideScrollbarRef.update();
}
});
//
watch(store.state, (val) => {
if (val.routes.length === state.menuList.length) return false;
let { layout, isClassicSplitMenu } = val.themeConfig;
if (layout === "classic" && isClassicSplitMenu) return false;
setFilterRoutes();
});
//
onBeforeMount(() => {
initMenuFixed(document.body.clientWidth);
setFilterRoutes();
proxy.mittBus.on("setSendColumnsChildren", (res) => {
state.menuList = res.children;
});
proxy.mittBus.on("setSendClassicChildren", (res) => {
let { layout, isClassicSplitMenu } = store.state.themeConfig;
if (layout === "classic" && isClassicSplitMenu) {
state.menuList = [];
state.menuList = res.children;
}
});
proxy.mittBus.on("getBreadcrumbIndexSetFilterRoutes", () => {
setFilterRoutes();
});
proxy.mittBus.on("layoutMobileResize", (res) => {
initMenuFixed(res.clientWidth);
});
});
//
onUnmounted(() => {
proxy.mittBus.off("setSendColumnsChildren");
proxy.mittBus.off("setSendClassicChildren");
proxy.mittBus.off("getBreadcrumbIndexSetFilterRoutes");
proxy.mittBus.off("layoutMobileResize");
});
return {
setCollapseWidth,
setShowLogo,
getThemeConfig,
...toRefs(state),
};
},
name: 'layoutAside',
components: { Logo, Vertical },
setup() {
const { proxy } = getCurrentInstance() as any;
const store = useStore();
const state: any = reactive({
menuList: [],
clientWidth: '',
});
//
const getThemeConfig = computed(() => {
return store.state.themeConfig.themeConfig;
});
// /
const setCollapseWidth = computed(() => {
let { layout, isCollapse, menuBar } = store.state.themeConfig.themeConfig;
let asideBrColor = menuBar === '#FFFFFF' || menuBar === '#FFF' || menuBar === '#fff' || menuBar === '#ffffff' ? 'layout-el-aside-br-color' : '';
if (layout === 'columns') {
// 1px
if (isCollapse) {
return ['layout-aside-width1', asideBrColor];
} else {
return ['layout-aside-width-default', asideBrColor];
}
} else {
// 64px
if (isCollapse) {
return ['layout-aside-width64', asideBrColor];
} else {
return ['layout-aside-width-default', asideBrColor];
}
}
});
// / logo
const setShowLogo = computed(() => {
let { layout, isShowLogo } = store.state.themeConfig.themeConfig;
return (isShowLogo && layout === 'defaults') || (isShowLogo && layout === 'columns');
});
// //
const setFilterRoutes = () => {
if (store.state.themeConfig.themeConfig.layout === 'columns') return false;
state.menuList = filterRoutesFun(store.state.routesList.routesList);
};
//
const filterRoutesFun = (arr: Array<object>) => {
return arr
.filter((item: any) => !item.meta.isHide)
.map((item: any) => {
item = Object.assign({}, item);
if (item.children) item.children = filterRoutesFun(item.children);
return item;
});
};
//
const initMenuFixed = (clientWidth: number) => {
state.clientWidth = clientWidth;
};
// themeConfig el-scrollbar
watch(store.state.themeConfig.themeConfig, (val) => {
if (val.isShowLogoChange !== val.isShowLogo) {
if (!proxy.$refs.layoutAsideScrollbarRef) return false;
proxy.$refs.layoutAsideScrollbarRef.update();
}
});
//
watch(store.state, (val) => {
if (val.routesList.routesList.length === state.menuList.length) return false;
let { layout, isClassicSplitMenu } = val.themeConfig.themeConfig;
if (layout === 'classic' && isClassicSplitMenu) return false;
setFilterRoutes();
});
//
onBeforeMount(() => {
initMenuFixed(document.body.clientWidth);
setFilterRoutes();
proxy.mittBus.on('setSendColumnsChildren', (res: any) => {
state.menuList = res.children;
});
proxy.mittBus.on('setSendClassicChildren', (res: any) => {
let { layout, isClassicSplitMenu } = store.state.themeConfig.themeConfig;
if (layout === 'classic' && isClassicSplitMenu) {
state.menuList = [];
state.menuList = res.children;
}
});
proxy.mittBus.on('getBreadcrumbIndexSetFilterRoutes', () => {
setFilterRoutes();
});
proxy.mittBus.on('layoutMobileResize', (res: any) => {
initMenuFixed(res.clientWidth);
});
});
//
onUnmounted(() => {
proxy.mittBus.off('setSendColumnsChildren');
proxy.mittBus.off('setSendClassicChildren');
proxy.mittBus.off('getBreadcrumbIndexSetFilterRoutes');
proxy.mittBus.off('layoutMobileResize');
});
return {
setCollapseWidth,
setShowLogo,
getThemeConfig,
...toRefs(state),
};
},
};
</script>
</script>

View File

@ -1,211 +1,201 @@
<template>
<div class="layout-columns-aside">
<el-scrollbar>
<ul>
<li v-for="(v,k) in columnsAsideList" :key="k" @click="onColumnsAsideMenuClick(v,k)"
:ref="el => { if (el) columnsAsideOffsetTopRefs[k] = el }" :class="{'layout-columns-active':liIndex === k}"
:title="v.meta.title">
<div class="layout-columns-aside-li-box" v-if="!v.meta.isLink || v.meta.isLink && v.meta.isIframe">
<i :class="v.meta.icon"></i>
<div class="layout-columns-aside-li-box-title font12">
{{v.meta.title && v.meta.title.length >= 4 ? v.meta.title.substr(0,4) : v.meta.title}}
</div>
</div>
<div class="layout-columns-aside-li-box" v-else>
<a :href="v.meta.isLink" target="_blank">
<i :class="v.meta.icon"></i>
<div class="layout-columns-aside-li-box-title font12">
{{v.meta.title && v.meta.title.length >= 4 ? v.meta.title.substr(0,4) : v.meta.title}}
</div>
</a>
</div>
</li>
<div ref="columnsAsideActiveRef" :class="setColumnsAsideStyle"></div>
</ul>
</el-scrollbar>
</div>
<div class="layout-columns-aside">
<el-scrollbar>
<ul>
<li
v-for="(v, k) in columnsAsideList"
:key="k"
@click="onColumnsAsideMenuClick(v, k)"
:ref="
(el) => {
if (el) columnsAsideOffsetTopRefs[k] = el;
}
"
:class="{ 'layout-columns-active': liIndex === k }"
:title="v.meta.title"
>
<div class="layout-columns-aside-li-box" v-if="!v.meta.isLink || (v.meta.isLink && v.meta.isIframe)">
<i :class="v.meta.icon"></i>
<div class="layout-columns-aside-li-box-title font12">
{{ v.meta.title && v.meta.title.length >= 4 ? v.meta.title.substr(0, 4) : v.meta.title }}
</div>
</div>
<div class="layout-columns-aside-li-box" v-else>
<a :href="v.meta.isLink" target="_blank">
<i :class="v.meta.icon"></i>
<div class="layout-columns-aside-li-box-title font12">
{{ v.meta.title && v.meta.title.length >= 4 ? v.meta.title.substr(0, 4) : v.meta.title }}
</div>
</a>
</div>
</li>
<div ref="columnsAsideActiveRef" :class="setColumnsAsideStyle"></div>
</ul>
</el-scrollbar>
</div>
</template>
<script lang="ts">
import {
reactive,
toRefs,
ref,
computed,
onMounted,
nextTick,
getCurrentInstance,
watch,
} from "vue";
import { useRoute, useRouter, onBeforeRouteUpdate } from "vue-router";
import { useStore } from "/@/store/index.ts";
import { reactive, toRefs, ref, computed, onMounted, nextTick, getCurrentInstance, watch } from 'vue';
import { useRoute, useRouter, onBeforeRouteUpdate } from 'vue-router';
import { useStore } from '/@/store/index.ts';
export default {
name: "layoutColumnsAside",
setup() {
const columnsAsideOffsetTopRefs = ref([]);
const columnsAsideActiveRef = ref();
const { proxy } = getCurrentInstance();
const store = useStore();
const route = useRoute();
const router = useRouter();
const state = reactive({
columnsAsideList: [],
liIndex: 0,
difference: 0,
routeSplit: [],
});
//
const setColumnsAsideStyle = computed(() => {
let { columnsAsideStyle } = store.state.themeConfig;
columnsAsideStyle === "columnsRound"
? (state.difference = 3)
: (state.difference = 0);
if (columnsAsideStyle === "columnsRound")
return "layout-columns-round-active";
else if (columnsAsideStyle === "columnsCard")
return "layout-columns-card-active";
});
//
const setColumnsAsideMove = (k: number) => {
state.liIndex = k;
columnsAsideActiveRef.value.style.top = `${
columnsAsideOffsetTopRefs.value[k].offsetTop + state.difference
}px`;
};
//
const onColumnsAsideMenuClick = (v: Object, k: number) => {
setColumnsAsideMove(k);
let { path, redirect } = v;
if (redirect) router.push(redirect);
else router.push(path);
};
//
const onColumnsAsideDown = (k: number) => {
nextTick(() => {
setColumnsAsideMove(k);
});
};
// //
const setFilterRoutes = () => {
state.columnsAsideList = filterRoutesFun(store.state.routes);
const resData = setSendChildren(route.path);
onColumnsAsideDown(resData.item[0].k);
proxy.mittBus.emit("setSendColumnsChildren", resData);
};
//
const setSendChildren = (path: string) => {
const currentPathSplit = path.split("/");
let currentData: object = {};
state.columnsAsideList.map((v, k) => {
if (v.path === `/${currentPathSplit[1]}`) {
v["k"] = k;
currentData["item"] = [{ ...v }];
currentData["children"] = [{ ...v }];
if (v.children) currentData["children"] = v.children;
}
});
return currentData;
};
//
const filterRoutesFun = (arr: Array<object>) => {
return arr
.filter((item) => !item.meta.isHide)
.map((item) => {
item = Object.assign({}, item);
if (item.children) item.children = filterRoutesFun(item.children);
return item;
});
};
// tagsView columnsAsideList
const setColumnsMenuHighlight = (path) => {
state.routeSplit = path.split("/");
state.routeSplit.shift();
const routeFirst = `/${state.routeSplit[0]}`;
const currentSplitRoute = state.columnsAsideList.find(
(v) => v.path === routeFirst
);
//
setTimeout(() => {
onColumnsAsideDown(currentSplitRoute.k);
}, 0);
};
//
watch(store.state, (val) => {
if (val.routes.length === state.columnsAsideList.length) return false;
setFilterRoutes();
});
//
onMounted(() => {
setFilterRoutes();
});
//
onBeforeRouteUpdate((to) => {
setColumnsMenuHighlight(to.path);
proxy.mittBus.emit("setSendColumnsChildren", setSendChildren(to.path));
});
return {
columnsAsideOffsetTopRefs,
columnsAsideActiveRef,
onColumnsAsideDown,
setColumnsAsideStyle,
onColumnsAsideMenuClick,
...toRefs(state),
};
},
name: 'layoutColumnsAside',
setup() {
const columnsAsideOffsetTopRefs: any = ref([]);
const columnsAsideActiveRef = ref();
const { proxy } = getCurrentInstance() as any;
const store = useStore();
const route = useRoute();
const router = useRouter();
const state: any = reactive({
columnsAsideList: [],
liIndex: 0,
difference: 0,
routeSplit: [],
});
//
const setColumnsAsideStyle = computed(() => {
return store.state.themeConfig.themeConfig.columnsAsideStyle;
});
//
const setColumnsAsideMove = (k: number) => {
state.liIndex = k;
columnsAsideActiveRef.value.style.top = `${columnsAsideOffsetTopRefs.value[k].offsetTop + state.difference}px`;
};
//
const onColumnsAsideMenuClick = (v: Object, k: number) => {
setColumnsAsideMove(k);
let { path, redirect } = v as any;
if (redirect) router.push(redirect);
else router.push(path);
};
//
const onColumnsAsideDown = (k: number) => {
nextTick(() => {
setColumnsAsideMove(k);
});
};
// //
const setFilterRoutes = () => {
state.columnsAsideList = filterRoutesFun(store.state.routesList.routesList);
const resData: any = setSendChildren(route.path);
onColumnsAsideDown(resData.item[0].k);
proxy.mittBus.emit('setSendColumnsChildren', resData);
};
//
const setSendChildren = (path: string) => {
const currentPathSplit = path.split('/');
let currentData: any = {};
state.columnsAsideList.map((v: any, k: number) => {
if (v.path === `/${currentPathSplit[1]}`) {
v['k'] = k;
currentData['item'] = [{ ...v }];
currentData['children'] = [{ ...v }];
if (v.children) currentData['children'] = v.children;
}
});
return currentData;
};
//
const filterRoutesFun = (arr: Array<object>) => {
return arr
.filter((item: any) => !item.meta.isHide)
.map((item: any) => {
item = Object.assign({}, item);
if (item.children) item.children = filterRoutesFun(item.children);
return item;
});
};
// tagsView columnsAsideList
const setColumnsMenuHighlight = (path: string) => {
state.routeSplit = path.split('/');
state.routeSplit.shift();
const routeFirst = `/${state.routeSplit[0]}`;
const currentSplitRoute = state.columnsAsideList.find((v: any) => v.path === routeFirst);
//
setTimeout(() => {
onColumnsAsideDown(currentSplitRoute.k);
}, 0);
};
//
watch(store.state, (val) => {
val.themeConfig.themeConfig.columnsAsideStyle === 'columnsRound' ? (state.difference = 3) : (state.difference = 0);
if (val.routesList.routesList.length === state.columnsAsideList.length) return false;
setFilterRoutes();
});
//
onMounted(() => {
setFilterRoutes();
});
//
onBeforeRouteUpdate((to) => {
setColumnsMenuHighlight(to.path);
proxy.mittBus.emit('setSendColumnsChildren', setSendChildren(to.path));
});
return {
columnsAsideOffsetTopRefs,
columnsAsideActiveRef,
onColumnsAsideDown,
setColumnsAsideStyle,
onColumnsAsideMenuClick,
...toRefs(state),
};
},
};
</script>
<style scoped lang="scss">
.layout-columns-aside {
width: 64px;
height: 100%;
background: var(--bg-columnsMenuBar);
ul {
position: relative;
li {
color: var(--bg-columnsMenuBarColor);
width: 100%;
height: 50px;
text-align: center;
display: flex;
cursor: pointer;
position: relative;
z-index: 1;
.layout-columns-aside-li-box {
margin: auto;
.layout-columns-aside-li-box-title {
padding-top: 1px;
}
}
a {
text-decoration: none;
color: var(--bg-columnsMenuBarColor);
}
}
.layout-columns-active {
color: #ffffff;
transition: 0.3s ease-in-out;
}
.layout-columns-round-active {
background: var(--color-primary);
color: #ffffff;
position: absolute;
left: 50%;
top: 2px;
height: 44px;
width: 58px;
transform: translateX(-50%);
z-index: 0;
transition: 0.3s ease-in-out;
border-radius: 5px;
}
.layout-columns-card-active {
@extend .layout-columns-round-active;
top: 0;
height: 50px;
width: 100%;
border-radius: 0;
}
}
width: 64px;
height: 100%;
background: var(--bg-columnsMenuBar);
ul {
position: relative;
li {
color: var(--bg-columnsMenuBarColor);
width: 100%;
height: 50px;
text-align: center;
display: flex;
cursor: pointer;
position: relative;
z-index: 1;
.layout-columns-aside-li-box {
margin: auto;
.layout-columns-aside-li-box-title {
padding-top: 1px;
}
}
a {
text-decoration: none;
color: var(--bg-columnsMenuBarColor);
}
}
.layout-columns-active {
color: #ffffff;
transition: 0.3s ease-in-out;
}
.columns-round {
background: var(--color-primary);
color: #ffffff;
position: absolute;
left: 50%;
top: 2px;
height: 44px;
width: 58px;
transform: translateX(-50%);
z-index: 0;
transition: 0.3s ease-in-out;
border-radius: 5px;
}
.columns-card {
@extend .columns-round;
top: 0;
height: 50px;
width: 100%;
border-radius: 0;
}
}
}
</style>
</style>

View File

@ -1,27 +1,27 @@
<template>
<el-header class="layout-header" :height="setHeaderHeight">
<NavBarsIndex />
</el-header>
<el-header class="layout-header" :height="setHeaderHeight">
<NavBarsIndex />
</el-header>
</template>
<script lang="ts">
import { computed } from "vue";
import { useStore } from "/@/store/index.ts";
import NavBarsIndex from "/@/views/layout/navBars/index.vue";
import { computed } from 'vue';
import { useStore } from '/@/store/index.ts';
import NavBarsIndex from '/@/views/layout/navBars/index.vue';
export default {
name: "layoutHeader",
components: { NavBarsIndex },
setup() {
const store = useStore();
// header
const setHeaderHeight = computed(() => {
let { isTagsview, layout } = store.state.themeConfig;
if (isTagsview && layout !== "classic") return "84px";
else return "50px";
});
return {
setHeaderHeight,
};
},
name: 'layoutHeader',
components: { NavBarsIndex },
setup() {
const store = useStore();
// header
const setHeaderHeight = computed(() => {
let { isTagsview, layout } = store.state.themeConfig.themeConfig;
if (isTagsview && layout !== 'classic') return '84px';
else return '50px';
});
return {
setHeaderHeight,
};
},
};
</script>
</script>

View File

@ -1,85 +1,93 @@
<template>
<el-main class="layout-main">
<el-scrollbar class="layout-scrollbar" ref="layoutScrollbarRef"
v-show="!currentRouteMeta.isLink && !currentRouteMeta.isIframe"
:style="{minHeight: `calc(100vh - ${headerHeight}`}">
<LayoutParentView />
<Footer v-if="getThemeConfig.isFooter" />
</el-scrollbar>
<Link :style="{height: `calc(100vh - ${headerHeight}`}" :meta="currentRouteMeta"
v-if="currentRouteMeta.isLink && !currentRouteMeta.isIframe" />
<Iframes :style="{height: `calc(100vh - ${headerHeight}`}" :meta="currentRouteMeta"
v-if="currentRouteMeta.isLink && currentRouteMeta.isIframe" />
</el-main>
<el-main class="layout-main">
<el-scrollbar
class="layout-scrollbar"
ref="layoutScrollbarRef"
v-show="!currentRouteMeta.isLink && !currentRouteMeta.isIframe"
:style="{ minHeight: `calc(100vh - ${headerHeight}` }"
>
<LayoutParentView />
<Footer v-if="getThemeConfig.isFooter" />
</el-scrollbar>
<Link :style="{ height: `calc(100vh - ${headerHeight}` }" :meta="currentRouteMeta" v-if="currentRouteMeta.isLink && !currentRouteMeta.isIframe" />
<Iframes
:style="{ height: `calc(100vh - ${headerHeight}` }"
:meta="currentRouteMeta"
v-if="currentRouteMeta.isLink && currentRouteMeta.isIframe && isShowLink"
@getCurrentRouteMeta="onGetCurrentRouteMeta"
/>
</el-main>
</template>
<script lang="ts">
import {
computed,
defineComponent,
toRefs,
reactive,
getCurrentInstance,
watch,
onBeforeMount,
} from "vue";
import { useRoute } from "vue-router";
import { useStore } from "/@/store/index.ts";
import LayoutParentView from "/@/views/layout/routerView/parent.vue";
import Footer from "/@/views/layout/footer/index.vue";
import Link from "/@/views/layout/routerView/link.vue";
import Iframes from "/@/views/layout/routerView/iframes.vue";
import { computed, defineComponent, toRefs, reactive, getCurrentInstance, watch, onBeforeMount } from 'vue';
import { useRoute } from 'vue-router';
import { useStore } from '/@/store/index.ts';
import LayoutParentView from '/@/views/layout/routerView/parent.vue';
import Footer from '/@/views/layout/footer/index.vue';
import Link from '/@/views/layout/routerView/link.vue';
import Iframes from '/@/views/layout/routerView/iframes.vue';
export default defineComponent({
name: "layoutMain",
components: { LayoutParentView, Footer, Link, Iframes },
setup() {
const { proxy } = getCurrentInstance();
const store = useStore();
const route = useRoute();
const state = reactive({
headerHeight: "",
currentRouteMeta: {},
});
//
const getThemeConfig = computed(() => {
return store.state.themeConfig;
});
// meta
const initCurrentRouteMeta = (meta: object) => {
state.currentRouteMeta = meta;
};
// main
const initHeaderHeight = () => {
let { isTagsview } = store.state.themeConfig;
if (isTagsview) return (state.headerHeight = `84px`);
else return (state.headerHeight = `50px`);
};
//
onBeforeMount(() => {
initCurrentRouteMeta(route.meta);
initHeaderHeight();
});
// themeConfig el-scrollbar
watch(store.state.themeConfig, (val) => {
state.headerHeight = val.isTagsview ? "84px" : "50px";
if (val.isFixedHeaderChange !== val.isFixedHeader) {
if (!proxy.$refs.layoutScrollbarRef) return false;
proxy.$refs.layoutScrollbarRef.update();
}
});
//
watch(
() => route.path,
() => {
initCurrentRouteMeta(route.meta);
proxy.$refs.layoutScrollbarRef.wrap.scrollTop = 0;
}
);
return {
getThemeConfig,
initCurrentRouteMeta,
...toRefs(state),
};
},
name: 'layoutMain',
components: { LayoutParentView, Footer, Link, Iframes },
setup() {
const { proxy } = getCurrentInstance() as any;
const store = useStore();
const route = useRoute();
const state = reactive({
headerHeight: '',
currentRouteMeta: {},
isShowLink: false,
});
//
const getThemeConfig = computed(() => {
return store.state.themeConfig.themeConfig;
});
//
const onGetCurrentRouteMeta = () => {
initCurrentRouteMeta(route.meta);
};
// meta
const initCurrentRouteMeta = (meta: object) => {
state.isShowLink = false;
state.currentRouteMeta = meta;
setTimeout(() => {
state.isShowLink = true;
}, 100);
};
// main
const initHeaderHeight = () => {
let { isTagsview } = store.state.themeConfig.themeConfig;
if (isTagsview) return (state.headerHeight = `84px`);
else return (state.headerHeight = `50px`);
};
//
onBeforeMount(() => {
initCurrentRouteMeta(route.meta);
initHeaderHeight();
});
// themeConfig el-scrollbar
watch(store.state.themeConfig.themeConfig, (val) => {
state.headerHeight = val.isTagsview ? '84px' : '50px';
if (val.isFixedHeaderChange !== val.isFixedHeader) {
if (!proxy.$refs.layoutScrollbarRef) return false;
proxy.$refs.layoutScrollbarRef.update();
}
});
//
watch(
() => route.path,
() => {
initCurrentRouteMeta(route.meta);
proxy.$refs.layoutScrollbarRef.wrap.scrollTop = 0;
}
);
return {
getThemeConfig,
initCurrentRouteMeta,
onGetCurrentRouteMeta,
...toRefs(state),
};
},
});
</script>

View File

@ -1,44 +1,44 @@
<template>
<div class="layout-footer mt15" v-show="isDelayFooter">
<div class="layout-footer-warp">
<div>vue-next-adminMade by lyt with </div>
<div class="mt5">Copyright &copy 深圳市 xxx 软件科技有限公司</div>
</div>
</div>
<div class="layout-footer mt15" v-show="isDelayFooter">
<div class="layout-footer-warp">
<div>vue-next-adminMade by lyt with </div>
<div class="mt5">Copyright 深圳市 xxx 软件科技有限公司</div>
</div>
</div>
</template>
<script lang="ts">
import { toRefs, reactive } from "vue";
import { onBeforeRouteUpdate } from "vue-router";
import { toRefs, reactive } from 'vue';
import { onBeforeRouteUpdate } from 'vue-router';
export default {
name: "layoutFooter",
setup() {
const state = reactive({
isDelayFooter: true,
});
// footer
onBeforeRouteUpdate((to, from) => {
state.isDelayFooter = false;
setTimeout(() => {
state.isDelayFooter = true;
}, 800);
});
return {
...toRefs(state),
};
},
name: 'layoutFooter',
setup() {
const state = reactive({
isDelayFooter: true,
});
// footer
onBeforeRouteUpdate(() => {
state.isDelayFooter = false;
setTimeout(() => {
state.isDelayFooter = true;
}, 800);
});
return {
...toRefs(state),
};
},
};
</script>
<style scoped lang="scss">
.layout-footer {
width: 100%;
display: flex;
&-warp {
margin: auto;
color: #9e9e9e;
text-align: center;
animation: logoAnimation 0.3s ease-in-out;
}
width: 100%;
display: flex;
&-warp {
margin: auto;
color: #9e9e9e;
text-align: center;
animation: logoAnimation 0.3s ease-in-out;
}
}
</style>
</style>

View File

@ -1,71 +1,57 @@
<template>
<Defaults v-if="getThemeConfig.layout === 'defaults'" />
<Classic v-else-if="getThemeConfig.layout === 'classic'" />
<Transverse v-else-if="getThemeConfig.layout === 'transverse'" />
<Columns v-else-if="getThemeConfig.layout === 'columns'" />
<Defaults v-if="getThemeConfig.layout === 'defaults'" />
<Classic v-else-if="getThemeConfig.layout === 'classic'" />
<Transverse v-else-if="getThemeConfig.layout === 'transverse'" />
<Columns v-else-if="getThemeConfig.layout === 'columns'" />
</template>
<script lang="ts">
import {
computed,
onBeforeMount,
onUnmounted,
getCurrentInstance,
defineAsyncComponent,
} from "vue";
import { useStore } from "/@/store/index.ts";
import { getLocal } from "/@/utils/storage.ts";
import { computed, onBeforeMount, onUnmounted, getCurrentInstance, defineAsyncComponent } from 'vue';
import { useStore } from '/@/store/index.ts';
import { getLocal } from '/@/utils/storage.ts';
export default {
name: "layout",
components: {
Defaults: defineAsyncComponent(
() => import("/@/views/layout/main/defaults.vue")
),
Classic: defineAsyncComponent(
() => import("/@/views/layout/main/classic.vue")
),
Transverse: defineAsyncComponent(
() => import("/@/views/layout/main/transverse.vue")
),
Columns: defineAsyncComponent(
() => import("/@/views/layout/main/columns.vue")
),
},
setup() {
const { proxy } = getCurrentInstance();
const store = useStore();
//
const getThemeConfig = computed(() => {
return store.state.themeConfig;
});
// ()
const onLayoutResize = () => {
const clientWidth = document.body.clientWidth;
if (clientWidth < 1000) {
getThemeConfig.value.isCollapse = false;
proxy.mittBus.emit("layoutMobileResize", {
layout: "defaults",
clientWidth,
});
} else {
proxy.mittBus.emit("layoutMobileResize", {
layout: getLocal("oldLayout") ? getLocal("oldLayout") : "defaults",
clientWidth,
});
}
};
//
onBeforeMount(() => {
onLayoutResize();
window.addEventListener("resize", onLayoutResize);
});
//
onUnmounted(() => {
window.removeEventListener("resize", onLayoutResize);
});
return {
getThemeConfig,
};
},
name: 'layout',
components: {
Defaults: defineAsyncComponent(() => import('/@/views/layout/main/defaults.vue')),
Classic: defineAsyncComponent(() => import('/@/views/layout/main/classic.vue')),
Transverse: defineAsyncComponent(() => import('/@/views/layout/main/transverse.vue')),
Columns: defineAsyncComponent(() => import('/@/views/layout/main/columns.vue')),
},
setup() {
const { proxy } = getCurrentInstance() as any;
const store = useStore();
//
const getThemeConfig = computed(() => {
return store.state.themeConfig.themeConfig;
});
// ()
const onLayoutResize = () => {
const clientWidth = document.body.clientWidth;
if (clientWidth < 1000) {
getThemeConfig.value.isCollapse = false;
proxy.mittBus.emit('layoutMobileResize', {
layout: 'defaults',
clientWidth,
});
} else {
proxy.mittBus.emit('layoutMobileResize', {
layout: getLocal('oldLayout') ? getLocal('oldLayout') : 'defaults',
clientWidth,
});
}
};
//
onBeforeMount(() => {
onLayoutResize();
window.addEventListener('resize', onLayoutResize);
});
//
onUnmounted(() => {
window.removeEventListener('resize', onLayoutResize);
});
return {
getThemeConfig,
};
},
};
</script>
</script>

View File

@ -1,290 +1,292 @@
<template>
<div v-show="isShowLockScreen">
<div class="layout-lock-screen-mask"></div>
<div class="layout-lock-screen-img" :class="{'layout-lock-screen-filter':isShowLoockLogin}"></div>
<div class="layout-lock-screen">
<div class="layout-lock-screen-date" @mousedown="onDown" @mousemove="onMove" @mouseup="onEnd"
@touchstart.stop="onDown" @touchmove.stop="onMove" @touchend.stop="onEnd">
<div class="layout-lock-screen-date-box">
<div class="layout-lock-screen-date-box-time">{{time.hm}}<span
class="layout-lock-screen-date-box-minutes">{{time.s}}</span></div>
<div class="layout-lock-screen-date-box-info">{{time.mdq}}</div>
</div>
</div>
<transition name="el-zoom-in-center">
<div v-show="isShowLoockLogin" class="layout-lock-screen-login">
<div class="layout-lock-screen-login-box">
<div class="layout-lock-screen-login-box-img">
<img
src="https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1813762643,1914315241&fm=26&gp=0.jpg" />
</div>
<div class="layout-lock-screen-login-box-name">Administrator</div>
<div class="layout-lock-screen-login-box-value">
<el-input placeholder="请输入密码" ref="layoutLockScreenInputRef" v-model="lockScreenPassword"
@keyup.enter.native.stop="onLockScreenSubmit()">
<template #append>
<el-button icon="el-icon-right" @click="onLockScreenSubmit"></el-button>
</template>
</el-input>
</div>
</div>
<div class="layout-lock-screen-login-icon">
<i class="el-icon-microphone"></i>
<i class="el-icon-alarm-clock"></i>
<i class="el-icon-switch-button"></i>
</div>
</div>
</transition>
</div>
</div>
<div v-show="isShowLockScreen">
<div class="layout-lock-screen-mask"></div>
<div class="layout-lock-screen-img" :class="{ 'layout-lock-screen-filter': isShowLoockLogin }"></div>
<div class="layout-lock-screen">
<div
class="layout-lock-screen-date"
ref="layoutLockScreenDateRef"
@mousedown="onDown"
@mousemove="onMove"
@mouseup="onEnd"
@touchstart.stop="onDown"
@touchmove.stop="onMove"
@touchend.stop="onEnd"
>
<div class="layout-lock-screen-date-box">
<div class="layout-lock-screen-date-box-time">
{{ time.hm }}<span class="layout-lock-screen-date-box-minutes">{{ time.s }}</span>
</div>
<div class="layout-lock-screen-date-box-info">{{ time.mdq }}</div>
</div>
</div>
<transition name="el-zoom-in-center">
<div v-show="isShowLoockLogin" class="layout-lock-screen-login">
<div class="layout-lock-screen-login-box">
<div class="layout-lock-screen-login-box-img">
<img src="https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1813762643,1914315241&fm=26&gp=0.jpg" />
</div>
<div class="layout-lock-screen-login-box-name">Administrator</div>
<div class="layout-lock-screen-login-box-value">
<el-input
placeholder="请输入密码"
ref="layoutLockScreenInputRef"
v-model="lockScreenPassword"
@keyup.enter.native.stop="onLockScreenSubmit()"
>
<template #append>
<el-button icon="el-icon-right" @click="onLockScreenSubmit"></el-button>
</template>
</el-input>
</div>
</div>
<div class="layout-lock-screen-login-icon">
<i class="el-icon-microphone"></i>
<i class="el-icon-alarm-clock"></i>
<i class="el-icon-switch-button"></i>
</div>
</div>
</transition>
</div>
</div>
</template>
<script lang="ts">
import { nextTick, onMounted, reactive, toRefs, ref, onUnmounted } from "vue";
import { useStore } from "/@/store/index.ts";
import { formatDate } from "/@/utils/formatTime.ts";
import { setLocal } from "/@/utils/storage.ts";
import { nextTick, onMounted, reactive, toRefs, ref, onUnmounted, getCurrentInstance } from 'vue';
import { useStore } from '/@/store/index.ts';
import { formatDate } from '/@/utils/formatTime.ts';
import { setLocal } from '/@/utils/storage.ts';
export default {
name: "layoutLockScreen",
setup() {
const layoutLockScreenInputRef = ref();
const store = useStore();
const state = reactive({
transparency: 1,
downClientY: 0,
moveDifference: 0,
isShowLoockLogin: false,
isFlags: false,
querySelectorEl: null,
time: {
hm: "",
s: "",
mdq: "",
},
setIntervalTime: null,
isShowLockScreen: false,
isShowLockScreenIntervalTime: null,
lockScreenPassword: "",
});
//
const onDown = (down) => {
state.isFlags = true;
state.downClientY = down.touches ? down.touches[0].clientY : down.clientY;
};
//
const onMove = (move) => {
if (state.isFlags) {
const el = state.querySelectorEl;
const opacitys = (state.transparency -= 1 / 200);
if (move.touches) {
state.moveDifference = move.touches[0].clientY - state.downClientY;
} else {
state.moveDifference = move.clientY - state.downClientY;
}
if (state.moveDifference >= 0) return false;
el.setAttribute(
"style",
`top:${state.moveDifference}px;cursor:pointer;opacity:${opacitys};`
);
if (state.moveDifference < -400) {
el.setAttribute(
"style",
`top:${-el.clientHeight}px;cursor:pointer;transition:all 0.3s ease;`
);
state.moveDifference = -el.clientHeight;
setTimeout(() => {
el.remove();
}, 300);
}
if (state.moveDifference === -el.clientHeight) {
state.isShowLoockLogin = true;
layoutLockScreenInputRef.value.focus();
}
}
};
//
const onEnd = () => {
state.isFlags = false;
state.transparency = 1;
if (state.moveDifference >= -400) {
state.querySelectorEl.setAttribute(
"style",
`top:0px;opacity:1;transition:all 0.3s ease;`
);
}
};
//
const initGetElement = () => {
nextTick(() => {
state.querySelectorEl = document.querySelector(
".layout-lock-screen-date"
);
});
};
//
const initTime = () => {
state.time.hm = formatDate(new Date(), "HH:MM");
state.time.s = formatDate(new Date(), "SS");
state.time.mdq = formatDate(new Date(), "mm月dd日WWW");
};
//
const initSetTime = () => {
initTime();
state.setIntervalTime = setInterval(() => {
initTime();
}, 1000);
};
//
const initLockScreen = () => {
if (store.state.themeConfig.isLockScreen) {
state.isShowLockScreenIntervalTime = setInterval(() => {
if (store.state.themeConfig.lockScreenTime <= 0) {
state.isShowLockScreen = true;
setLocalThemeConfig();
return false;
}
store.state.themeConfig.lockScreenTime--;
}, 1000);
} else {
clearInterval(state.isShowLockScreenIntervalTime);
}
};
//
const setLocalThemeConfig = () => {
store.state.themeConfig.isDrawer = false;
setLocal("themeConfig", store.state.themeConfig);
};
//
const onLockScreenSubmit = () => {
store.state.themeConfig.isLockScreen = false;
store.state.themeConfig.lockScreenTime = 30;
setLocalThemeConfig();
};
//
onMounted(() => {
initGetElement();
initSetTime();
initLockScreen();
});
//
onUnmounted(() => {
clearInterval(state.setIntervalTime);
clearInterval(state.isShowLockScreenIntervalTime);
});
return {
layoutLockScreenInputRef,
onDown,
onMove,
onEnd,
onLockScreenSubmit,
...toRefs(state),
};
},
name: 'layoutLockScreen',
setup() {
const { proxy } = getCurrentInstance() as any;
const layoutLockScreenInputRef = ref();
const store = useStore();
const state: any = reactive({
transparency: 1,
downClientY: 0,
moveDifference: 0,
isShowLoockLogin: false,
isFlags: false,
querySelectorEl: '',
time: {
hm: '',
s: '',
mdq: '',
},
setIntervalTime: 0,
isShowLockScreen: false,
isShowLockScreenIntervalTime: 0,
lockScreenPassword: '',
});
//
const onDown = (down: any) => {
state.isFlags = true;
state.downClientY = down.touches ? down.touches[0].clientY : down.clientY;
};
//
const onMove = (move: any) => {
if (state.isFlags) {
const el = state.querySelectorEl;
const opacitys = (state.transparency -= 1 / 200);
if (move.touches) {
state.moveDifference = move.touches[0].clientY - state.downClientY;
} else {
state.moveDifference = move.clientY - state.downClientY;
}
if (state.moveDifference >= 0) return false;
el.setAttribute('style', `top:${state.moveDifference}px;cursor:pointer;opacity:${opacitys};`);
if (state.moveDifference < -400) {
el.setAttribute('style', `top:${-el.clientHeight}px;cursor:pointer;transition:all 0.3s ease;`);
state.moveDifference = -el.clientHeight;
setTimeout(() => {
el.remove();
}, 300);
}
if (state.moveDifference === -el.clientHeight) {
state.isShowLoockLogin = true;
layoutLockScreenInputRef.value.focus();
}
}
};
//
const onEnd = () => {
state.isFlags = false;
state.transparency = 1;
if (state.moveDifference >= -400) {
state.querySelectorEl.setAttribute('style', `top:0px;opacity:1;transition:all 0.3s ease;`);
}
};
//
const initGetElement = () => {
nextTick(() => {
state.querySelectorEl = proxy.$refs.layoutLockScreenDateRef;
});
};
//
const initTime = () => {
state.time.hm = formatDate(new Date(), 'HH:MM');
state.time.s = formatDate(new Date(), 'SS');
state.time.mdq = formatDate(new Date(), 'mm月dd日WWW');
};
//
const initSetTime = () => {
initTime();
state.setIntervalTime = window.setInterval(() => {
initTime();
}, 1000);
};
//
const initLockScreen = () => {
if (store.state.themeConfig.themeConfig.isLockScreen) {
state.isShowLockScreenIntervalTime = window.setInterval(() => {
if (store.state.themeConfig.themeConfig.lockScreenTime <= 0) {
state.isShowLockScreen = true;
setLocalThemeConfig();
return false;
}
store.state.themeConfig.themeConfig.lockScreenTime--;
}, 1000);
} else {
clearInterval(state.isShowLockScreenIntervalTime);
}
};
//
const setLocalThemeConfig = () => {
store.state.themeConfig.themeConfig.isDrawer = false;
setLocal('themeConfig', store.state.themeConfig.themeConfig);
};
//
const onLockScreenSubmit = () => {
store.state.themeConfig.themeConfig.isLockScreen = false;
store.state.themeConfig.themeConfig.lockScreenTime = 30;
setLocalThemeConfig();
};
//
onMounted(() => {
initGetElement();
initSetTime();
initLockScreen();
});
//
onUnmounted(() => {
window.clearInterval(state.setIntervalTime);
window.clearInterval(state.isShowLockScreenIntervalTime);
});
return {
layoutLockScreenInputRef,
onDown,
onMove,
onEnd,
onLockScreenSubmit,
...toRefs(state),
};
},
};
</script>
<style scoped lang="scss">
.layout-lock-screen-fixed {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.layout-lock-screen-filter {
filter: blur(5px);
filter: blur(5px);
}
.layout-lock-screen-mask {
background: rgba(255, 255, 255, 1);
@extend .layout-lock-screen-fixed;
z-index: 9999990;
background: rgba(255, 255, 255, 1);
@extend .layout-lock-screen-fixed;
z-index: 9999990;
}
.layout-lock-screen-img {
@extend .layout-lock-screen-fixed;
background-image: url("https://img6.bdstatic.com/img/image/pcindex/sunjunpchuazhoutu.JPG");
background-size: 100% 100%;
z-index: 9999991;
@extend .layout-lock-screen-fixed;
background-image: url('https://img6.bdstatic.com/img/image/pcindex/sunjunpchuazhoutu.JPG');
background-size: 100% 100%;
z-index: 9999991;
}
.layout-lock-screen {
@extend .layout-lock-screen-fixed;
z-index: 9999992;
&-date {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
color: #ffffff;
z-index: 9999993;
user-select: none;
&-box {
position: absolute;
left: 30px;
bottom: 50px;
&-time {
font-size: 100px;
}
&-info {
font-size: 40px;
}
&-minutes {
font-size: 16px;
}
}
}
&-login {
position: relative;
z-index: 9999994;
width: 100%;
height: 100%;
left: 0;
top: 0;
display: flex;
flex-direction: column;
justify-content: center;
color: #ffffff;
&-box {
text-align: center;
margin: auto;
&-img {
width: 180px;
height: 180px;
margin: auto;
img {
width: 100%;
height: 100%;
border-radius: 100%;
}
}
&-name {
font-size: 26px;
margin: 15px 0 30px;
}
}
&-icon {
position: absolute;
right: 30px;
bottom: 30px;
i {
font-size: 20px;
margin-left: 15px;
cursor: pointer;
opacity: 0.8;
&:hover {
opacity: 1;
}
}
}
}
@extend .layout-lock-screen-fixed;
z-index: 9999992;
&-date {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
color: #ffffff;
z-index: 9999993;
user-select: none;
&-box {
position: absolute;
left: 30px;
bottom: 50px;
&-time {
font-size: 100px;
}
&-info {
font-size: 40px;
}
&-minutes {
font-size: 16px;
}
}
}
&-login {
position: relative;
z-index: 9999994;
width: 100%;
height: 100%;
left: 0;
top: 0;
display: flex;
flex-direction: column;
justify-content: center;
color: #ffffff;
&-box {
text-align: center;
margin: auto;
&-img {
width: 180px;
height: 180px;
margin: auto;
img {
width: 100%;
height: 100%;
border-radius: 100%;
}
}
&-name {
font-size: 26px;
margin: 15px 0 30px;
}
}
&-icon {
position: absolute;
right: 30px;
bottom: 30px;
i {
font-size: 20px;
margin-left: 15px;
cursor: pointer;
opacity: 0.8;
&:hover {
opacity: 1;
}
}
}
}
}
::v-deep(.el-input-group__append) {
background: #ffffff;
padding: 0px 15px;
background: #ffffff;
padding: 0px 15px;
}
::v-deep(.el-input__inner) {
border-right-color: #f6f6f6;
&:hover {
border-color: #f6f6f6;
}
border-right-color: #f6f6f6;
&:hover {
border-color: #f6f6f6;
}
}
</style>
</style>

View File

@ -1,85 +1,81 @@
<template>
<div class="layout-logo" v-if="setShowLogo" @click="onThemeConfigChange">
<img src="https://gitee.com/lyt-top/vue-next-admin-images/raw/master/logo/logo-mini.svg"
class="layout-logo-medium-img" />
<span>{{config.globalTitle}}</span>
</div>
<div class="layout-logo-size" v-else @click="onThemeConfigChange">
<img src="https://gitee.com/lyt-top/vue-next-admin-images/raw/master/logo/logo-mini.svg"
class="layout-logo-size-img" />
</div>
<div class="layout-logo" v-if="setShowLogo" @click="onThemeConfigChange">
<img src="https://gitee.com/lyt-top/vue-next-admin-images/raw/master/logo/logo-mini.svg" class="layout-logo-medium-img" />
<span>{{ getThemeConfig.globalTitle }}</span>
</div>
<div class="layout-logo-size" v-else @click="onThemeConfigChange">
<img src="https://gitee.com/lyt-top/vue-next-admin-images/raw/master/logo/logo-mini.svg" class="layout-logo-size-img" />
</div>
</template>
<script lang="ts">
import { reactive, toRefs, computed, getCurrentInstance } from "vue";
import { useStore } from "/@/store/index.ts";
import config from "/@/utils/themeConfig.ts";
import { computed, getCurrentInstance } from 'vue';
import { useStore } from '/@/store/index.ts';
export default {
name: "layoutLogo",
setup() {
const { proxy } = getCurrentInstance();
const store = useStore();
const state = reactive({
config,
});
// logo classic logo
const setShowLogo = computed(() => {
let { isCollapse, layout } = store.state.themeConfig;
return (
!isCollapse || layout === "classic" || document.body.clientWidth < 1000
);
});
// logo /
const onThemeConfigChange = () => {
if (store.state.themeConfig.layout === "transverse") return false;
proxy.mittBus.emit("onMenuClick");
store.state.themeConfig.isCollapse = !store.state.themeConfig.isCollapse;
};
return {
setShowLogo,
onThemeConfigChange,
...toRefs(state),
};
},
name: 'layoutLogo',
setup() {
const { proxy } = getCurrentInstance() as any;
const store = useStore();
//
const getThemeConfig = computed(() => {
return store.state.themeConfig.themeConfig;
});
// logo classic logo
const setShowLogo = computed(() => {
let { isCollapse, layout } = store.state.themeConfig.themeConfig;
return !isCollapse || layout === 'classic' || document.body.clientWidth < 1000;
});
// logo /
const onThemeConfigChange = () => {
if (store.state.themeConfig.themeConfig.layout === 'transverse') return false;
proxy.mittBus.emit('onMenuClick');
store.state.themeConfig.themeConfig.isCollapse = !store.state.themeConfig.themeConfig.isCollapse;
};
return {
setShowLogo,
getThemeConfig,
onThemeConfigChange,
};
},
};
</script>
<style scoped lang="scss">
.layout-logo {
width: 220px;
height: 50px;
display: flex;
align-items: center;
justify-content: center;
box-shadow: rgb(0 21 41 / 2%) 0px 1px 4px;
color: var(--color-primary);
font-size: 16px;
cursor: pointer;
animation: logoAnimation 0.3s ease-in-out;
&:hover {
span {
color: var(--color-primary-light-2);
}
}
&-medium-img {
width: 20px;
margin-right: 5px;
}
width: 220px;
height: 50px;
display: flex;
align-items: center;
justify-content: center;
box-shadow: rgb(0 21 41 / 2%) 0px 1px 4px;
color: var(--color-primary);
font-size: 16px;
cursor: pointer;
animation: logoAnimation 0.3s ease-in-out;
&:hover {
span {
color: var(--color-primary-light-2);
}
}
&-medium-img {
width: 20px;
margin-right: 5px;
}
}
.layout-logo-size {
width: 100%;
height: 50px;
display: flex;
cursor: pointer;
animation: logoAnimation 0.3s ease-in-out;
&-img {
width: 20px;
margin: auto;
}
&:hover {
img {
animation: logoAnimation 0.3s ease-in-out;
}
}
width: 100%;
height: 50px;
display: flex;
cursor: pointer;
animation: logoAnimation 0.3s ease-in-out;
&-img {
width: 20px;
margin: auto;
}
&:hover {
img {
animation: logoAnimation 0.3s ease-in-out;
}
}
}
</style>
</style>

View File

@ -1,24 +1,24 @@
<template>
<el-container class="layout-container flex-center">
<Header />
<el-container class="layout-mian-height-50">
<Aside />
<div class="flex-center layout-backtop">
<TagsView />
<Main />
</div>
</el-container>
<el-backtop target=".layout-backtop .el-main .el-scrollbar__wrap"></el-backtop>
</el-container>
<el-container class="layout-container flex-center">
<Header />
<el-container class="layout-mian-height-50">
<Aside />
<div class="flex-center layout-backtop">
<TagsView />
<Main />
</div>
</el-container>
<el-backtop target=".layout-backtop .el-main .el-scrollbar__wrap"></el-backtop>
</el-container>
</template>
<script>
import Aside from '/@/views/layout/component/aside.vue';
import Header from '/@/views/layout/component/header.vue';
import Main from '/@/views/layout/component/main.vue';
import TagsView from "/@/views/layout/navBars/tagsView/tagsView.vue";
import TagsView from '/@/views/layout/navBars/tagsView/tagsView.vue';
export default {
name: 'layoutClassic',
components: { Aside, Header, Main, TagsView }
}
</script>
name: 'layoutClassic',
components: { Aside, Header, Main, TagsView },
};
</script>

View File

@ -1,38 +1,38 @@
<template>
<el-container class="layout-container">
<ColumnsAside />
<div class="layout-columns-warp">
<Aside />
<el-container class="flex-center layout-backtop">
<Header v-if="isFixedHeader" />
<el-scrollbar>
<Header v-if="!isFixedHeader" />
<Main />
</el-scrollbar>
</el-container>
</div>
<el-backtop target=".layout-backtop .el-scrollbar__wrap"></el-backtop>
</el-container>
<el-container class="layout-container">
<ColumnsAside />
<div class="layout-columns-warp">
<Aside />
<el-container class="flex-center layout-backtop">
<Header v-if="isFixedHeader" />
<el-scrollbar>
<Header v-if="!isFixedHeader" />
<Main />
</el-scrollbar>
</el-container>
</div>
<el-backtop target=".layout-backtop .el-scrollbar__wrap"></el-backtop>
</el-container>
</template>
<script>
import { computed } from 'vue'
import { useStore } from "/@/store/index.ts";
import { computed } from 'vue';
import { useStore } from '/@/store/index.ts';
import Aside from '/@/views/layout/component/aside.vue';
import Header from '/@/views/layout/component/header.vue';
import Main from '/@/views/layout/component/main.vue';
import ColumnsAside from '/@/views/layout/component/columnsAside.vue';
export default {
name: 'layoutColumns',
components: { Aside, Header, Main, ColumnsAside },
setup() {
const store = useStore();
const isFixedHeader = computed(() => {
return store.state.themeConfig.isFixedHeader;
});
return {
isFixedHeader
}
}
}
</script>
name: 'layoutColumns',
components: { Aside, Header, Main, ColumnsAside },
setup() {
const store = useStore();
const isFixedHeader = computed(() => {
return store.state.themeConfig.themeConfig.isFixedHeader;
});
return {
isFixedHeader,
};
},
};
</script>

View File

@ -1,44 +1,44 @@
<template>
<el-container class="layout-container">
<Aside />
<el-container class="flex-center layout-backtop">
<Header v-if="isFixedHeader" />
<el-scrollbar ref="layoutDefaultsScrollbarRef">
<Header v-if="!isFixedHeader" />
<Main />
</el-scrollbar>
</el-container>
<el-backtop target=".layout-backtop .el-scrollbar__wrap"></el-backtop>
</el-container>
<el-container class="layout-container">
<Aside />
<el-container class="flex-center layout-backtop">
<Header v-if="isFixedHeader" />
<el-scrollbar ref="layoutDefaultsScrollbarRef">
<Header v-if="!isFixedHeader" />
<Main />
</el-scrollbar>
</el-container>
<el-backtop target=".layout-backtop .el-scrollbar__wrap"></el-backtop>
</el-container>
</template>
<script>
import { computed, getCurrentInstance, watch } from 'vue'
import { useRoute } from "vue-router";
import { useStore } from "/@/store/index.ts";
import { computed, getCurrentInstance, watch } from 'vue';
import { useRoute } from 'vue-router';
import { useStore } from '/@/store/index.ts';
import Aside from '/@/views/layout/component/aside.vue';
import Header from '/@/views/layout/component/header.vue';
import Main from '/@/views/layout/component/main.vue';
export default {
name: 'layoutDefaults',
components: { Aside, Header, Main },
setup() {
const { proxy } = getCurrentInstance();
const store = useStore();
const route = useRoute();
const isFixedHeader = computed(() => {
return store.state.themeConfig.isFixedHeader;
});
//
watch(
() => route.path,
() => {
proxy.$refs.layoutDefaultsScrollbarRef.wrap.scrollTop = 0;
}
);
return {
isFixedHeader
}
}
}
</script>
name: 'layoutDefaults',
components: { Aside, Header, Main },
setup() {
const { proxy } = getCurrentInstance();
const store = useStore();
const route = useRoute();
const isFixedHeader = computed(() => {
return store.state.themeConfig.themeConfig.isFixedHeader;
});
//
watch(
() => route.path,
() => {
proxy.$refs.layoutDefaultsScrollbarRef.wrap.scrollTop = 0;
}
);
return {
isFixedHeader,
};
},
};
</script>

View File

@ -1,16 +1,16 @@
<template>
<el-container class="layout-container flex-center layout-backtop">
<Header />
<Main />
<el-backtop target=".layout-backtop .el-main .el-scrollbar__wrap"></el-backtop>
</el-container>
<el-container class="layout-container flex-center layout-backtop">
<Header />
<Main />
<el-backtop target=".layout-backtop .el-main .el-scrollbar__wrap"></el-backtop>
</el-container>
</template>
<script>
import Header from '/@/views/layout/component/header.vue';
import Main from '/@/views/layout/component/main.vue';
export default {
name: 'layoutTransverse',
components: { Header, Main }
}
</script>
name: 'layoutTransverse',
components: { Header, Main },
};
</script>

View File

@ -1,121 +1,122 @@
<template>
<div class="layout-navbars-breadcrumb" v-show="getThemeConfig.isBreadcrumb">
<i class="layout-navbars-breadcrumb-icon" :class="getThemeConfig.isCollapse ? 'el-icon-s-unfold' : 'el-icon-s-fold'"
@click="onThemeConfigChange"></i>
<el-breadcrumb class="layout-navbars-breadcrumb-hide">
<transition-group name="breadcrumb" mode="out-in">
<el-breadcrumb-item v-for="(v,k) in breadcrumbList" :key="v.meta.title">
<span v-if="k === breadcrumbList.length - 1" class="layout-navbars-breadcrumb-span">
<i :class="v.meta.icon" class="layout-navbars-breadcrumb-iconfont"
v-if="getThemeConfig.isBreadcrumbIcon"></i>{{v.meta.title}}
</span>
<a v-else @click.prevent="onBreadcrumbClick(v)">
<i :class="v.meta.icon" class="layout-navbars-breadcrumb-iconfont"
v-if="getThemeConfig.isBreadcrumbIcon"></i>{{v.meta.title}}
</a>
</el-breadcrumb-item>
</transition-group>
</el-breadcrumb>
</div>
<div class="layout-navbars-breadcrumb" v-show="getThemeConfig.isBreadcrumb">
<i
class="layout-navbars-breadcrumb-icon"
:class="getThemeConfig.isCollapse ? 'el-icon-s-unfold' : 'el-icon-s-fold'"
@click="onThemeConfigChange"
></i>
<el-breadcrumb class="layout-navbars-breadcrumb-hide">
<transition-group name="breadcrumb" mode="out-in">
<el-breadcrumb-item v-for="(v, k) in breadcrumbList" :key="v.meta.title">
<span v-if="k === breadcrumbList.length - 1" class="layout-navbars-breadcrumb-span">
<i :class="v.meta.icon" class="layout-navbars-breadcrumb-iconfont" v-if="getThemeConfig.isBreadcrumbIcon"></i>{{ v.meta.title }}
</span>
<a v-else @click.prevent="onBreadcrumbClick(v)">
<i :class="v.meta.icon" class="layout-navbars-breadcrumb-iconfont" v-if="getThemeConfig.isBreadcrumbIcon"></i>{{ v.meta.title }}
</a>
</el-breadcrumb-item>
</transition-group>
</el-breadcrumb>
</div>
</template>
<script lang="ts">
import { toRefs, reactive, computed, getCurrentInstance, onMounted } from "vue";
import { onBeforeRouteUpdate, useRoute, useRouter } from "vue-router";
import { useStore } from "/@/store/index.ts";
import { toRefs, reactive, computed, getCurrentInstance, onMounted } from 'vue';
import { onBeforeRouteUpdate, useRoute, useRouter } from 'vue-router';
import { useStore } from '/@/store/index.ts';
export default {
name: "layoutBreadcrumb",
setup() {
const { proxy } = getCurrentInstance();
const store = useStore();
const route = useRoute();
const router = useRouter();
const state = reactive({
breadcrumbList: [],
routeSplit: [],
routeSplitFirst: "",
routeSplitIndex: 1,
});
//
const getThemeConfig = computed(() => {
return store.state.themeConfig;
});
//
const onBreadcrumbClick = (v: object) => {
const { redirect, path } = v;
if (redirect) router.push(redirect);
else router.push(path);
};
// /
const onThemeConfigChange = () => {
proxy.mittBus.emit("onMenuClick");
store.state.themeConfig.isCollapse = !store.state.themeConfig.isCollapse;
};
//
const getBreadcrumbList = (arr: Array<object>) => {
arr.map((item) => {
state.routeSplit.map((v, k, arrs) => {
if (state.routeSplitFirst === item.path) {
state.routeSplitFirst += `/${arrs[state.routeSplitIndex]}`;
state.breadcrumbList.push(item);
state.routeSplitIndex++;
if (item.children) getBreadcrumbList(item.children);
}
});
});
};
//
const initRouteSplit = (path: string) => {
if (!store.state.themeConfig.isBreadcrumb) return false;
state.breadcrumbList = [store.state.routes[0]];
state.routeSplit = path.split("/");
state.routeSplit.shift();
state.routeSplitFirst = `/${state.routeSplit[0]}`;
state.routeSplitIndex = 1;
getBreadcrumbList(store.state.routes);
};
//
onMounted(() => {
initRouteSplit(route.path);
});
//
onBeforeRouteUpdate((to) => {
initRouteSplit(to.path);
});
return {
onThemeConfigChange,
getThemeConfig,
onBreadcrumbClick,
...toRefs(state),
};
},
name: 'layoutBreadcrumb',
setup() {
const { proxy } = getCurrentInstance() as any;
const store = useStore();
const route = useRoute();
const router = useRouter();
const state: any = reactive({
breadcrumbList: [],
routeSplit: [],
routeSplitFirst: '',
routeSplitIndex: 1,
});
//
const getThemeConfig = computed(() => {
return store.state.themeConfig.themeConfig;
});
//
const onBreadcrumbClick = (v: any) => {
const { redirect, path } = v;
if (redirect) router.push(redirect);
else router.push(path);
};
// /
const onThemeConfigChange = () => {
proxy.mittBus.emit('onMenuClick');
store.state.themeConfig.themeConfig.isCollapse = !store.state.themeConfig.themeConfig.isCollapse;
};
//
const getBreadcrumbList = (arr: Array<object>) => {
arr.map((item: any) => {
state.routeSplit.map((v: any, k: number, arrs: any) => {
if (state.routeSplitFirst === item.path) {
state.routeSplitFirst += `/${arrs[state.routeSplitIndex]}`;
state.breadcrumbList.push(item);
state.routeSplitIndex++;
if (item.children) getBreadcrumbList(item.children);
}
});
});
};
//
const initRouteSplit = (path: string) => {
if (!store.state.themeConfig.themeConfig.isBreadcrumb) return false;
state.breadcrumbList = [store.state.routesList.routesList[0]];
state.routeSplit = path.split('/');
state.routeSplit.shift();
state.routeSplitFirst = `/${state.routeSplit[0]}`;
state.routeSplitIndex = 1;
getBreadcrumbList(store.state.routesList.routesList);
};
//
onMounted(() => {
initRouteSplit(route.path);
});
//
onBeforeRouteUpdate((to) => {
initRouteSplit(to.path);
});
return {
onThemeConfigChange,
getThemeConfig,
onBreadcrumbClick,
...toRefs(state),
};
},
};
</script>
<style scoped lang="scss">
.layout-navbars-breadcrumb {
flex: 1;
height: inherit;
display: flex;
align-items: center;
padding-left: 15px;
.layout-navbars-breadcrumb-icon {
cursor: pointer;
font-size: 18px;
margin-right: 15px;
color: var(--bg-topBarColor);
}
.layout-navbars-breadcrumb-span {
opacity: 0.7;
color: var(--bg-topBarColor);
}
.layout-navbars-breadcrumb-iconfont {
font-size: 14px;
margin-right: 5px;
}
::v-deep(.el-breadcrumb__separator) {
opacity: 0.7;
color: var(--bg-topBarColor);
}
flex: 1;
height: inherit;
display: flex;
align-items: center;
padding-left: 15px;
.layout-navbars-breadcrumb-icon {
cursor: pointer;
font-size: 18px;
margin-right: 15px;
color: var(--bg-topBarColor);
}
.layout-navbars-breadcrumb-span {
opacity: 0.7;
color: var(--bg-topBarColor);
}
.layout-navbars-breadcrumb-iconfont {
font-size: 14px;
margin-right: 5px;
}
::v-deep(.el-breadcrumb__separator) {
opacity: 0.7;
color: var(--bg-topBarColor);
}
}
</style>
</style>

View File

@ -1,135 +1,120 @@
<template>
<div class="layout-navbars-breadcrumb-index">
<Logo v-if="setIsShowLogo" />
<Breadcrumb />
<Horizontal :menuList="menuList" v-if="isLayoutTransverse" />
<User />
</div>
<div class="layout-navbars-breadcrumb-index">
<Logo v-if="setIsShowLogo" />
<Breadcrumb />
<Horizontal :menuList="menuList" v-if="isLayoutTransverse" />
<User />
</div>
</template>
<script lang="ts">
import {
computed,
reactive,
toRefs,
onMounted,
onUnmounted,
getCurrentInstance,
watch,
} from "vue";
import { useRoute } from "vue-router";
import { useStore } from "/@/store/index.ts";
import Breadcrumb from "/@/views/layout/navBars/breadcrumb/breadcrumb.vue";
import User from "/@/views/layout/navBars/breadcrumb/user.vue";
import Logo from "/@/views/layout/logo/index.vue";
import Horizontal from "/@/views/layout/navMenu/horizontal.vue";
import { computed, reactive, toRefs, onMounted, onUnmounted, getCurrentInstance, watch } from 'vue';
import { useRoute } from 'vue-router';
import { useStore } from '/@/store/index.ts';
import Breadcrumb from '/@/views/layout/navBars/breadcrumb/breadcrumb.vue';
import User from '/@/views/layout/navBars/breadcrumb/user.vue';
import Logo from '/@/views/layout/logo/index.vue';
import Horizontal from '/@/views/layout/navMenu/horizontal.vue';
export default {
name: "layoutBreadcrumbIndex",
components: { Breadcrumb, User, Logo, Horizontal },
setup() {
const { proxy } = getCurrentInstance();
const store = useStore();
const route = useRoute();
const state = reactive({
menuList: [],
});
//
const getThemeConfig = computed(() => {
return store.state.themeConfig;
});
// logo /
const setIsShowLogo = computed(() => {
let { isShowLogo, layout } = store.state.themeConfig;
return (
(isShowLogo && layout === "classic") ||
(isShowLogo && layout === "transverse")
);
});
//
const isLayoutTransverse = computed(() => {
let { layout, isClassicSplitMenu } = store.state.themeConfig;
return (
layout === "transverse" || (isClassicSplitMenu && layout === "classic")
);
});
// //
const setFilterRoutes = () => {
let { layout, isClassicSplitMenu } = store.state.themeConfig;
if (layout === "classic" && isClassicSplitMenu) {
state.menuList = delClassicChildren(
filterRoutesFun(store.state.routes)
);
const resData = setSendClassicChildren(route.path);
proxy.mittBus.emit("setSendClassicChildren", resData);
} else {
state.menuList = filterRoutesFun(store.state.routes);
}
};
// children
const delClassicChildren = (arr: Array<object>) => {
arr.map((v) => {
if (v.children) delete v.children;
});
return arr;
};
//
const filterRoutesFun = (arr: Array<object>) => {
return arr
.filter((item) => !item.meta.isHide)
.map((item) => {
item = Object.assign({}, item);
if (item.children) item.children = filterRoutesFun(item.children);
return item;
});
};
//
const setSendClassicChildren = (path: string) => {
const currentPathSplit = path.split("/");
let currentData: object = {};
filterRoutesFun(store.state.routes).map((v, k) => {
if (v.path === `/${currentPathSplit[1]}`) {
v["k"] = k;
currentData["item"] = [{ ...v }];
currentData["children"] = [{ ...v }];
if (v.children) currentData["children"] = v.children;
}
});
return currentData;
};
//
watch(store.state, (val) => {
if (val.routes.length === state.menuList.length) return false;
setFilterRoutes();
});
//
onMounted(() => {
setFilterRoutes();
proxy.mittBus.on("getBreadcrumbIndexSetFilterRoutes", () => {
setFilterRoutes();
});
});
//
onUnmounted(() => {
proxy.mittBus.off("getBreadcrumbIndexSetFilterRoutes");
});
return {
getThemeConfig,
setIsShowLogo,
isLayoutTransverse,
...toRefs(state),
};
},
name: 'layoutBreadcrumbIndex',
components: { Breadcrumb, User, Logo, Horizontal },
setup() {
const { proxy } = getCurrentInstance() as any;
const store = useStore();
const route = useRoute();
const state: any = reactive({
menuList: [],
});
//
const getThemeConfig = computed(() => {
return store.state.themeConfig.themeConfig;
});
// logo /
const setIsShowLogo = computed(() => {
let { isShowLogo, layout } = store.state.themeConfig.themeConfig;
return (isShowLogo && layout === 'classic') || (isShowLogo && layout === 'transverse');
});
//
const isLayoutTransverse = computed(() => {
let { layout, isClassicSplitMenu } = store.state.themeConfig.themeConfig;
return layout === 'transverse' || (isClassicSplitMenu && layout === 'classic');
});
// //
const setFilterRoutes = () => {
let { layout, isClassicSplitMenu } = store.state.themeConfig.themeConfig;
if (layout === 'classic' && isClassicSplitMenu) {
state.menuList = delClassicChildren(filterRoutesFun(store.state.routesList.routesList));
const resData = setSendClassicChildren(route.path);
proxy.mittBus.emit('setSendClassicChildren', resData);
} else {
state.menuList = filterRoutesFun(store.state.routesList.routesList);
}
};
// children
const delClassicChildren = (arr: Array<object>) => {
arr.map((v: any) => {
if (v.children) delete v.children;
});
return arr;
};
//
const filterRoutesFun = (arr: Array<object>) => {
return arr
.filter((item: any) => !item.meta.isHide)
.map((item: any) => {
item = Object.assign({}, item);
if (item.children) item.children = filterRoutesFun(item.children);
return item;
});
};
//
const setSendClassicChildren = (path: string) => {
const currentPathSplit = path.split('/');
let currentData: any = {};
filterRoutesFun(store.state.routesList.routesList).map((v, k) => {
if (v.path === `/${currentPathSplit[1]}`) {
v['k'] = k;
currentData['item'] = [{ ...v }];
currentData['children'] = [{ ...v }];
if (v.children) currentData['children'] = v.children;
}
});
return currentData;
};
//
watch(store.state, (val) => {
if (val.routesList.routesList.length === state.menuList.length) return false;
setFilterRoutes();
});
//
onMounted(() => {
setFilterRoutes();
proxy.mittBus.on('getBreadcrumbIndexSetFilterRoutes', () => {
setFilterRoutes();
});
});
//
onUnmounted(() => {
proxy.mittBus.off('getBreadcrumbIndexSetFilterRoutes');
});
return {
getThemeConfig,
setIsShowLogo,
isLayoutTransverse,
...toRefs(state),
};
},
};
</script>
<style scoped lang="scss">
.layout-navbars-breadcrumb-index {
height: 50px;
display: flex;
align-items: center;
padding-right: 15px;
background: var(--bg-topBar);
overflow: hidden;
border-bottom: 1px solid #f1f2f3;
height: 50px;
display: flex;
align-items: center;
padding-right: 15px;
background: var(--bg-topBar);
overflow: hidden;
border-bottom: 1px solid #f1f2f3;
}
</style>
</style>

View File

@ -1,109 +1,110 @@
<template>
<div class="layout-search-dialog">
<el-dialog v-model="isShowSearch" width="300px" destroy-on-close :modal="false" fullscreen :show-close="false">
<el-autocomplete v-model="menuQuery" :fetch-suggestions="menuSearch" placeholder="菜单搜索:支持中文、路由路径"
prefix-icon="el-icon-search" ref="layoutMenuAutocompleteRef" @select="onHandleSelect" @blur="onSearchBlur">
<template #default="{ item }">
<div><i :class="item.meta.icon" class="mr10"></i>{{ item.meta.title }}</div>
</template>
</el-autocomplete>
</el-dialog>
</div>
<div class="layout-search-dialog">
<el-dialog v-model="isShowSearch" width="300px" destroy-on-close :modal="false" fullscreen :show-close="false">
<el-autocomplete
v-model="menuQuery"
:fetch-suggestions="menuSearch"
placeholder="菜单搜索:支持中文、路由路径"
prefix-icon="el-icon-search"
ref="layoutMenuAutocompleteRef"
@select="onHandleSelect"
@blur="onSearchBlur"
>
<template #default="{ item }">
<div><i :class="item.meta.icon" class="mr10"></i>{{ item.meta.title }}</div>
</template>
</el-autocomplete>
</el-dialog>
</div>
</template>
<script lang="ts">
import { reactive, toRefs, defineComponent, ref, nextTick } from "vue";
import { useRouter } from "vue-router";
import { useStore } from "/@/store/index.ts";
import { reactive, toRefs, defineComponent, ref, nextTick } from 'vue';
import { useRouter } from 'vue-router';
import { useStore } from '/@/store/index.ts';
export default defineComponent({
name: "layoutBreadcrumbSearch",
setup() {
const layoutMenuAutocompleteRef = ref();
const store = useStore();
const router = useRouter();
const state = reactive({
isShowSearch: false,
menuQuery: "",
tagsViewList: [],
});
//
const openSearch = () => {
state.menuQuery = "";
state.isShowSearch = true;
initTageView();
nextTick(() => {
layoutMenuAutocompleteRef.value.focus();
});
};
//
const closeSearch = () => {
state.isShowSearch = false;
};
//
const menuSearch = (queryString, cb) => {
let results = queryString
? state.tagsViewList.filter(createFilter(queryString))
: state.tagsViewList;
cb(results);
};
//
const createFilter = (queryString) => {
return (restaurant) => {
return (
restaurant.path.toLowerCase().indexOf(queryString.toLowerCase()) >
-1 ||
restaurant.meta.title
.toLowerCase()
.indexOf(queryString.toLowerCase()) > -1
);
};
};
//
const initTageView = () => {
if (state.tagsViewList.length > 0) return false;
store.state.tagsViewRoutes.map((v) => {
if (!v.meta.isHide) state.tagsViewList.push({ ...v });
});
};
//
const onHandleSelect = (item) => {
let { path, redirect } = item;
if (item.meta.isLink && !item.meta.isIframe)
window.open(item.meta.isLink);
else if (redirect) router.push(redirect);
else router.push(path);
closeSearch();
};
// input
const onSearchBlur = () => {
closeSearch();
};
return {
layoutMenuAutocompleteRef,
openSearch,
closeSearch,
menuSearch,
onHandleSelect,
onSearchBlur,
...toRefs(state),
};
},
name: 'layoutBreadcrumbSearch',
setup() {
const layoutMenuAutocompleteRef = ref();
const store = useStore();
const router = useRouter();
const state: any = reactive({
isShowSearch: false,
menuQuery: '',
tagsViewList: [],
});
//
const openSearch = () => {
state.menuQuery = '';
state.isShowSearch = true;
initTageView();
nextTick(() => {
layoutMenuAutocompleteRef.value.focus();
});
};
//
const closeSearch = () => {
state.isShowSearch = false;
};
//
const menuSearch = (queryString: any, cb: any) => {
let results = queryString ? state.tagsViewList.filter(createFilter(queryString)) : state.tagsViewList;
cb(results);
};
//
const createFilter = (queryString: any) => {
return (restaurant: any) => {
return (
restaurant.path.toLowerCase().indexOf(queryString.toLowerCase()) > -1 ||
restaurant.meta.title.toLowerCase().indexOf(queryString.toLowerCase()) > -1
);
};
};
//
const initTageView = () => {
if (state.tagsViewList.length > 0) return false;
store.state.tagsViewRoutes.tagsViewRoutes.map((v: any) => {
if (!v.meta.isHide) state.tagsViewList.push({ ...v });
});
};
//
const onHandleSelect = (item: any) => {
let { path, redirect } = item;
if (item.meta.isLink && !item.meta.isIframe) window.open(item.meta.isLink);
else if (redirect) router.push(redirect);
else router.push(path);
closeSearch();
};
// input
const onSearchBlur = () => {
closeSearch();
};
return {
layoutMenuAutocompleteRef,
openSearch,
closeSearch,
menuSearch,
onHandleSelect,
onSearchBlur,
...toRefs(state),
};
},
});
</script>
<style scoped lang="scss">
.layout-search-dialog {
::v-deep(.el-dialog) {
box-shadow: unset !important;
border-radius: 0 !important;
background: rgba(0, 0, 0, 0.5);
}
::v-deep(.el-autocomplete) {
width: 560px;
position: absolute;
top: 100px;
left: 50%;
transform: translateX(-50%);
}
::v-deep(.el-dialog) {
box-shadow: unset !important;
border-radius: 0 !important;
background: rgba(0, 0, 0, 0.5);
}
::v-deep(.el-autocomplete) {
width: 560px;
position: absolute;
top: 100px;
left: 50%;
transform: translateX(-50%);
}
}
</style>
</style>

File diff suppressed because it is too large Load Diff

View File

@ -1,202 +1,190 @@
<template>
<div class="layout-navbars-breadcrumb-user" :style="setFlexAutoStyle">
<div class="layout-navbars-breadcrumb-user-icon" @click="onSearchClick">
<i class="el-icon-search" title="菜单搜索"></i>
</div>
<div class="layout-navbars-breadcrumb-user-icon" @click="onLayoutSetingClick">
<i class="icon-skin iconfont" title="布局配置"></i>
</div>
<div class="layout-navbars-breadcrumb-user-icon">
<el-popover placement="bottom" trigger="click" v-model:visible="isShowUserNewsPopover" :width="300"
popper-class="el-popover-pupop-user-news">
<template #reference>
<el-badge :is-dot="true">
<i class="el-icon-bell" title="消息"></i>
</el-badge>
</template>
<transition name="el-zoom-in-top">
<UserNews v-show="isShowUserNewsPopover" />
</transition>
</el-popover>
</div>
<div class="layout-navbars-breadcrumb-user-icon mr10" @click="onScreenfullClick"><i class="iconfont"
:title="isScreenfull ? '开全屏' : '关全屏'" :class="!isScreenfull?'icon-fullscreen':'icon-tuichuquanping'"></i></div>
<el-dropdown :show-timeout="70" :hide-timeout="50" @command="onHandleCommandClick">
<span class="layout-navbars-breadcrumb-user-link">
<img :src="getUserInfos.photo" class="layout-navbars-breadcrumb-user-link-photo mr5" />
{{getUserInfos.userName === '' ? 'test' : getUserInfos.userName}}
<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="/home">首页</el-dropdown-item>
<el-dropdown-item command="/personal">个人中心</el-dropdown-item>
<el-dropdown-item command="/404">404</el-dropdown-item>
<el-dropdown-item command="/401">401</el-dropdown-item>
<el-dropdown-item divided command="logOut">退出登录</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<Search ref="searchRef" />
</div>
<div class="layout-navbars-breadcrumb-user" :style="{ flex: setFlexAutoStyle }">
<div class="layout-navbars-breadcrumb-user-icon" @click="onSearchClick">
<i class="el-icon-search" title="菜单搜索"></i>
</div>
<div class="layout-navbars-breadcrumb-user-icon" @click="onLayoutSetingClick">
<i class="icon-skin iconfont" title="布局配置"></i>
</div>
<div class="layout-navbars-breadcrumb-user-icon">
<el-popover placement="bottom" trigger="click" v-model:visible="isShowUserNewsPopover" :width="300" popper-class="el-popover-pupop-user-news">
<template #reference>
<el-badge :is-dot="true" @click="isShowUserNewsPopover = !isShowUserNewsPopover">
<i class="el-icon-bell" title="消息"></i>
</el-badge>
</template>
<transition name="el-zoom-in-top">
<UserNews v-show="isShowUserNewsPopover" />
</transition>
</el-popover>
</div>
<div class="layout-navbars-breadcrumb-user-icon mr10" @click="onScreenfullClick">
<i class="iconfont" :title="isScreenfull ? '开全屏' : '关全屏'" :class="!isScreenfull ? 'icon-fullscreen' : 'icon-tuichuquanping'"></i>
</div>
<el-dropdown :show-timeout="70" :hide-timeout="50" @command="onHandleCommandClick">
<span class="layout-navbars-breadcrumb-user-link">
<img :src="getUserInfos.photo" class="layout-navbars-breadcrumb-user-link-photo mr5" />
{{ getUserInfos.userName === '' ? 'test' : getUserInfos.userName }}
<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="/home">首页</el-dropdown-item>
<el-dropdown-item command="/personal">个人中心</el-dropdown-item>
<el-dropdown-item command="/404">404</el-dropdown-item>
<el-dropdown-item command="/401">401</el-dropdown-item>
<el-dropdown-item divided command="logOut">退出登录</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<Search ref="searchRef" />
</div>
</template>
<script lang="ts">
import {
ref,
getCurrentInstance,
computed,
reactive,
toRefs,
toRef,
ref,
} from "vue";
import { useRouter } from "vue-router";
import { ElMessageBox, ElMessage } from "element-plus";
import screenfull from "screenfull";
import { resetRoute } from "/@/router/index.ts";
import { useStore } from "/@/store/index.ts";
import { getSession, clearSession } from "/@/utils/storage.ts";
import UserNews from "/@/views/layout/navBars/breadcrumb/userNews.vue";
import Search from "/@/views/layout/navBars/breadcrumb/search.vue";
import { ref, getCurrentInstance, computed, reactive, toRefs } from 'vue';
import { useRouter } from 'vue-router';
import { ElMessageBox, ElMessage } from 'element-plus';
import screenfull from 'screenfull';
import { resetRoute } from '/@/router/index.ts';
import { useStore } from '/@/store/index.ts';
import { clearSession } from '/@/utils/storage.ts';
import UserNews from '/@/views/layout/navBars/breadcrumb/userNews.vue';
import Search from '/@/views/layout/navBars/breadcrumb/search.vue';
export default {
name: "layoutBreadcrumbUser",
components: { UserNews, Search },
setup() {
const { proxy } = getCurrentInstance();
const router = useRouter();
const store = useStore();
const searchRef = ref();
const state = reactive({
isScreenfull: false,
isShowUserNewsPopover: false,
});
//
const setFlexAutoStyle = computed(() => {
if (
!store.state.themeConfig.isBreadcrumb &&
store.state.themeConfig.layout !== "transverse" &&
!store.state.themeConfig.isClassicSplitMenu
)
return { flex: 1 };
});
// vuex
const getUserInfos = computed(() => {
return store.state.userInfos;
});
//
const onScreenfullClick = () => {
if (!screenfull.isEnabled) {
ElMessage.warning("暂不不支持全屏");
return false;
}
screenfull.toggle();
state.isScreenfull = !state.isScreenfull;
};
// icon
const onLayoutSetingClick = () => {
proxy.mittBus.emit("openSetingsDrawer");
};
//
const onHandleCommandClick = (path) => {
if (path === "logOut") {
ElMessageBox({
closeOnClickModal: false,
closeOnPressEscape: false,
title: "提示",
message: "此操作将退出登录, 是否继续?",
showCancelButton: true,
confirmButtonText: "确定",
cancelButtonText: "取消",
beforeClose: (action, instance, done) => {
if (action === "confirm") {
instance.confirmButtonLoading = true;
instance.confirmButtonText = "退出中";
setTimeout(() => {
done();
setTimeout(() => {
instance.confirmButtonLoading = false;
}, 300);
}, 700);
} else {
done();
}
},
})
.then((action) => {
clearSession(); // /token
resetRoute(); // /
router.push("/login");
setTimeout(() => {
ElMessage.success("安全退出成功!");
}, 300);
})
.catch(() => {});
} else {
router.push(path);
}
};
//
const onSearchClick = () => {
searchRef.value.openSearch();
};
return {
setFlexAutoStyle,
getUserInfos,
onLayoutSetingClick,
onHandleCommandClick,
onScreenfullClick,
onSearchClick,
searchRef,
...toRefs(state),
};
},
name: 'layoutBreadcrumbUser',
components: { UserNews, Search },
setup() {
const { proxy } = getCurrentInstance() as any;
const router = useRouter();
const store = useStore();
const searchRef = ref();
const state = reactive({
isScreenfull: false,
isShowUserNewsPopover: false,
});
//
const setFlexAutoStyle = computed(() => {
let { isBreadcrumb, layout, isClassicSplitMenu } = store.state.themeConfig.themeConfig;
return !isBreadcrumb && layout !== 'transverse' && isClassicSplitMenu ? 1 : '';
});
// vuex
const getUserInfos = computed(() => {
return store.state.userInfos.userInfos;
});
//
const onScreenfullClick = () => {
if (!screenfull.isEnabled) {
ElMessage.warning('暂不不支持全屏');
return false;
}
screenfull.toggle();
state.isScreenfull = !state.isScreenfull;
};
// icon
const onLayoutSetingClick = () => {
proxy.mittBus.emit('openSetingsDrawer');
};
//
const onHandleCommandClick = (path: string) => {
if (path === 'logOut') {
ElMessageBox({
closeOnClickModal: false,
closeOnPressEscape: false,
title: '提示',
message: '此操作将退出登录, 是否继续?',
showCancelButton: true,
confirmButtonText: '确定',
cancelButtonText: '取消',
beforeClose: (action, instance, done) => {
if (action === 'confirm') {
instance.confirmButtonLoading = true;
instance.confirmButtonText = '退出中';
setTimeout(() => {
done();
setTimeout(() => {
instance.confirmButtonLoading = false;
}, 300);
}, 700);
} else {
done();
}
},
})
.then(() => {
clearSession(); // /token
resetRoute(); // /
router.push('/login');
setTimeout(() => {
ElMessage.success('安全退出成功!');
}, 300);
})
.catch(() => {});
} else {
router.push(path);
}
};
//
const onSearchClick = () => {
searchRef.value.openSearch();
};
return {
setFlexAutoStyle,
getUserInfos,
onLayoutSetingClick,
onHandleCommandClick,
onScreenfullClick,
onSearchClick,
searchRef,
...toRefs(state),
};
},
};
</script>
<style scoped lang="scss">
.layout-navbars-breadcrumb-user {
display: flex;
align-items: center;
justify-content: flex-end;
&-link {
height: 100%;
display: flex;
align-items: center;
white-space: nowrap;
&-photo {
width: 25px;
height: 25px;
border-radius: 100%;
}
}
&-icon {
padding: 0 10px;
cursor: pointer;
color: var(--bg-topBarColor);
height: 50px;
line-height: 50px;
display: flex;
align-items: center;
&:hover {
background: rgba(0, 0, 0, 0.04);
i {
display: inline-block;
animation: logoAnimation 0.3s ease-in-out;
}
}
}
::v-deep(.el-dropdown) {
color: var(--bg-topBarColor);
}
::v-deep(.el-badge) {
height: 40px;
line-height: 40px;
display: flex;
align-items: center;
}
::v-deep(.el-badge__content.is-fixed) {
top: 12px;
}
display: flex;
align-items: center;
justify-content: flex-end;
&-link {
height: 100%;
display: flex;
align-items: center;
white-space: nowrap;
&-photo {
width: 25px;
height: 25px;
border-radius: 100%;
}
}
&-icon {
padding: 0 10px;
cursor: pointer;
color: var(--bg-topBarColor);
height: 50px;
line-height: 50px;
display: flex;
align-items: center;
&:hover {
background: rgba(0, 0, 0, 0.04);
i {
display: inline-block;
animation: logoAnimation 0.3s ease-in-out;
}
}
}
::v-deep(.el-dropdown) {
color: var(--bg-topBarColor);
}
::v-deep(.el-badge) {
height: 40px;
line-height: 40px;
display: flex;
align-items: center;
}
::v-deep(.el-badge__content.is-fixed) {
top: 12px;
}
}
</style>
</style>

View File

@ -1,114 +1,114 @@
<template>
<div class="layout-navbars-breadcrumb-user-news">
<div class="head-box">
<div class="head-box-title">通知</div>
<div class="head-box-btn" v-if="newsList.length > 0" @click="onAllReadClick">全部已读</div>
</div>
<div class="content-box">
<template v-if="newsList.length > 0">
<div class="content-box-item" v-for="(v,k) in newsList" :key="k">
<div>{{v.label}}</div>
<div class="content-box-msg">
{{v.value}}</div>
<div class="content-box-time">{{v.time}}</div>
</div>
</template>
<el-empty description="暂无通知" v-else></el-empty>
</div>
<div class="foot-box" @click="onGoToGiteeClick" v-if="newsList.length > 0">前往通知中心</div>
</div>
<div class="layout-navbars-breadcrumb-user-news">
<div class="head-box">
<div class="head-box-title">通知</div>
<div class="head-box-btn" v-if="newsList.length > 0" @click="onAllReadClick">全部已读</div>
</div>
<div class="content-box">
<template v-if="newsList.length > 0">
<div class="content-box-item" v-for="(v, k) in newsList" :key="k">
<div>{{ v.label }}</div>
<div class="content-box-msg">
{{ v.value }}
</div>
<div class="content-box-time">{{ v.time }}</div>
</div>
</template>
<el-empty description="暂无通知" v-else></el-empty>
</div>
<div class="foot-box" @click="onGoToGiteeClick" v-if="newsList.length > 0">前往通知中心</div>
</div>
</template>
<script lang="ts">
import { reactive, toRefs } from "vue";
import { reactive, toRefs } from 'vue';
export default {
name: "layoutBreadcrumbUserNews",
setup() {
const state = reactive({
newsList: [
{
label: "关于版本发布的通知",
value:
"vue-next-admin基于 vue3 + CompositionAPI + typescript + vite + element plus正式发布时间2021年02月28日",
time: "2020-12-08",
},
{
label: "关于学习交流的通知",
value: "QQ群号码 665452019欢迎小伙伴入群学习交流探讨",
time: "2020-12-08",
},
],
});
//
const onAllReadClick = () => {
state.newsList = [];
};
//
const onGoToGiteeClick = () => {
window.open("https://gitee.com/lyt-top/vue-next-admin");
};
return {
onAllReadClick,
onGoToGiteeClick,
...toRefs(state),
};
},
name: 'layoutBreadcrumbUserNews',
setup() {
const state = reactive({
newsList: [
{
label: '关于版本发布的通知',
value: 'vue-next-admin基于 vue3 + CompositionAPI + typescript + vite + element plus正式发布时间2021年02月28日',
time: '2020-12-08',
},
{
label: '关于学习交流的通知',
value: 'QQ群号码 665452019欢迎小伙伴入群学习交流探讨',
time: '2020-12-08',
},
],
});
//
const onAllReadClick = () => {
state.newsList = [];
};
//
const onGoToGiteeClick = () => {
window.open('https://gitee.com/lyt-top/vue-next-admin');
};
return {
onAllReadClick,
onGoToGiteeClick,
...toRefs(state),
};
},
};
</script>
<style scoped lang="scss">
.layout-navbars-breadcrumb-user-news {
.head-box {
display: flex;
border-bottom: 1px solid #ebeef5;
box-sizing: border-box;
color: #333333;
justify-content: space-between;
height: 35px;
align-items: center;
.head-box-btn {
color: var(--color-primary);
font-size: 13px;
cursor: pointer;
opacity: 0.8;
&:hover {
opacity: 1;
}
}
}
.content-box {
font-size: 13px;
.content-box-item {
padding-top: 12px;
&:last-of-type {
padding-bottom: 12px;
}
.content-box-msg {
color: #999999;
margin-top: 5px;
margin-bottom: 5px;
}
.content-box-time {
color: #999999;
}
}
}
.foot-box {
height: 35px;
color: var(--color-primary);
font-size: 13px;
cursor: pointer;
opacity: 0.8;
display: flex;
align-items: center;
justify-content: center;
border-top: 1px solid #ebeef5;
&:hover {
opacity: 1;
}
}
::v-deep(.el-empty__description p) {
font-size: 13px;
}
.head-box {
display: flex;
border-bottom: 1px solid #ebeef5;
box-sizing: border-box;
color: #333333;
justify-content: space-between;
height: 35px;
align-items: center;
.head-box-btn {
color: var(--color-primary);
font-size: 13px;
cursor: pointer;
opacity: 0.8;
&:hover {
opacity: 1;
}
}
}
.content-box {
font-size: 13px;
.content-box-item {
padding-top: 12px;
&:last-of-type {
padding-bottom: 12px;
}
.content-box-msg {
color: #999999;
margin-top: 5px;
margin-bottom: 5px;
}
.content-box-time {
color: #999999;
}
}
}
.foot-box {
height: 35px;
color: var(--color-primary);
font-size: 13px;
cursor: pointer;
opacity: 0.8;
display: flex;
align-items: center;
justify-content: center;
border-top: 1px solid #ebeef5;
&:hover {
opacity: 1;
}
}
::v-deep(.el-empty__description p) {
font-size: 13px;
}
}
</style>
</style>

Some files were not shown because too many files have changed in this diff Show More