24 Commits
Author SHA1 Message Date
xiayuping666 9df1378f8e 访客考勤记录对接完成 2024-06-03 17:17:18 +08:00
xiayuping666 9d82c89c66 多选重试对接完成 2024-05-31 09:43:37 +08:00
xiayuping666 8357146548 一键升学对接完成,设备日志列表对接完成 2024-05-29 17:34:39 +08:00
xiayuping666 18608f734e 后台新增班级校区重新改版 2024-05-27 18:00:58 +08:00
xiayuping666 27e92af29d 人脸设备对接完成 2024-05-13 18:01:58 +08:00
xiayuping666 8efb16a791 封装文件上传分包 2024-05-07 17:17:37 +08:00
xiayuping666 c0efa47d1f 规则对接完成 2024-04-26 18:02:23 +08:00
xiayuping666 b7e02f94d9 Merge branch 'wolfking' of http://gitlab.lzyyj.com/hzd/h5 2024-04-22 17:58:48 +08:00
xiayuping666 71805702a3 更改弹出无法取消 2024-04-22 17:58:37 +08:00
hezhidong 153328dacc 部分修改 2024-04-22 17:57:12 +08:00
xiayuping666 295117a443 角色权限设置完成 2024-04-22 17:15:38 +08:00
xiayuping666 1f0b347af6 角色修改完成 2024-04-22 14:47:26 +08:00
xiayuping666 2d7cbc4d9d 角色管理完成 2024-04-18 17:15:06 +08:00
xiayuping666 480863aa4b 部门新增修改对接 2024-04-15 18:00:39 +08:00
xiayuping666 81b7489d45 添加班级校区新增按钮 2024-04-07 17:54:23 +08:00
xiayuping666 07b3495575 对接班级管理列表 2024-04-03 09:55:45 +08:00
xiayuping666 95638a4b10 登录完成 2024-03-12 16:16:30 +08:00
xiayuping666 7bf3d0df2f 幼儿评价对接完成 2024-03-07 14:57:29 +08:00
xiayuping666 59374abd86 解决添加多个类别后点击单元格,表格出现偏移问题 2024-02-05 10:26:32 +08:00
xiayuping666 4fb4a10815 完成每日食谱 2024-02-04 17:31:34 +08:00
xiayuping666 e1681bb58a 每周食谱对接菜单新增修改 2024-02-02 17:51:49 +08:00
xiayuping666 ad52fa5c78 新增每周食谱 2024-01-31 17:40:36 +08:00
hezhidong 4438dbfe4d 1 2024-01-30 10:55:56 +08:00
hezhidong ff582f261b 初始化 2024-01-30 09:30:56 +08:00
254 changed files with 44821 additions and 4 deletions
+5
View File
@@ -0,0 +1,5 @@
# port 端口号
VUE_APP_PORT = 9999
# open 运行 npm run dev 时自动打开浏览器
VUE_APP_OPEN = false
+29
View File
@@ -0,0 +1,29 @@
# 开发环境
# VUE_APP_BASE_API = ''
# 彭宇pc获取信息
# 胖胖
# VUE_APP_BASE_API = https://campus.lzyyj.com/prod-api
#红星
VUE_APP_BASE_API = https://hxhl.lzyyj.com/prod-api
# VUE_APP_BASE_API = http://192.168.31.101:8088
# 王镇海
# VUE_APP_BASE_API = http://192.168.31.170:9091
# VUE_APP_BASE_API = http://192.168.31.170:8088
# VUE_APP_BASE_API = https://dswj.cpolar.cn
# 袁工
# VUE_APP_BASE_API = http://pandamimi.lzyyj.com/prod-api
# VUE_APP_BASE_API = http://pandamimi.lzyyj.com/prod-api
# VUE_APP_BASE_API = http://localhost:9999
# 肖兴跃
# VUE_APP_BASE_API = http://dswj.cpolar.cn
# 彭宇pc登录获取tk
# 红星
# VUE_APP_BASE_LOGO_API = https://auth.campus.lzyyj.com
# 胖胖
VUE_APP_BASE_LOGO_API = https://auth.hxhl.lzyyj.com
# VUE_APP_BASE_LOGO_API = http://192.168.31.101:9000
# VUE_APP_BASE_LOGO_API = https://73354289vo.zicp.fun
# VUE_APP_BASE_LOGO_API = https://auth.cpolar.cn
+18
View File
@@ -0,0 +1,18 @@
*.sh
node_modules
lib
*.md
*.scss
*.woff
*.ttf
*.json
.vscode
.idea
dist
mock
public
bin
build
config
index.html
src/assets
+22
View File
@@ -0,0 +1,22 @@
module.exports = {
root: true,
env: {
node: true,
},
parserOptions: {
parser: '@babel/eslint-parser',
},
plugins: ['vue'],
extends: ['plugin:vue/essential', 'eslint:recommended'],
rules: {
// http://eslint.cn/docs/rules/
'vue/no-parsing-error': 'off',
'no-unused-vars': 'error',
'no-dupe-args': 'error',
'no-empty': 'off',
'no-extra-semi': 'off',
'no-constant-condition': 'off',
'no-console': 'error',
'vue/multi-word-component-names': 'off',
},
};
+26
View File
@@ -0,0 +1,26 @@
node_modules
.DS_Store
/dist
# local env files
.env.local
.env.*.local
.env.development
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
.env.development
+39
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',
};
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 lyt-Top
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+4 -4
View File
@@ -1,6 +1,6 @@
# 智慧校园H5版-后台管理-平台端 # 智慧校园平台
智慧校园H5版后台管理平台端 智慧校园平台
## Getting started ## Getting started
@@ -15,14 +15,14 @@ Already a pro? Just edit this README.md and make it your own. Want to make it ea
``` ```
cd existing_repo cd existing_repo
git remote add origin http://gitlab.lzyyj.com/hzd/h5.git git remote add origin http://192.168.31.120/SmartSchool/ss-platform-front.git
git branch -M main git branch -M main
git push -uf origin main git push -uf origin main
``` ```
## Integrate with your tools ## Integrate with your tools
- [ ] [Set up project integrations](http://gitlab.lzyyj.com/hzd/h5/-/settings/integrations) - [ ] [Set up project integrations](http://192.168.31.120/SmartSchool/ss-platform-front/-/settings/integrations)
## Collaborate with your team ## Collaborate with your team
+14
View File
@@ -0,0 +1,14 @@
// module.exports = {
// presets: ['@vue/cli-plugin-babel/preset'],
// plugins: ['@babel/plugin-proposal-optional-chaining'],
// };
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
],
plugins: [
// 添加插件配置
process.env.NODE_ENV === 'production' && 'transform-remove-console'
].filter(Boolean)
};
+11
View File
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"allowJs": true,
"lib": ["esnext", "dom", "dom.iterable", "scripthost"],
"jsx": "preserve",
"baseUrl": ".",
"paths": {
"/@/*": ["src/*"]
}
}
}
+81
View File
@@ -0,0 +1,81 @@
{
"name": "smart-campus",
"version": "1.2.2",
"private": true,
"description": "vue2 webpack admin template",
"author": "lyt_20201208",
"license": "MIT",
"scripts": {
"dev": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"webpack": "webpack --version"
},
"dependencies": {
"@riophae/vue-treeselect": "^0.4.0",
"axios": "0.24.0",
"clipboard": "2.0.8",
"core-js": "^3.36.1",
"countup.js": "2.0.8",
"cropperjs": "^1.5.13",
"dingtalk-jsapi": "^3.0.20",
"echarts": "5.2.2",
"element-ui": "2.15.6",
"js-sha3": "^0.9.3",
"jsonwebtoken": "^9.0.2",
"nprogress": "0.2.0",
"screenfull": "5.2.0",
"serve": "^14.2.0",
"sign-canvas": "1.1.4",
"spark-md5": "^3.0.2",
"vue": "^2.6.14",
"vue-cropper": "^0.6.2",
"vue-cropperjs": "^2.2.2",
"vue-i18n": "8.26.7",
"vue-particles": "1.0.9",
"vue-router": "3.5.3",
"vue-seamless-scroll": "1.1.23",
"vuex": "3.6.2"
},
"devDependencies": {
"@babel/eslint-parser": "7.16.5",
"@babel/plugin-proposal-optional-chaining": "7.17.12",
"@vue/cli-plugin-babel": "4.5.15",
"@vue/cli-plugin-eslint": "4.5.15",
"@vue/cli-plugin-router": "4.5.15",
"@vue/cli-plugin-vuex": "4.5.15",
"@vue/cli-service": "4.5.15",
"babel-plugin-transform-remove-console": "^6.9.4",
"eslint": "8.4.1",
"eslint-plugin-vue": "8.2.0",
"sass": "1.45.0",
"sass-loader": "10.1.1",
"terser-webpack-plugin": "^5.3.9",
"vue-template-compiler": "2.6.14"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
],
"bugs": {
"url": "https://www.baidu.com/"
},
"engines": {
"node": ">=12.0.0",
"npm": ">= 6.0.0"
},
"keywords": [
"vue",
"vue3",
"vuejs/vue-next",
"element-ui",
"element-plus",
"vue-next-admin",
"next-admin"
],
"repository": {
"type": "git",
"url": "https://www.baidu.com/"
}
}
+722
View File
@@ -0,0 +1,722 @@
export default {
code: 0,
data: [
{
path: '/home',
name: 'home',
component: 'home',
meta: {
title: 'message.router.home',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: true,
isIframe: false,
roles: ['admin', 'common'],
icon: 'iconfont icon-shouye',
},
},
{
path: '/rolePermissions',
name: 'rolePermissions',
component: 'rolePermissions',
meta: {
title: 'message.router.rolePermissions',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-user',
},
},
{
path: '/MeetingRoomReservation',
name: 'MeetingRoomReservation',
component: 'layout/routerView/parent',
redirect: '/MeetingRoomReservation/CreateMeetingRoom',
meta: {
title: 'message.router.MeetingRoomReservation',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-data-line',
},
children: [
{
path: '/MeetingRoomReservation/CreateMeetingRoom',
name: 'CreateMeetingRoom',
component: 'MeetingRoomReservation/CreateMeetingRoom',
meta: {
title: 'message.router.CreateMeetingRoom',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-data-board',
},
},
{
path: '/MeetingRoomReservation/CreateFunctionRoom',
name: 'CreateFunctionRoom',
component: 'MeetingRoomReservation/CreateFunctionRoom',
meta: {
title: 'message.router.CreateFunctionRoom',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-data-analysis',
},
},
],
},
{
path: '/CampusCalendar',
name: 'CampusCalendar',
component: 'CampusCalendar',
meta: {
title: 'message.router.CampusCalendar',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-notebook-1',
},
},
{
path: '/PrincipalsMailbox',
name: 'PrincipalsMailbox',
component: 'layout/routerView/parent',
redirect: '/PrincipalsMailbox/LetterList',
meta: {
title: 'message.router.PrincipalsMailbox',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-message',
},
children: [
{
path: '/PrincipalsMailbox/LetterList',
name: 'LetterList',
component: 'PrincipalsMailbox/LetterList',
meta: {
title: 'message.router.LetterList',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-files',
},
},
{
path: '/PrincipalsMailbox/ResponsiblePersonManagement',
name: 'ResponsiblePersonManagement',
component: 'PrincipalsMailbox/ResponsiblePersonManagement',
meta: {
title: 'message.router.ResponsiblePersonManagement',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-user',
},
},
],
},
{
path: '/StudentSafetyAttendance',
name: 'StudentSafetyAttendance',
component: 'layout/routerView/parent',
redirect: '/StudentSafetyAttendance/AttendanceForm',
meta: {
title: 'message.router.StudentSafetyAttendance',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-star-off',
},
children: [
{
path: '/StudentSafetyAttendance/AttendanceForm',
name: 'AttendanceForm',
component: 'StudentSafetyAttendance/AttendanceForm',
meta: {
title: 'message.router.AttendanceForm',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-tickets',
},
},
{
path: '/StudentSafetyAttendance/leavedRecord',
name: 'leavedRecord',
component: 'StudentSafetyAttendance/leavedRecord',
meta: {
title: 'message.router.leavedRecord',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-tickets',
},
},
{
path: '/StudentSafetyAttendance/SetAttendanceRules',
name: 'SetAttendanceRules',
component: 'StudentSafetyAttendance/SetAttendanceRules',
meta: {
title: 'message.router.SetAttendanceRules',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-thumb',
},
},
],
},
{
path: '/morningAndAfternoonInspectionManagement',
name: 'morningAndAfternoonInspectionManagement',
component: 'layout/routerView/parent',
redirect: '/morningAndAfternoonInspectionManagement/Inspect',
meta: {
title: 'message.router.morningAndAfternoonInspectionManagement',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-bangzhu',
},
children: [
{
path: '/morningAndAfternoonInspectionManagement/Inspect',
name: 'Inspect',
component: 'morningAndAfternoonInspectionManagement/Inspect',
meta: {
title: 'message.router.Inspect',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-check',
},
},
{
path: '/morningAndAfternoonInspectionManagement/Statistics',
name: 'Statistics',
component: 'morningAndAfternoonInspectionManagement/Statistics',
meta: {
title: 'message.router.Statistics',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-edit-outline',
},
},
],
},
{
path: '/moralEducationManagement',
name: 'moralEducationManagement',
component: 'layout/routerView/parent',
redirect: '/moralEducationManagement/MoralEducationEvaluation',
meta: {
title: 'message.router.moralEducationManagement',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-s-promotion',
},
children: [
{
path: '/moralEducationManagement/ccInformation',
name: 'ccInformation',
component: 'moralEducationManagement/ccInformation',
meta: {
title: 'message.router.ccInformation',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-edit',
},
},
{
path: '/moralEducationManagement/moralEducationEvaluation',
name: 'moralEducationEvaluation',
component: 'moralEducationManagement/moralEducationEvaluation',
meta: {
title: 'message.router.MoralEducationEvaluation',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-check',
},
},
],
},
{
path: '/InterestClass',
name: 'InterestClass',
component: 'layout/routerView/parent',
redirect: '/InterestClass/InterestClassEntry',
meta: {
title: 'message.router.InterestClass',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-basketball',
},
children: [
{
path: '/InterestClass/InterestClassEntry',
name: 'InterestClassEntry',
component: 'InterestClass/InterestClassEntry',
meta: {
title: 'message.router.InterestClassEntry',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-files',
},
},
{
path: '/InterestClass/InterestCourseManagement',
name: 'InterestCourseManagement',
component: 'InterestClass/InterestCourseManagement',
meta: {
title: 'message.router.InterestCourseManagement',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-files',
},
},
{
path: '/InterestClass/abnormalStudentManagement',
name: 'abnormalStudentManagement',
component: 'InterestClass/abnormalStudentManagement',
meta: {
title: 'message.router.abnormalStudentManagement',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-warning-outline',
},
},
],
},
{
path: '/PaymentSystem',
name: 'PaymentSystem',
component: 'layout/routerView/parent',
redirect: '/PaymentSystem/CreatePayment',
meta: {
title: 'message.router.PaymentSystem',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-connection',
},
children: [
{
path: '/PaymentSystem/CreatePayment',
name: 'CreatePayment',
component: 'PaymentSystem/CreatePayment',
meta: {
title: 'message.router.CreatePayment',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-document',
},
},
{
path: '/PaymentSystem/PaymentDetails',
name: 'PaymentDetails',
component: 'PaymentSystem/PaymentDetails',
meta: {
title: 'message.router.PaymentDetails',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-tickets',
},
},
],
},
{
path: '/SmartVisitors',
name: 'SmartVisitors',
component: 'layout/routerView/parent',
redirect: '/SmartVisitors/HomeSchoolAddressBook',
meta: {
title: 'message.router.SmartVisitors',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-s-opportunity',
},
children: [
{
path: '/SmartVisitors/VisitorsRecord',
name: 'VisitorsRecord',
component: 'SmartVisitors/VisitorsRecord',
meta: {
title: 'message.router.VisitorsRecord',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-edit-outline',
},
},
],
},
{
path: '/deviceManagement',
name: 'deviceManagement',
component: 'deviceManagement',
meta: {
title: 'message.router.deviceManagement',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-cpu',
},
},
// {
// path: '/attendanceMachineEquipmentManagement',
// name: 'attendanceMachineEquipmentManagement',
// component: 'attendanceMachineEquipmentManagement',
// meta: {
// title: 'message.router.attendanceMachineEquipmentManagement',
// isLink: '',
// isHide: false,
// isKeepAlive: true,
// isAffix: false,
// isIframe: false,
// roles: ['admin', 'common'],
// icon: 'el-icon-alarm-clock',
// },
// },
{
path: '/attendanceMachineEquipmentManagement',
name: 'attendanceMachineEquipmentManagement',
component: 'layout/routerView/parent',
redirect: '/attendanceMachineEquipmentManagement/attendanceMachineEquipmentManagement',
meta: {
title: 'message.router.attendanceMachineEquipmentManagement',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-brush',
},
children: [
{
path: '/attendanceMachineEquipmentManagement/attendanceMachineEquipmentManagement',
name: 'attendanceMachineEquipmentManagement/attendanceMachineEquipmentManagement',
component: 'attendanceMachineEquipmentManagement/attendanceMachineEquipmentManagement',
meta: {
title: 'message.router.attendanceMachineEquipmentManagement',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-alarm-clock',
},
},
{
path: '/attendanceMachineEquipmentManagement/devicelog',
name: 'attendanceMachineEquipmentManagement/devicelog',
component: 'attendanceMachineEquipmentManagement/devicelog',
meta: {
title: 'message.router.devicelog',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-notebook-2',
},
},
]
},
{
path: '/growthAlbumSection',
name: 'growthAlbumSection',
component: 'layout/routerView/parent',
redirect: '/growthAlbumSection/basicInFormation',
meta: {
title: 'message.router.growthAlbumSection',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-brush',
},
children: [
{
path: '/growthAlbumSection/dataItemConfiguration',
name: 'dataItemConfiguration',
component: 'growthAlbumSection/dataItemConfiguration',
meta: {
title: 'message.router.dataItemConfiguration',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-setting',
},
},
{
path: '/growthAlbumSection/basicInFormation',
name: 'basicInFormation',
component: 'growthAlbumSection/basicInFormation',
meta: {
title: 'message.router.basicInFormation',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-wallet',
},
},
{
path: '/growthAlbumSection/setScoreRules',
name: 'setScoreRules',
component: 'growthAlbumSection/setScoreRules',
meta: {
title: 'message.router.setScoreRules',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-link',
},
},
{
path: '/growthAlbumSection/pictureSetConfiguration',
name: 'pictureSetConfiguration',
component: 'growthAlbumSection/pictureSetConfiguration',
meta: {
title: 'message.router.pictureSetConfiguration',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-picture-outline',
},
},
{
path: '/growthAlbumSection/schoolAlbumManagement',
name: 'schoolAlbumManagement',
component: 'growthAlbumSection/schoolAlbumManagement',
meta: {
title: 'message.router.schoolAlbumManagement',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-wallet',
},
},
],
},
{
path: '/facultyInformation',
name: 'facultyInformation',
component: 'facultyInformation',
meta: {
title: 'message.router.facultyInformation',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-magic-stick',
},
},
{
path: '/recipe',
name: 'recipe',
component: 'recipe',
meta: {
title: 'message.router.recipe',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-s-opportunity',
},
},
{
path: '/evaluate',
name: 'evaluate',
component: 'evaluate',
meta: {
title: 'message.router.evaluate',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-connection',
},
},
{
path: '/classList/classList',
name: 'classList',
component: 'classList/classList',
meta: {
title: 'message.router.classList',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-coordinate',
},
},
{
path: '/department',
name: 'department',
component: 'department',
meta: {
title: 'message.router.department',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-collection',
},
},
{
path: '/regulation',
name: 'regulation',
component: 'regulation',
meta: {
title: 'message.router.regulation',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'el-icon-collection',
},
},
],
};
+290
View File
@@ -0,0 +1,290 @@
{
"code": 0,
"data": [
{
"path": "/home",
"name": "home",
"component": "home",
"meta": {
"title": "message.router.home",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": true,
"isIframe": false,
"roles": ["admin", "common"],
"icon": "iconfont icon-shouye"
}
},
{
"path": "/tools",
"name": "tools",
"component": "tools",
"meta": {
"title": "message.router.tools",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": false,
"isIframe": false,
"roles": ["admin", "common"],
"icon": "iconfont icon-gongju"
}
},
{
"path": "/menu",
"name": "menu",
"component": "layout/routerView/parent",
"redirect": "/menu/menu1",
"meta": {
"title": "message.router.menu",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": false,
"isIframe": false,
"roles": ["admin", "common"],
"icon": "iconfont icon-caidan"
},
"children": [
{
"path": "/menu/menu1",
"name": "menu1",
"component": "layout/routerView/parent",
"redirect": "/menu/menu1/menu11",
"meta": {
"title": "message.router.menu1",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": false,
"isIframe": false,
"roles": ["admin", "common"],
"icon": "iconfont icon-caidan"
},
"children": [
{
"path": "/menu/menu1/menu11",
"name": "menu11",
"component": "menu/menu1/menu11/index",
"meta": {
"title": "message.router.menu11",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": false,
"isIframe": false,
"roles": ["admin", "common"],
"icon": "iconfont icon-caidan"
}
},
{
"path": "/menu/menu1/menu12",
"name": "menu12",
"component": "layout/routerView/parent",
"redirect": "/menu/menu1/menu12/menu121",
"meta": {
"title": "message.router.menu12",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": false,
"isIframe": false,
"roles": ["admin", "common"],
"icon": "iconfont icon-caidan"
},
"children": [
{
"path": "/menu/menu1/menu12/menu121",
"name": "menu121",
"component": "menu/menu1/menu12/menu121/index",
"meta": {
"title": "message.router.menu121",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": false,
"isIframe": false,
"roles": ["admin", "common"],
"icon": "iconfont icon-caidan"
}
},
{
"path": "/menu/menu1/menu12/menu122",
"name": "menu122",
"component": "menu/menu1/menu12/menu122/index",
"meta": {
"title": "message.router.menu122",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": false,
"isIframe": false,
"roles": ["admin", "common"],
"icon": "iconfont icon-caidan"
}
}
]
},
{
"path": "/menu/menu1/menu13",
"name": "menu13",
"component": "menu/menu1/menu13/index",
"meta": {
"title": "message.router.menu13",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": false,
"isIframe": false,
"roles": ["admin", "common"],
"icon": "iconfont icon-caidan"
}
}
]
},
{
"path": "/menu/menu2",
"name": "menu2",
"component": "menu/menu2/index",
"meta": {
"title": "message.router.menu2",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": false,
"isIframe": false,
"roles": ["admin", "common"],
"icon": "iconfont icon-caidan"
}
}
]
},
{
"path": "/fun",
"name": "funIndex",
"component": "layout/routerView/parent",
"redirect": "/fun/tagsView",
"meta": {
"title": "message.router.funIndex",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": false,
"isIframe": false,
"roles": ["admin", "common"],
"icon": "iconfont icon-crew_feature"
},
"children": [
{
"path": "/fun/tagsView",
"name": "funTagsView",
"component": "fun/tagsView/index",
"meta": {
"title": "message.router.funTagsView",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": false,
"isIframe": false,
"roles": ["admin", "common"],
"icon": "el-icon-thumb"
}
},
{
"path": "/fun/signCanvas",
"name": "funSignCanvas",
"component": "fun/signCanvas/index",
"meta": {
"title": "message.router.funSignCanvas",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": false,
"isIframe": false,
"roles": ["admin", "common"],
"icon": "el-icon-edit"
}
}
]
},
{
"path": "/pages",
"name": "pagesIndex",
"component": "layout/routerView/parent",
"redirect": "/pages/formAdapt",
"meta": {
"title": "message.router.pagesIndex",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": false,
"isIframe": false,
"roles": ["admin", "common"],
"icon": "iconfont icon-fuzhiyemian"
},
"children": [
{
"path": "/pages/formAdapt",
"name": "pagesFormAdapt",
"component": "pages/formAdapt/index",
"meta": {
"title": "message.router.pagesFormAdapt",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": false,
"isIframe": false,
"roles": ["admin", "common"],
"icon": "iconfont icon-biaodan"
}
}
]
},
{
"path": "/personal",
"name": "personal",
"component": "personal/index",
"meta": {
"title": "message.router.personal",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": false,
"isIframe": false,
"roles": ["admin", "common"],
"icon": "iconfont icon-gerenzhongxin"
}
},
{
"path": "/link",
"name": "layoutLinkView",
"component": "layout/routerView/parent",
"meta": {
"title": "message.router.layoutLinkView",
"isLink": "https://element-plus.gitee.io/#/zh-CN/component/installation",
"isHide": false,
"isKeepAlive": false,
"isAffix": false,
"isIframe": false,
"roles": ["admin"],
"icon": "iconfont icon-caozuo-wailian"
}
},
{
"path": "/iframes",
"name": "layoutIfameView",
"component": "layout/routerView/parent",
"meta": {
"title": "message.router.layoutIfameView",
"isLink": "https://element-plus.gitee.io/zh-CN/#/zh-CN/component/installation",
"isHide": false,
"isKeepAlive": false,
"isAffix": true,
"isIframe": true,
"roles": ["admin"],
"icon": "iconfont icon-neiqianshujuchucun"
}
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

+31
View File
@@ -0,0 +1,31 @@
<!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-next-adminvue-prev-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 的后台开源管理系统模板!vue-prev-admin,基于 vue2 + element ui,适配手机、平板、pc 的后台开源管理系统模板!"
/>
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<title>数字校园教育管理平台</title>
</head>
<script src="https://g.alicdn.com/dingding/h5-dingtalk-login/0.21.0/ddlogin.js"></script>
<body>
<div id="app"></div>
<script type="text/javascript">
var _hmt = _hmt || [];
(function () {
var hm = document.createElement('script');
hm.src = 'https://hm.baidu.com/hm.js?9d1e524198ede8205ac7c938c243344c';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
</body>
</html>
+229
View File
@@ -0,0 +1,229 @@
{
"code": 0,
"data": [
{
"path": "/home",
"name": "home",
"component": "home",
"meta": {
"title": "message.router.home",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": true,
"isIframe": false,
"roles": ["admin", "common"],
"icon": "iconfont icon-shouye"
}
},
{
"path": "/tools",
"name": "tools",
"component": "tools",
"meta": {
"title": "message.router.tools",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": false,
"isIframe": false,
"roles": ["admin"],
"icon": "iconfont icon-gongju"
}
},
{
"path": "/menu",
"name": "menu",
"component": "layout/routerView/parent",
"redirect": "/menu/menu1",
"meta": {
"title": "message.router.menu",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": false,
"isIframe": false,
"roles": ["admin"],
"icon": "iconfont icon-caidan"
},
"children": [
{
"path": "/menu/menu1",
"name": "menu1",
"component": "layout/routerView/parent",
"redirect": "/menu/menu1/menu11",
"meta": {
"title": "message.router.menu1",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": false,
"isIframe": false,
"roles": ["admin", "common"],
"icon": "iconfont icon-caidan"
},
"children": [
{
"path": "/menu/menu1/menu11",
"name": "menu11",
"component": "menu/menu1/menu11/index",
"meta": {
"title": "message.router.menu11",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": false,
"isIframe": false,
"roles": ["admin", "common"],
"icon": "iconfont icon-caidan"
}
},
{
"path": "/menu/menu1/menu12",
"name": "menu12",
"component": "layout/routerView/parent",
"redirect": "/menu/menu1/menu12/menu121",
"meta": {
"title": "message.router.menu12",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": false,
"isIframe": false,
"roles": ["admin", "common"],
"icon": "iconfont icon-caidan"
},
"children": [
{
"path": "/menu/menu1/menu12/menu121",
"name": "menu121",
"component": "menu/menu1/menu12/menu121/index",
"meta": {
"title": "message.router.menu121",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": false,
"isIframe": false,
"roles": ["admin", "common"],
"icon": "iconfont icon-caidan"
}
},
{
"path": "/menu/menu1/menu12/menu122",
"name": "menu122",
"component": "menu/menu1/menu12/menu122/index",
"meta": {
"title": "message.router.menu122",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": false,
"isIframe": false,
"roles": ["admin", "common"],
"icon": "iconfont icon-caidan"
}
}
]
},
{
"path": "/menu/menu1/menu13",
"name": "menu13",
"component": "menu/menu1/menu13/index",
"meta": {
"title": "message.router.menu13",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": false,
"isIframe": false,
"roles": ["admin", "common"],
"icon": "iconfont icon-caidan"
}
}
]
},
{
"path": "/menu/menu2",
"name": "menu2",
"component": "menu/menu2/index",
"meta": {
"title": "message.router.menu2",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": false,
"isIframe": false,
"roles": ["admin", "common"],
"icon": "iconfont icon-caidan"
}
}
]
},
{
"path": "/fun",
"name": "funIndex",
"component": "layout/routerView/parent",
"redirect": "/fun/tagsView",
"meta": {
"title": "message.router.funIndex",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": false,
"isIframe": false,
"roles": ["admin", "common"],
"icon": "iconfont icon-crew_feature"
},
"children": [
{
"path": "/fun/tagsView",
"name": "funTagsView",
"component": "fun/tagsView/index",
"meta": {
"title": "message.router.funTagsView",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": false,
"isIframe": false,
"roles": ["admin", "common"],
"icon": "el-icon-thumb"
}
}
]
},
{
"path": "/link",
"name": "layoutLinkView",
"component": "layout/routerView/parent",
"meta": {
"title": "message.router.layoutLinkView",
"isLink": "https://element-plus.gitee.io/#/zh-CN/component/installation",
"isHide": false,
"isKeepAlive": false,
"isAffix": false,
"isIframe": false,
"roles": ["admin"],
"icon": "iconfont icon-caozuo-wailian"
}
},
{
"path": "/iframes",
"name": "layoutIfameView",
"component": "layout/routerView/parent",
"meta": {
"title": "message.router.layoutIfameView",
"isLink": "https://gitee.com/lyt-top/vue-next-admin",
"isHide": false,
"isKeepAlive": false,
"isAffix": true,
"isIframe": true,
"roles": ["admin"],
"icon": "iconfont icon-neiqianshujuchucun"
}
}
]
}
+27
View File
@@ -0,0 +1,27 @@
// 后台路由示例表字段说明
const menu = {
// 设置路由路径
"path": "/home",
// 命名路由
"name": "home",
// 设置路由组件
"component": "home",
"meta": {
// 设置菜单名称,使用i18n引入,没有中文切换要求也可以直接填写
"title": "message.router.home",
// 设置外部嵌入外部链接
"isLink": "",
// 设置是否隐藏
"isHide": false,
// 设置是否缓存
"isKeepAlive": true,
// 设置是否一直固定头部不能被删除
"isAffix": true,
// 设置是否开启内嵌
"isIframe": false,
// 角色字段
"roles": ["admin", "common"],
// 设置图标
"icon": "iconfont icon-shouye"
}
}
+85
View File
@@ -0,0 +1,85 @@
<template>
<div id="app">
<router-view />
<Setings ref="setingsRef" />
</div>
</template>
<script>
import setIntroduction from "@/utils/setIconfont.js";
import { Local } from "@/utils/storage.js";
import Setings from "@/layout/navBars/breadcrumb/setings.vue";
import Upgrade from "@/layout/upgrade/index.vue";
import jsonwebtoken from 'jsonwebtoken'
export default {
name: "App",
components: { Setings, Upgrade },
mounted() {
this.initSetIconfont();
this.openSetingsDrawer();
this.getLayoutThemeConfig();
console.log('jsonwebtoken')
const token = 'eyJ4NXQjUzI1NiI6IkRIS0NvOTNWbURZd0tRNk5xX3BEOFdnNDUtRTBzQ2h6c3VKNThjbmVzeDAiLCJraWQiOiJkc3dqIiwiYWxnIjoiUlMyNTYifQ.eyJjYW1wdXNJbmZvIjpbeyJjYW1wdXNJZCI6ODUxNDY2OTMyLCJjYW1wdXNOYW1lIjoi6IOW6IOW5pWZ6IKy6ZuG5ZuiIiwiY2xhc3NJbmZvIjpbeyJjbGFzc0lkIjo4NTEzODI3ODYsImNsYXNzTmFtZSI6IuWkp-ePrTHnj60iLCJjbGFzc1JvbGVMaXN0IjpbeyJyb2xlIjoiZ3VhcmRpYW4iLCJpc0FkdmlzZXIiOjB9LHsicm9sZSI6InRlYWNoZXIiLCJpc0FkdmlzZXIiOjB9XX1dfV0sInN1YiI6IuW8oOS4iSIsImlzcyI6Imh0dHA6Ly9hdXRoLmNwb2xhci5jbiIsInVzZXJpZCI6IjIxMzE1ODQ2MzkzMjMxNjkwMSIsImF1dGhvcml0aWVzIjpbInVzZXIucmVhZCIsInRlc3QiLCJ1c2VyX2luZm8iLCJvcGVuaWQiLCJwcm9maWxlIiwiU0NPUEVfdGVzdCIsIlNDT1BFX3Rlc3QucmVhZCJdLCJhdWQiOiJ0ZXN0LWNsaWVudCIsIm5iZiI6MTcxMDEyOTA5NSwicm9sZUluZm8iOlt7InJvbGVJZCI6Mzc1OTk0NzEzMiwicm9sZU5hbWUiOiLkuLvnrqHnkIblkZgiLCJhdXRob3JpdGllcyI6WyJTQ09QRV90ZXN0IiwiU0NPUEVfdGVzdC5yZWFkIl19LHsicm9sZUlkIjozNzU5OTQ3MTM1LCJyb2xlTmFtZSI6IuS4u-euoSIsImF1dGhvcml0aWVzIjpbXX0seyJyb2xlSWQiOjM3NTk5NDcxMzcsInJvbGVOYW1lIjoi5Zut6ZW_IiwiYXV0aG9yaXRpZXMiOltdfSx7InJvbGVJZCI6Mzc3MjEyODMzNSwicm9sZU5hbWUiOiJ0ZXN0IiwiYXV0aG9yaXRpZXMiOltdfV0sInNjb3BlIjpbInVzZXIucmVhZCIsInRlc3QiLCJ1c2VyX2luZm8iLCJvcGVuaWQiLCJwcm9maWxlIl0sImV4cCI6MTcxMDIxNTQ5NSwiZGVwdEluZm8iOltdLCJpYXQiOjE3MTAxMjkwOTV9.LCMTCclfbhVJVzU1EjdrY7gpR7W7VKzt3-9nwTcZjv2A1bCigmUQjRI6S8dMMF_mIfptiUer5nCk1CBAYm-xQ-Rj86bOf1fqseg6UDTM1_ehiSYR5OSYHcbTMSxvA9RtaA05kT9kReCpUyMeAgdV4-Uj453cTEiGlTrK2TXNthosgIcwgRZooNcMEGGsV-YMkYv69Nmv9e9F8d2lQ26w8MZ-Rke5BUL2fvsvy-XBW8ygvkcarUWfdwml9XDXSLRK1sRCSad1ghvR84EkS8qK_Ii5LoKaxuZ7j4OSJifGeWNuTYveaTTtUy9ZG7cCbD7-kSdOxpgeNS0MjZDc22Xdhg'
console.log(jsonwebtoken.decode(token))
},
methods: {
// 设置初始化,防止刷新时恢复默认
initSetIconfont() {
// 设置批量第三方 icon 图标
setIntroduction.cssCdn();
// 设置批量第三方 js
setIntroduction.jsCdn();
},
// 布局配置弹窗打开
openSetingsDrawer() {
this.bus.$on("openSetingsDrawer", () => {
this.$refs.setingsRef.openDrawer();
});
},
// 获取缓存中的布局配置
getLayoutThemeConfig() {
if (Local.get("themeConfigPrev")) {
this.$store.dispatch("themeConfig/setThemeConfig", Local.get("themeConfigPrev"));
document.documentElement.style.cssText = Local.get("themeConfigStyle");
} else {
Local.set("themeConfigPrev", this.$store.state.themeConfig.themeConfig);
}
},
},
watch: {
// 监听路由的变化
$route: {
handler(to) {
this.$nextTick(() => {
let webTitle = "";
let { globalTitle } = this.$store.state.themeConfig.themeConfig;
to.path === "/login"
? (webTitle = to.meta.title)
: (webTitle = this.$t(to.meta.title));
document.title = `${webTitle} - ${globalTitle}` || globalTitle;
});
},
deep: true,
immediate: true,
},
},
destroyed() {
this.bus.$off("openSetingsDrawer");
},
};
</script>
<style>
textarea {
resize: none;
}
.el-textarea .el-textarea__inner {
resize: none;
}
.box-card {
margin-top: 10px;
}
</style>
+65
View File
@@ -0,0 +1,65 @@
import request from '@/utils/request';
import logoRequest from '@/utils/logoRequest';
/**
* 登录api接口集合
* @method signIn 用户登录
* @method signOut 用户退出登录
*/
// export function useLoginApi() {
// return {
// signIn: (params) => {
// return request({
// url: '/user/signIn',
// method: 'post',
// data: params,
// });
// },
// signOut: (params) => {
// return request({
// url: '/user/signOut',
// method: 'post',
// data: params,
// });
// },
// };
// }
export function useLoginApi() {
return {
signIn: (params) => {
return request({
url: '/auth/login',
method: 'post',
data: params,
});
},
signOut: () => {
return request({
url: '/auth/logout',
method: 'DELETE',
});
},
// 获取验证码
getCode: () => {
return request({
url: '/code',
method: 'get',
});
},
// 获取用户信息
requestToObtainUserInformation: () => {
return request({
url: '/user-dept/user/info',
method: 'get',
});
},
// 登录获取thken
loginToObtain: (authCode) => {
return logoRequest({
url: "/oauth2/token?client_id=test-client&client_secret=123456&login_type=qrcode&grant_type=dingtalk&authCode="+authCode,
method: 'post',
});
},
};
}
+54
View File
@@ -0,0 +1,54 @@
import request from '@/utils/request';
/**
* webpack 的代理只是本地开发生效,打包后需要在部署环境 搭建 nginx 代理
* 所以:
* 开发环境,请求跨越的接口。为了配置跨越示例
* 线上环境,请求目录下的 `json` 数据
* 一般后端接口都会处理跨越问题,可根据具体情况进行修改
* json 格式地址:https://gitee.com/lyt-top/vue-next-admin-images/tree/master/vue2
* 本地菜单地址:public/xxx.json
*/
/**
* 后端控制菜单模拟json,路径在 https://gitee.com/lyt-top/vue-next-admin-images/tree/master/menu
* 后端控制路由,isRequestRoutes 为 true,则开启后端控制路由
* @method getMenuAdmin 获取后端动态路由菜单(admin)
* @method getMenuTest 获取后端动态路由菜单(test)
*/
export function useMenuApi() {
return {
getMenuAdmin: (params) => {
// 本地数据,路径:`/public/xxx.json`
// return request({
// url: './admin.json',
// method: 'get',
// params,
// });
// 模拟跨域
// return request({
// url: '/gitee/lyt-top/vue-next-admin-images/raw/master/vue2/admin.json',
// method: 'get',
// });
// 获取袁永军路由表
return request({
url: '/system/menu/getRouters',
method: 'get',
params,
});
},
getMenuTest: (params) => {
// 本地数据,路径:`/public/xxx.json`
return request({
url: './test.json',
method: 'get',
params,
});
// 模拟跨域
// return request({
// url: '/gitee/lyt-top/vue-next-admin-images/raw/master/vue2/test.json',
// method: 'get',
// });
},
};
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

+6
View File
@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 50" width="64" height="50">
<style>
tspan { white-space:pre }
</style>
<path id="p " fill="#409eff" d="M32.37 1.82L32.37 1.82Q33.13 1.88 33.13 2.05L33.77 1.94Q44.03 1.94 49.24 11.55Q50.12 13.71 50.12 15.94Q50.12 20.75 45.61 24.03Q41.86 26.31 37.93 26.31L37.82 26.31Q34.24 26.31 30.02 25.14Q28.32 30.71 25.86 40.61L26.04 40.84Q25.39 43.36 24.46 48.4Q24.34 48.4 24.05 48.52Q19.13 46.23 19.13 42.84Q20.18 36.45 20.71 34.75Q20.71 31.82 16.31 25.67Q14.73 22.21 14.73 20.1L14.85 19.87Q14.85 19.75 14.73 19.75Q15.67 14.54 16.31 14.54Q17.07 11.96 22.64 6.63Q25.45 4.46 28.85 2.99Q30.67 2.52 32.37 1.82ZM35.77 4.69L35.77 4.69L35.77 4.81Q35.77 7.09 31.72 19.05Q31.72 19.4 30.67 22.56L30.55 23.21L30.55 23.62Q30.9 24.14 34.18 24.14Q38.23 24.14 42.09 21.57Q45.43 19.11 46.37 15.71L46.25 15.41Q46.66 14.54 46.66 14.01L46.66 12.31Q46.66 10.02 43.91 6.74Q40.8 4.69 36.53 4.69L35.77 4.69ZM18.48 16.88L18.48 16.88Q21.88 20.22 24.05 21.27Q24.81 19.52 26.04 15.18L27.45 10.79L28.73 7.27Q29.03 7.27 29.03 6.51L28.85 6.51Q22.64 8.97 18.77 16.12Q18.77 16.18 18.48 16.88ZM18.13 17.41L18.13 17.41Q17.6 19.05 17.31 21.57Q17.31 25.9 21.59 31L23.93 22.33Q23.93 22.04 21.06 20.1Q18.48 17.76 18.48 17.41L18.13 17.41Z" />
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

+179
View File
@@ -0,0 +1,179 @@
import { getProgress, postTask, getPartUrl, getMerge } from "/src/com/uploadApi";
// import createOverallHase from '@/com/createOverallHase'
import SparkMD5 from 'spark-md5'
import axios from "axios";
const DEFAULT_SIZE = 20 * 1024 * 1024
export function cutUpload (file, isFace = false, backUploadProgress){
return new Promise((resolve, reject) => {
const PART_SIZE = 1024 * 1024 * 20; // 20M
// 计算上传进度
const calculateProgress = (progressArr, total) => {
let count = 0;
progressArr.forEach((item) => {
count += item;
});
if (count == total) {
count = Math.floor(total * 0.9999);//如果上传进度为100%,伪造上传进度,为合并文件做准备
}
return count;
};
// 分片上传函数
const requestUploadFun = async (url, fileData, uploadProgress) => {
try {
await axios.put(url, fileData, {
headers: {
"Content-Type": "application/octet-stream",
},
onUploadProgress: function (progressEvent) {
uploadProgress(progressEvent.loaded);
}
});
} catch (error) {
console.error(error);
reject(error);
throw error;
}
};
const uploadChunks = async (file, identifier, progressData, uploadProgressFun) => {
const progressEvent = { total: file.size, loaded: 0 };
const progressArr = [];
const partNumberSet = new Set(progressData.parts.map((item) => item.partNumber));
const partCount = Math.ceil(file.size / PART_SIZE);
let totalSize = 0;
const partArr = [];
for (let i = 0; i < partCount; i++) {
let partNumber = i + 1;
const start = PART_SIZE * (partNumber - 1);
const end = Math.min(start + PART_SIZE, file.size);
if (!partNumberSet.has(partNumber)) {
const blob = file.slice(start, end);
totalSize += blob.size;
progressArr[partNumber] = 0;
partArr.push({ partNumber, blob });
} else {
progressArr[partNumber] = end - start;
progressEvent.loaded = calculateProgress(progressArr, progressEvent.total);
uploadProgressFun(progressEvent);
}
}
const uploadUrlDataArr = await Promise.all(partArr.map(async item => {
const urlData = await getPartUrl(identifier, item.partNumber);
return {
uploadUrl: urlData.uploadUrl,
fileData: item.blob,
partNumber: item.partNumber
}
}));
const uploadPromises = uploadUrlDataArr.map(async (uploadUrlData, i) => {
return requestUploadFun(uploadUrlData.uploadUrl, uploadUrlData.fileData, function (loaded) {
progressArr[uploadUrlData.partNumber] = loaded;
progressEvent.loaded = calculateProgress(progressArr, progressEvent.total);
uploadProgressFun(progressEvent);
});
});
await Promise.all(uploadPromises);
};
// 获取hash
const uploadFile = async (file, onUploadProgress = () => {}, checkFace, onCheckFace = () => {}) => {
if (file) {
const hashStr = await createOverallHase(file);
const fileForm = {
identifier: hashStr,
fileName: file.name,
fileSize: file.size.toString(),
checkFace: checkFace,
};
uploadProgress(file, fileForm, onCheckFace, onUploadProgress)
} else {
console.log("文件为空");
}
};
let obj = {}
uploadFile(file, function(Progress) {
backUploadProgress(Progress)
}, isFace, function(faceData){
// resolve({...obj, ...faceData})
})
// 判断任务 是否存在
const uploadProgress = async (file, fileForm, onCheckFace, onUploadProgressFun) => {
try {
const progressData = await getProgress(fileForm.identifier, fileForm.checkFace);
if (progressData.errMessage === "文件上传任务不存在") {
await postTask(fileForm);
await uploadProgress(file, fileForm, onCheckFace, onUploadProgressFun);
} else {
if (!progressData.finished) {
if (progressData.parts.length == progressData.totalPartNum) {
await getMerge(fileForm.identifier);
} else {
//const chunksArr = await uploadFile(file);
await uploadChunks(file, fileForm.identifier, progressData, onUploadProgressFun);
}
await uploadProgress(file, fileForm, onCheckFace, onUploadProgressFun);
} else {
let checkFaceMsg = progressData.checkFaceMsg
// onUploadProgressFun({ total: Number(file.size), loaded: Number(file.size) });
onUploadProgressFun({ total: Number(file.size), loaded: Number(file.size), path: progressData.path })
if (fileForm.checkFace) {
// onCheckFace({ isFace: progressData.face, checkFaceMsg: progressData.checkFaceMsg });
onCheckFace({ total: Number(file.size), loaded: Number(file.size), isFace: progressData.face, checkFaceMsg, path: progressData.path })
}
// let checkFaceMsg = progressData.checkFaceMsg
resolve({ total: Number(file.size), loaded: Number(file.size), isFace: progressData.face, checkFaceMsg, path: progressData.path });
// console.log(progressData.path);
}
}
} catch (err) {
reject(err);
}
};
})
}
// md5
const createOverallHase = (file, chunkSize = DEFAULT_SIZE) => {
return new Promise((resolve, reject) => {
const startMs = new Date().getTime();
let blobSlice =
File.prototype.slice ||
File.prototype.mozSlice ||
File.prototype.webkitSlice;
let chunks = Math.ceil(file.size / chunkSize);
let currentChunk = 0;
let spark = new SparkMD5.ArrayBuffer(); //追加数组缓冲区。
let fileReader = new FileReader(); //读取文件
fileReader.onload = function (e) {
spark.append(e.target.result);
currentChunk++;
if (currentChunk < chunks) {
loadNext();
} else {
const md5 = spark.end(); //完成md5的计算,返回十六进制结果。
console.log('文件md5计算结束,总耗时:', (new Date().getTime() - startMs) / 1000, 's')
resolve(md5);
}
};
fileReader.onerror = function (e) {
reject(e);
};
function loadNext() {
console.log('当前part number', currentChunk, '总块数:', chunks);
let start = currentChunk * chunkSize;
let end = start + chunkSize;
(end > file.size) && (end = file.size);
fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
}
loadNext();
});
}
+94
View File
@@ -0,0 +1,94 @@
// timeStr表示时间 separator表示分隔符 type == yaer表示只返回年月日
export function formatDate (timeStr = (new Date()), separator = '-', type){
const date = new Date(timeStr)
let yaer = date.getFullYear()
let month = date.getMonth() + 1
let day = date.getDate()
let hour = date.getHours()
let minute = date.getMinutes()
let second = date.getSeconds()
if(type == 'year'){
return yaer + separator + (month >= 10 ? month : ('0' + month)) + separator + (day >= 10 ? day : ('0' + day))
}else {
return yaer + separator + (month >= 10 ? month : ('0' + month)) + separator + (day >= 10 ? day : ('0' + day)) + ' ' + (hour >= 10 ? hour : ('0' + hour)) + ':' + (minute >= 10 ? minute : ('0' + minute)) + ':' + (second >= 10 ? second : ('0' + second))
}
}
/*
重置表单对象
@param { Object } form(必填) 需要重置的表单
@param { Object } rules(选填) 指定需要重置的值默认设为null 试例rules:{ name: 1 } name字段重置为1
@return { Object } 重置后的值
*/
export function resetForm(form, rules = {}) {
for (let key in form) {
if (checkType(form[key]) == "Array") {
if (rules.hasOwnProperty(key)) {
// 是否包含需要更改的
form[key] = rules[key];
} else {
form[key] = [];
}
} else if (checkType(form[key]) == "Object") {
if (rules.hasOwnProperty(key)) {
// 是否包含需要更改的
form[key] = rules[key];
} else {
form[key] = {};
}
} else if (checkType(form[key]) == "Boolean") {
if (rules.hasOwnProperty(key)) {
// 是否包含需要更改的
form[key] = rules[key];
} else {
form[key] = false;
}
} else {
if (rules.hasOwnProperty(key)) {
// 是否包含需要更改的
form[key] = rules[key];
} else {
form[key] = null;
}
}
}
return form;
}
/* 手机号验证
@param { Number } IdcardVal(必填) 手机号
@return { Boolean } true 通过 false 失败
*/
export function rulesPhone(phoneVal) {
let phoneReg = /(^1\d{10}$)|(^[0-9]\d{7}$)/;
if (!phoneReg.test(phoneVal)) {
return false;
} else {
return true;
}
}
/*
根据id递归查询对象
@param { Array } arr(必填) 查询的数组
@param { Number||String } value(必填) 查询的数组
@param { Number||String } unique(选填) 默认值'id' 查询的字段名
@param { Array } children(选填) 默认值'children' 查询递归数组
@return { Object||null } 查询到的值
*/
export function recursion (arr, value, unique = 'id', children = 'children' ) {
let obj = null
arr.forEach(( item, index ) => {
if(item[unique] == value){
obj = item
}else {
if(item[children] && item[children].length != 0){
if(recursion(item[children], value, unique, children)){
obj = recursion(item[children], value, unique, children)
}
}
}
});
return obj
}
+35
View File
@@ -0,0 +1,35 @@
import request from "/src/utils/request";
// 查询分片上传进度
export function getProgress(identifier,checkFace){
return request({
url: `/manager/file/task/${identifier}?checkFace=${checkFace}`,
method: 'GET',
})
}
// 初始化分片上传
export function postTask(data){
return request({
url: '/manager/file/task',
method: 'POST',
data
})
}
// 获取指定分片的上传地址
export function getPartUrl(identifier, partNumber){
return request({
url: `/manager/file/task/part/${identifier}/${partNumber}`,
method: 'GET',
})
}
// 完成上传时调用
export function getMerge(identifier){
return request({
url: `/manager/file/task/merge/${identifier}`,
method: 'GET',
})
}
+47
View File
@@ -0,0 +1,47 @@
<template>
<div>
<el-button @click="newlyClick" type="primary" size="mini" icon="el-icon-plus"
>新增</el-button
>
<el-button @click="resetClick" type="info" size="mini" icon="iconfont icon-biaodan"
>重置</el-button
>
<el-button @click="searchClick" type="warning" size="mini" icon="el-icon-search"
>搜索</el-button
>
<el-input
v-if="false"
v-model="searchData"
size="mini"
style="width: 20%"
placeholder="请输入搜索的关键字"
>
</el-input>
</div>
</template>
<script>
export default {
name: "CommonHead",
data() {
return {
searchData: "",
};
},
methods: {
newlyClick() {
// 在此处调用父组件传入的方法叫父组件做事情
this.$emit("newly-data");
},
resetClick() {
this.$emit("reset-data");
},
searchClick() {
this.$emit("search-data", this.searchData);
},
},
};
</script>
<style lang="scss" scoped></style>
+108
View File
@@ -0,0 +1,108 @@
<template>
<el-table
border
:header-cell-style="{
background: '#f5f7fa',
}"
:data="tableData"
style="width: 100%; margin-top: 20px"
height="650"
size="mini"
>
<el-table-column
v-if="column.label !== 'id'"
align="left"
v-for="(column, index) in tableColumns"
:key="index"
:prop="column.prop"
:label="column.label"
width="auto"
></el-table-column>
<el-table-column align="left" prop="zip" label="操作" width="160">
<template slot-scope="scope">
<el-button
@click="handleEdit(scope.row)"
class="el-icon-edit"
type="text"
size="small"
>编辑</el-button
>
<el-popconfirm @confirm="handleDelete(scope.row)" :title="'确定要删除吗?'">
<el-button
slot="reference"
style="margin-left: 10px; color: red"
class="el-icon-delete"
type="text"
size="small"
>删除</el-button
>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
</template>
<script>
export default {
props: {
columns: {
type: Array,
required: true,
},
data: {
type: Array,
required: true,
},
deleteFunc: {
type: Function,
default: () => {},
},
editFunc: {
type: Function,
default: () => {},
},
},
name: "CommonTables",
data() {
return {};
},
methods: {
// 删除事件
handleDelete(row) {
this.deleteFunc(row);
},
// 编辑事件
handleEdit(row) {
console.log(row);
this.editFunc(row);
},
},
computed: {
tableColumns() {
// 处理传进来的列配置,返回符合 Element UI 表格要求的配置
return this.columns.map((column) => {
return {
label: column.label,
prop: column.prop,
};
});
},
tableData() {
// 处理传进来的数据,返回符合 Element UI 表格要求的数据
return this.data.map((rowData) => {
let row = {};
for (let column of this.columns) {
row[column.prop] = rowData[column.prop];
}
return row;
});
},
},
};
</script>
<style lang="scss" scoped>
.s {
color: red;
}
</style>
+127
View File
@@ -0,0 +1,127 @@
<template>
<el-table
border
:header-cell-style="{
background: '#f5f7fa',
}"
:data="tableData"
style="width: 100%; margin-top: 20px"
height="650"
size="mini"
>
<el-table-column
v-if="column.label !== 'id'"
align="left"
v-for="(column, index) in tableColumns"
:key="index"
:prop="column.prop"
:label="column.label"
width="auto"
>
<template slot-scope="scope">
<span v-if="column.type === 'text'"> {{ scope.row[column.prop] }}</span>
<div v-else-if="column.type === 'signUp'">
<el-tag size="small" v-if="scope.row[column.prop] == 0">已到</el-tag>
<el-tag size="small" type="success" v-else-if="scope.row[column.prop] == 1"
>迟到</el-tag
>
<el-tag size="small" type="danger" v-else-if="scope.row[column.prop] == 2"
>旷课</el-tag
>
<el-tag size="small" type="warning" v-else-if="scope.row[column.prop] == 3"
>请假</el-tag
>
<el-tag size="small" type="warning" v-else-if="scope.row[column.prop] == 4"
>早退</el-tag
>
</div>
<div v-else-if="column.type === 'image'">
<img style="width: 200px; height: 100px" :src="scope.row[column.prop]" />
</div>
</template>
</el-table-column>
<el-table-column align="left" label="操作" width="160">
<template slot-scope="scope">
<el-button
@click="handleEdit(scope.row)"
class="el-icon-edit"
type="text"
size="small"
>编辑</el-button
>
<el-popconfirm @confirm="handleDelete(scope.row)" :title="'确定要删除吗?'">
<el-button
slot="reference"
style="margin-left: 10px; color: red"
class="el-icon-delete"
type="text"
size="small"
>删除</el-button
>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
</template>
<script>
export default {
name: "CommonTablesImg",
props: {
columns: {
type: Array,
required: true,
},
data: {
type: Array,
required: true,
},
deleteFunc: {
type: Function,
default: () => {},
},
editFunc: {
type: Function,
default: () => {},
},
},
data() {
return {};
},
methods: {
// 删除事件
handleDelete(row) {
this.deleteFunc(row);
},
// 编辑事件
handleEdit(row) {
console.log(row);
this.editFunc(row);
},
},
computed: {
tableColumns() {
// 处理传进来的列配置,返回符合 Element UI 表格要求的配置
return this.columns.map((column) => {
return {
label: column.label,
prop: column.prop,
type: column.type,
};
});
},
tableData() {
// 处理传进来的数据,返回符合 Element UI 表格要求的数据
return this.data.map((rowData) => {
let row = {};
for (let column of this.columns) {
row[column.prop] = rowData[column.prop];
}
return row;
});
},
},
};
</script>
<style lang="scss" scoped></style>
+140
View File
@@ -0,0 +1,140 @@
<template>
<el-dialog title="图片剪裁" width="630px" :visible.sync="dialogVisible" append-to-body>
<div class="cropper-content">
<div class="cropper" style="text-align: center">
<!-- 这个组件vueCropper就是我们刚才引入在main.js里面的那个 直接拿来用 就好 -->
<vueCropper
ref="cropper"
:img="option.img"
:output-size="option.size"
:output-type="option.outputType"
:info="true"
:full="option.full"
:can-move="option.canMove"
:can-move-box="option.canMoveBox"
:original="option.original"
:auto-crop="option.autoCrop"
:fixed="option.fixed"
:fixed-number="option.fixedNumber"
:center-box="option.centerBox"
:info-true="option.infoTrue"
:fixed-box="option.fixedBox"
/>
</div>
</div>
<div slot="footer" class="dialog-footer">
<el-button>
<el-upload
class="avatar-uploader"
list-type="picture"
action=""
:auto-upload="false"
:show-file-list="false"
:on-change="changeUpload"
>
<i class="el-icon-refresh" style="margin-right: 5px" />换图片
</el-upload>
</el-button>
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="finish">确认</el-button>
</div>
</el-dialog>
</template>
<script>
import axios from "axios"; //你们有封装接口了的 就直接用你们封装的方法来写 我这里是为了做样式 就直接用了axios请求
// 发送到服务器的请求
import { rqUploadImages } from "../../views/growthAlbumSection/pictureSetConfiguration/api";
export default {
data() {
return {
dialogVisible: false,
// 这都是需要用到的参数看个人需求 用不到的可以删除 可以去官网参考一下
option: {
name: "",
img: "",
info: true,
outputSize: 1,
outputType: "png",
canScale: false,
autoCrop: true,
fixedBox: false,
fixed: false,
fixedNumber: [150, 240],
full: true,
canMoveBox: true,
original: false,
centerBox: false,
infoTrue: true,
},
// 上传线上地址的数据
form: {
files: [],
type: "",
},
};
},
mounted() {},
methods: {
changeUpload(file) {
let testmsg = file.name.substring(file.name.lastIndexOf(".") + 1);
const isJPG = testmsg === "jpg";
const isJPEG = testmsg === "jpeg";
const isPNG = testmsg === "png";
if (!isJPG && !isPNG && !isJPEG) {
this.$message.error("上传图片只能是 JPG/JPEG 或 PNG 格式!");
return;
}
this.$nextTick(() => {
this.option.img = file.url;
this.option.name = file.name;
this.dialogVisible = true;
});
},
// 上传
async Upload() {
let json = "";
let newJson = JSON.stringify(this.form);
json = newJson;
try {
let result = await rqUploadImages(json);
if (result.code == 200) {
this.$message.success("新增成功");
} else {
this.$message.error("服务器错误");
}
} catch (error) {
this.$message.error("网络错误");
}
},
finish() {
this.$refs.cropper.getCropBlob(async (data) => {
let file = new FormData(); //转formData格式 因为我们获取的是blob类型 我后端只支持文件类型所以转了 如果你们后端什么格式都接受 这里就不用走了
var abc = new File([data], this.option.name, { type: "image/jpg" });
file.append("img", abc);
axios
.post(this.$store.state.imgUrl, file, {
// headers: {
// "Content-Type": "application/x-www-form-urlencoded",
// token: "这里是token 后端需要的话就带 不需要这个可以删掉",
// },
headers: this.$store.state.uploadHeader,
})
.then((res) => {
console.log(this.form);
console.log(res.data.data); //后端返回来的图片地址
this.form.files.push(res.data.data);
this.Upload();
this.dialogVisible = false;
});
});
},
},
};
</script>
<style scoped>
.cropper {
width: 100%;
height: 400px;
}
</style>
+58
View File
@@ -0,0 +1,58 @@
<!-- page-size 每页数据 -->
<template>
<div class="pagination-box">
<el-pagination
background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pageNum"
:page-sizes="[10,20,50,100]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
</template>
<script>
export default {
props:{
total: {
required: true,
type: Number
},
pageNum: {
type: Number
},
pageSize: {
type: Number,
default: 10,
}
},
methods: {
handleSizeChange(val) {
this.$emit('clickSize',val)
},
handleCurrentChange(val) {
this.$emit('clickCurrent',val)
}
},
data() {
return {
};
},
created(){
console.log('分液器')
// 阿莎积分拉萨见附件当了
},
mounted(){
console.log('mounted')
}
}
</script>
<style lang="scss" scoped>
.pagination-box{
padding-top: 20px;
}
</style>
+60
View File
@@ -0,0 +1,60 @@
import Vue from 'vue';
import VueI18n from 'vue-i18n';
import zhcnLocale from 'element-ui/lib/locale/lang/zh-CN';
import enLocale from 'element-ui/lib/locale/lang/en';
import zhtwLocale from 'element-ui/lib/locale/lang/zh-TW';
import store from '@/store/index.js';
import nextZhcn from '@/i18n/lang/zh-cn.js';
import nextEn from '@/i18n/lang/en.js';
import nextZhtw from '@/i18n/lang/zh-tw.js';
import pagesHomeZhcn from '@/i18n/pages/home/zh-cn.js';
import pagesHomeEn from '@/i18n/pages/home/en.js';
import pagesHomeZhtw from '@/i18n/pages/home/zh-tw.js';
import pagesLoginZhcn from '@/i18n/pages/login/zh-cn.js';
import pagesLoginEn from '@/i18n/pages/login/en.js';
import pagesLoginZhtw from '@/i18n/pages/login/zh-tw.js';
// 使用插件
Vue.use(VueI18n);
// 定义语言国际化内容
/**
* 说明:
* /src/i18n/lang 下的 js 为框架的国际化内容
* /src/i18n/pages 下的 js 为各界面的国际化内容
*/
const messages = {
'zh-cn': {
...zhcnLocale,
message: {
...nextZhcn,
...pagesHomeZhcn,
...pagesLoginZhcn,
},
},
en: {
...enLocale,
message: {
...nextEn,
...pagesHomeEn,
...pagesLoginEn,
},
},
'zh-tw': {
...zhtwLocale,
message: {
...nextZhtw,
...pagesHomeZhtw,
...pagesLoginZhtw,
},
},
};
// 导出语言国际化
export const i18n = new VueI18n({
locale: store.state.themeConfig.themeConfig.globalI18n,
fallbackLocale: 'zh-cn',
messages,
});
+176
View File
@@ -0,0 +1,176 @@
// 定义内容
export default {
router: {
home: 'home',
system: 'system',
systemMenu: 'systemMenu',
systemUser: 'systemUser',
limits: 'limits',
limitsFrontEnd: 'FrontEnd',
limitsFrontEndPage: 'FrontEndPage',
limitsFrontEndBtn: 'FrontEndBtn',
limitsBackEnd: 'BackEnd',
ParentList:'ParentList',
limitsBackEndEndPage: 'BackEndEndPage',
MeetingRoomReservation:'MeetingRoomReservation',
CreateMeetingRoom:'CreateMeetingRoom',
CreateFunctionRoom:'CreateFunctionRoom',
TeacherTable:'TeacherTable',
CampusCalendar:'CampusCalendar',
StudentTable:'StudentTable',
PrincipalsMailbox:"PrincipalsMailbox",
roleManagement:'roleManagement',
abnormalStudentManagement:'abnormalStudentManagement',
morningAndAfternoonInspectionManagement:'morningAndAfternoonInspectionManagement',
deviceManagement:'deviceManagement',
schoolAlbumManagement:'schoolAlbumManagement',
Statistics:'Statistics',
LetterList:"LetterList",
ccInformation:"ccInformation",
moralEducationManagement:'moralEducationManagement',
personnelManagement:'personnelManagement',
ResponsiblePersonManagement:'ResponsiblePersonManagement',
AttendanceForm:'AttendanceForm',
StudentSafetyAttendance:'StudentSafetyAttendance',
leavedRecord: 'leavedRecord',
SetAttendanceRules:'SetAttendanceRules',
Inspect:'Inspect',
MoralEducationEvaluation:'MoralEducationEvaluation',
InterestClass:'InterestClass',
InterestClassEntry:'InterestClassEntry',
InterestCourseManagement:'InterestCourseManagement',
PaymentSystem:'PaymentSystem',
CreatePayment:'CreatePayment',
PaymentDetails:'PaymentDetails',
SmartVisitors:'SmartVisitors',
HomeSchoolAddressBook:'HomeSchoolAddressBook',
VisitorsRecord:'VisitorsRecord',
basicInFormation:'basicInFormation',
businessDataInformation:"businessDataInformation",
dataItemAnalysis:'dataItemAnalysis',
dataItemConfiguration:'dataItemConfiguration',
pictureSetConfiguration:'pictureSetConfiguration',
growthAlbumSection:'growthAlbumSection',
rolePermissions:"rolePermissions",
setScoreRules:'setScoreRules',
facultyInformation:'facultyInformation',
attendanceMachineEquipmentManagement:'attendanceMachineEquipmentManagement',
devicelog:'devicelog',
recipe: 'recipe',
evaluate: 'evaluate',
classList: 'classList',
department: 'department',
regulation: 'regulation'
},
staticRoutes: {
signIn: 'signIn',
notFound: 'notFound',
noPower: 'noPower',
},
user: {
title0: 'Component size',
title1: 'Language switching',
title2: 'Menu search',
title3: 'Layout configuration',
title4: 'news',
title5: 'Full screen on',
title6: 'Full screen off',
dropdownDefault: 'default',
dropdownMedium: 'medium',
dropdownSmall: 'small',
dropdownMini: 'mini',
dropdown1: 'home page',
dropdown2: 'Personal Center',
dropdown3: '404',
dropdown4: '401',
dropdown5: 'Log out',
dropdown6: 'Code warehouse',
searchPlaceholder: 'Menu search: support Chinese, routing path',
newTitle: 'notice',
newBtn: 'All read',
newGo: 'Go to the notification center',
newDesc: 'No notice',
logOutTitle: 'Tips',
logOutMessage: 'This operation will log out. Do you want to continue?',
logOutConfirm: 'determine',
logOutCancel: 'cancel',
logOutExit: 'Exiting',
logOutSuccess: 'Exit successfully!',
},
tagsView: {
refresh: 'refresh',
close: 'close',
closeOther: 'closeOther',
closeAll: 'closeAll',
fullscreen: 'fullscreen',
},
notFound: {
foundTitle: 'Wrong address input, please re-enter the address~',
foundMsg: 'You can check the web address first, and then re-enter or give us feedback.',
foundBtn: 'Back to home page',
},
noAccess: {
accessTitle: 'You are not authorized to operate~',
accessMsg: 'Contact information: add QQ group discussion 665452019',
accessBtn: 'Reauthorization',
},
layout: {
configTitle: 'Layout configuration',
oneTitle: 'Global Themes',
twoTitle: 'Menu / top bar',
twoTopBar: 'Top bar background',
twoMenuBar: 'Menu background',
twoColumnsMenuBar: 'Column menu background',
twoTopBarColor: 'Top bar default font color',
twoMenuBarColor: 'Menu default font color',
twoColumnsMenuBarColor: 'Default font color bar menu',
twoIsTopBarColorGradual: 'Top bar gradient',
twoIsMenuBarColorGradual: 'Menu gradient',
twoIsMenuBarColorHighlight: 'Menu font highlight',
threeTitle: 'Interface settings',
threeIsCollapse: 'Menu horizontal collapse',
threeIsUniqueOpened: 'Menu accordion',
threeIsFixedHeader: 'Fixed header',
threeIsClassicSplitMenu: 'Classic layout split menu',
threeIsLockScreen: 'Open the lock screen',
threeLockScreenTime: 'screen locking(s/s)',
fourTitle: 'Interface display',
fourIsShowLogo: 'Sidebar logo',
fourIsBreadcrumb: 'Open breadcrumb',
fourIsBreadcrumbIcon: 'Open breadcrumb icon',
fourIsTagsview: 'Open tagsview',
fourIsTagsviewIcon: 'Open tagsview Icon',
fourIsCacheTagsView: 'Enable tagsview cache',
fourIsSortableTagsView: 'Enable tagsview drag',
fourIsFooter: 'Open footer',
fourIsGrayscale: 'Grey model',
fourIsInvert: 'Color weak mode',
fourIsDark: 'Dark Mode',
fourIsWartermark: 'Turn on watermark',
fourWartermarkText: 'Watermark copy',
fiveTitle: 'Other settings',
fiveTagsStyle: 'Tagsview style',
fiveAnimation: 'page animation',
fiveColumnsAsideStyle: 'Column style',
fiveColumnsAsideLayout: 'Column layout',
sixTitle: 'Layout switch',
sixDefaults: 'One',
sixClassic: 'Two',
sixTransverse: 'Three',
sixColumns: 'Four',
tipText: 'Click the button below to copy the layout configuration to `/src/store/modules/themeConfig.js` It has been modified in.',
copyText: 'replication configuration',
resetText: 'restore default',
copyTextSuccess: 'Copy succeeded!',
copyTextError: 'Copy failed!',
},
upgrade: {
title: 'New version',
msg: 'The new version is available, please update it now! Dont worry, the update is fast!',
desc: 'Prompt: Update will restore the default configuration',
btnOne: 'Cruel refusal',
btnTwo: 'Update now',
btnTwoLoading: 'Updating',
},
};
+177
View File
@@ -0,0 +1,177 @@
// 定义内容
export default {
router: {
home: '首页',
system: '系统设置',
systemMenu: '菜单管理',
systemUser: '用户管理',
limits: '权限管理',
limitsFrontEnd: '前端控制',
limitsFrontEndPage: '页面权限',
limitsFrontEndBtn: '按钮权限',
limitsBackEnd: '后端控制',
personnelManagement:'人员管理',
limitsBackEndEndPage: '页面权限',
MeetingRoomReservation:'会议室与功能室',
CreateMeetingRoom:'创建会议室',
CreateFunctionRoom:'创建功能室',
CampusCalendar:'校园行事历',
ParentList:'家长列表',
StudentTable:'学生列表',
PrincipalsMailbox:"校长信箱",
LetterList:'信件列表',
TeacherTable:'教师列表',
abnormalStudentManagement:'异常学生管理',
morningAndAfternoonInspectionManagement:"晨午检管理",
deviceManagement:'人脸设备管理',
ResponsiblePersonManagement:'负责人管理',
moralEducationManagement:'德育管理',
Statistics:'统计',
ccInformation:'配置',
AttendanceForm:'考勤表单',
StudentSafetyAttendance:'学生安全考勤',
leavedRecord: '请假记录',
SetAttendanceRules:'设置考勤规则',
Inspect:'晨午检查',
roleManagement:'角色分配',
MoralEducationEvaluation:'德育评价',
InterestClass:'兴趣班',
InterestClassEntry:'兴趣班录入',
InterestCourseManagement:'兴趣课程管理',
PaymentSystem:'缴费系统',
CreatePayment:'创建缴费',
PaymentDetails:'缴费明细',
SmartVisitors:'智能访客',
HomeSchoolAddressBook:'家校通信录',
VisitorsRecord:'访客记录',
basicInFormation:'信息管理',
businessDataInformation:'业务数据管理',
dataItemAnalysis:'数据项分析',
dataItemConfiguration:'数据项配置',
pictureSetConfiguration:'图片集配置',
growthAlbumSection:'成长画册',
rolePermissions:'角色权限',
setScoreRules:'设置规则',
schoolAlbumManagement:'学校画册管理',
facultyInformation:'教职工信息',
attendanceMachineEquipmentManagement:'考勤机设备管理',
devicelog: '设备日志',
recipe: '每周食谱',
evaluate: '幼儿评价表',
classList: '班级管理',
department: '部门管理',
regulation: '规则管理'
},
staticRoutes: {
signIn: '登录',
notFound: '找不到此页面',
noPower: '没有权限',
},
user: {
title0: '组件大小',
title1: '语言切换',
title2: '菜单搜索',
title3: '布局配置',
title4: '消息',
title5: '开全屏',
title6: '关全屏',
dropdownDefault: '默认',
dropdownMedium: '中等',
dropdownSmall: '小型',
dropdownMini: '超小',
dropdown1: '首页',
dropdown2: '个人中心',
dropdown3: '404',
dropdown4: '401',
dropdown5: '退出登录',
dropdown6: '代码仓库',
searchPlaceholder: '菜单搜索:支持中文、路由路径',
newTitle: '通知',
newBtn: '全部已读',
newGo: '前往通知中心',
newDesc: '暂无通知',
logOutTitle: '提示',
logOutMessage: '此操作将退出登录, 是否继续?',
logOutConfirm: '确定',
logOutCancel: '取消',
logOutExit: '退出中',
logOutSuccess: '安全退出成功!',
},
tagsView: {
refresh: '刷新',
close: '关闭',
closeOther: '关闭其它',
closeAll: '全部关闭',
fullscreen: '当前页全屏',
},
notFound: {
foundTitle: '地址输入错误,请重新输入地址~',
foundMsg: '您可以先检查网址,然后重新输入或给我们反馈问题。',
foundBtn: '返回首页',
},
noAccess: {
accessTitle: '您未被授权,没有操作权限~',
accessMsg: '联系方式:加QQ群探讨 665452019',
accessBtn: '重新授权',
},
layout: {
configTitle: '布局配置',
oneTitle: '全局主题',
twoTitle: '菜单 / 顶栏',
twoTopBar: '顶栏背景',
twoMenuBar: '菜单背景',
twoColumnsMenuBar: '分栏菜单背景',
twoTopBarColor: '顶栏默认字体颜色',
twoMenuBarColor: '菜单默认字体颜色',
twoColumnsMenuBarColor: '分栏菜单默认字体颜色',
twoIsTopBarColorGradual: '顶栏背景渐变',
twoIsMenuBarColorGradual: '菜单背景渐变',
twoIsMenuBarColorHighlight: '菜单字体背景高亮',
threeTitle: '界面设置',
threeIsCollapse: '菜单水平折叠',
threeIsUniqueOpened: '菜单手风琴',
threeIsFixedHeader: '固定 Header',
threeIsClassicSplitMenu: '经典布局分割菜单',
threeIsLockScreen: '开启锁屏',
threeLockScreenTime: '自动锁屏(s/秒)',
fourTitle: '界面显示',
fourIsShowLogo: '侧边栏 Logo',
fourIsBreadcrumb: '开启 Breadcrumb',
fourIsBreadcrumbIcon: '开启 Breadcrumb 图标',
fourIsTagsview: '开启 Tagsview',
fourIsTagsviewIcon: '开启 Tagsview 图标',
fourIsCacheTagsView: '开启 TagsView 缓存',
fourIsSortableTagsView: '开启 TagsView 拖拽',
fourIsFooter: '开启 Footer',
fourIsGrayscale: '灰色模式',
fourIsInvert: '色弱模式',
fourIsDark: '深色模式',
fourIsWartermark: '开启水印',
fourWartermarkText: '水印文案',
fiveTitle: '其它设置',
fiveTagsStyle: 'Tagsview 风格',
fiveAnimation: '主页面切换动画',
fiveColumnsAsideStyle: '分栏高亮风格',
fiveColumnsAsideLayout: '分栏布局风格',
sixTitle: '布局切换',
sixDefaults: '默认',
sixClassic: '经典',
sixTransverse: '横向',
sixColumns: '分栏',
tipText: '点击下方按钮,复制布局配置去 `src/store/modules/themeConfig.js` 中修改。',
copyText: '一键复制配置',
resetText: '一键恢复默认',
copyTextSuccess: '复制成功!',
copyTextError: '复制失败!',
},
upgrade: {
title: '新版本升级',
msg: '新版本来啦,马上更新尝鲜吧!不用担心,更新很快的哦!',
desc: '提示:更新会还原默认配置',
btnOne: '残忍拒绝',
btnTwo: '马上更新',
btnTwoLoading: '更新中',
},
};
+176
View File
@@ -0,0 +1,176 @@
// 定义内容
export default {
router: {
home: '首頁',
system: '系統設置',
systemMenu: '選單管理',
systemUser: '用戶管理',
limits: '許可權管理',
limitsFrontEnd: '前端控制',
limitsFrontEndPage: '頁面許可權',
limitsFrontEndBtn: '按鈕許可權',
limitsBackEnd: '後端控制',
personnelManagement:'人員管理',
ParentList:'家長列表',
limitsBackEndEndPage: '頁面許可權',
MeetingRoomReservation:'會議室與功能室',
CreateMeetingRoom:'創建會議室',
CreateFunctionRoom:'創建功能室',
CampusCalendar:'校園行事歷',
PrincipalsMailbox:"校長信箱",
TeacherTable:'教師列表',
abnormalStudentManagement:'异常学生管理',
roleManagement:'角色分配',
StudentTable:'學生列表',
LetterList:"信件列表",
Statistics:'统计',
ccInformation:'配置',
moralEducationManagement:'德育管理',
ResponsiblePersonManagement:'負責人管理',
morningAndAfternoonInspectionManagement:"晨午检管理",
AttendanceForm:'考勤表單',
StudentSafetyAttendance:'學生安全考勤',
leavedRecord: '請假記錄',
SetAttendanceRules:'設置考勤規則',
Inspect:'晨午檢查',
MoralEducationEvaluation:'德育評價',
InterestClass:'興趣班',
InterestClassEntry:'興趣班錄入',
InterestCourseManagement:'興趣課程管理',
PaymentSystem:'繳費系統',
CreatePayment:'創建繳費',
PaymentDetails:'繳費明細',
SmartVisitors:'智能訪客',
HomeSchoolAddressBook:'家校通信錄',
VisitorsRecord:'訪客記錄',
basicInFormation:'信息管理',
businessDataInformation:'業務數據管理',
dataItemAnalysis:'數據項分析',
dataItemConfiguration:'數據項配置',
pictureSetConfiguration:'圖片集配置',
growthAlbumSection:'成長畫冊',
rolePermissions:'角色权限',
setScoreRules:'设置规则',
schoolAlbumManagement:'學校畫冊管理',
facultyInformation:'教職工信息',
deviceManagement:'人脸设备管理',
attendanceMachineEquipmentManagement:'考勤機設備管理',
devicelog: '設備日誌',
recipe: '每周食谱',
evaluate: '幼儿评价表',
classList: '班级管理',
department: '部门管理',
regulation: '规则管理',
},
staticRoutes: {
signIn: '登入',
notFound: '找不到此頁面',
noPower: '沒有許可權',
},
user: {
title0: '組件大小',
title1: '語言切換',
title2: '選單蒐索',
title3: '佈局配寘',
title4: '消息',
title5: '開全屏',
title6: '關全屏',
dropdownDefault: '默認',
dropdownMedium: '中等',
dropdownSmall: '小型',
dropdownMini: '超小',
dropdown1: '首頁',
dropdown2: '個人中心',
dropdown3: '404',
dropdown4: '401',
dropdown5: '登出',
dropdown6: '程式碼倉庫',
searchPlaceholder: '選單蒐索:支援中文、路由路徑',
newTitle: '通知',
newBtn: '全部已讀',
newGo: '前往通知中心',
newDesc: '暫無通知',
logOutTitle: '提示',
logOutMessage: '此操作將登出,是否繼續?',
logOutConfirm: '確定',
logOutCancel: '取消',
logOutExit: '退出中',
logOutSuccess: '安全退出成功!',
},
tagsView: {
refresh: '重繪',
close: '關閉',
closeOther: '關閉其它',
closeAll: '全部關閉',
fullscreen: '當前頁全屏',
},
notFound: {
foundTitle: '地址輸入錯誤,請重新輸入地址~',
foundMsg: '您可以先檢查網址,然後重新輸入或給我們迴響問題。',
foundBtn: '返回首頁',
},
noAccess: {
accessTitle: '您未被授權,沒有操作許可權~',
accessMsg: '聯繫方式:加QQ群探討665452019',
accessBtn: '重新授權',
},
layout: {
configTitle: '佈局配寘',
oneTitle: '全域主題',
twoTitle: '選單 / 頂欄',
twoTopBar: '頂欄背景',
twoMenuBar: '選單背景',
twoColumnsMenuBar: '分欄選單背景',
twoTopBarColor: '頂欄默認字體顏色',
twoMenuBarColor: '選單默認字體顏色',
twoColumnsMenuBarColor: '分欄選單默認字體顏色',
twoIsTopBarColorGradual: '頂欄背景漸變',
twoIsMenuBarColorGradual: '選單背景漸變',
twoIsMenuBarColorHighlight: '選單字體背景高亮',
threeTitle: '介面設定',
threeIsCollapse: '選單水准折疊',
threeIsUniqueOpened: '選單手風琴',
threeIsFixedHeader: '固定 Header',
threeIsClassicSplitMenu: '經典佈局分割選單',
threeIsLockScreen: '開啟鎖屏',
threeLockScreenTime: '自動鎖屏(s/秒)',
fourTitle: '介面顯示',
fourIsShowLogo: '側邊欄 Logo',
fourIsBreadcrumb: '開啟 Breadcrumb',
fourIsBreadcrumbIcon: '開啟 Breadcrumb 圖標',
fourIsTagsview: '開啟 Tagsview',
fourIsTagsviewIcon: '開啟 Tagsview 圖標',
fourIsCacheTagsView: '開啟 TagsView 緩存',
fourIsSortableTagsView: '開啟 TagsView 拖拽',
fourIsFooter: '開啟 Footer',
fourIsGrayscale: '灰色模式',
fourIsInvert: '色弱模式',
fourIsDark: '深色模式',
fourIsWartermark: '開啟浮水印',
fourWartermarkText: '浮水印文案',
fiveTitle: '其它設定',
fiveTagsStyle: 'Tagsview 風格',
fiveAnimation: '主頁面切換動畫',
fiveColumnsAsideStyle: '分欄高亮風格',
fiveColumnsAsideLayout: '分欄佈局風格',
sixTitle: '佈局切換',
sixDefaults: '默認',
sixClassic: '經典',
sixTransverse: '橫向',
sixColumns: '分欄',
tipText: '點擊下方按鈕,複製佈局配寘去`src/store/modules/themeConfig.js`中修改。',
copyText: '一鍵複製配寘',
resetText: '一鍵恢復默認',
copyTextSuccess: '複製成功!',
copyTextError: '複製失敗!',
},
upgrade: {
title: '新版本陞級',
msg: '新版本來啦,馬上更新嘗鮮吧! 不用擔心,更新很快的哦!',
desc: '提示:更新會還原默認配寘',
btnOne: '殘忍拒絕',
btnTwo: '馬上更新',
btnTwoLoading: '更新中',
},
};
+14
View File
@@ -0,0 +1,14 @@
// 定义内容
export default {
card: {
title1: 'My desk',
title2: 'Message notification',
title3: 'more',
title4: 'Marketing recommendation',
title5: 'more',
title6: 'Inventory operations',
title7: 'Performance',
title8: 'Out of stock monitoring',
title9: 'Performance overtime warning',
},
};
+14
View File
@@ -0,0 +1,14 @@
// 定义内容
export default {
card: {
title1: '我的工作台',
title2: '消息通知',
title3: '更多',
title4: '营销推荐',
title5: '更多',
title6: '库存作业',
title7: '履约情况',
title8: '缺货监控',
title9: '履约超时预警',
},
};
+14
View File
@@ -0,0 +1,14 @@
// 定义内容
export default {
card: {
title1: '我的工作臺',
title2: '消息通知',
title3: '更多',
title4: '行銷推薦',
title5: '更多',
title6: '庫存工作',
title7: '履約情况',
title8: '缺貨監控',
title9: '履約超時預警',
},
};
+18
View File
@@ -0,0 +1,18 @@
// 定义内容
export default {
login: {
placeholder1: 'Please enter your phone number',
placeholder2: 'Please enter the verification code',
placeholder3: 'Please enter the verification code',
btnText: 'Sign in',
link: {
one1: 'Third party login',
one2: 'Links',
},
signInText: 'welcome back!',
copyright: {
one5: 'Copyright: Shenzhen XXX Software Technology Co., Ltd',
two6: 'Copyright: Shenzhen XXX software technology Guangdong ICP preparation no.05010000',
},
},
};
+18
View File
@@ -0,0 +1,18 @@
// 定义内容
export default {
login: {
placeholder1: '请输入手机号',
placeholder2: '请输入验证码',
placeholder3: '请输入验证码',
btnText: '登 录',
link: {
one1: '第三方登录',
one2: '友情链接',
},
signInText: '欢迎回来!',
copyright: {
one5: '版权所有:深圳市xxx软件科技有限公司',
two6: 'Copyright: Shenzhen XXX Software Technology 粤ICP备05010000号',
},
},
};
+18
View File
@@ -0,0 +1,18 @@
// 定义内容
export default {
login: {
placeholder1: '請輸入驗證碼',
placeholder2: '請輸入驗證碼',
placeholder3: '請輸入驗證碼',
btnText: '登 录',
link: {
one1: '協力廠商登入',
one2: '友情連結',
},
signInText: '歡迎回來!',
copyright: {
one5: '版權所有:深圳市xxx軟件科技有限公司',
two6: 'Copyright: Shenzhen XXX Software Technology 粵ICP備05010000號',
},
},
};
+106
View File
@@ -0,0 +1,106 @@
<template>
<el-aside class="layout-aside" :class="setCollapseWidth" v-if="clientWidth > 1000">
<Logo v-if="setShowLogo" />
<el-scrollbar class="flex-auto" ref="layoutAsideRef">
<Vertical :menuList="menuList" :class="setCollapseWidth" />
</el-scrollbar>
</el-aside>
<el-drawer :visible.sync="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="layoutAsideRef">
<Vertical :menuList="menuList" />
</el-scrollbar>
</el-aside>
</el-drawer>
</template>
<script>
import Vertical from '@/layout/navMenu/vertical.vue';
import Logo from '@/layout/logo/index.vue';
export default {
name: 'layoutAside',
components: { Vertical, Logo },
data() {
return {
menuList: [],
clientWidth: '',
};
},
computed: {
// 设置左侧菜单的具体宽度
setCollapseWidth() {
let { layout, isCollapse } = this.$store.state.themeConfig.themeConfig;
let asideBrColor = '';
layout === 'classic' || layout === 'columns' ? (asideBrColor = '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 是否显示
setShowLogo() {
let { layout, isShowLogo } = this.$store.state.themeConfig.themeConfig;
return (isShowLogo && layout === 'defaults') || (isShowLogo && layout === 'columns');
},
// 获取布局配置信息
getThemeConfig() {
return this.$store.state.themeConfig.themeConfig;
},
},
created() {
this.initMenuFixed(document.body.clientWidth);
this.setFilterRoutes();
this.bus.$on('setSendColumnsChildren', (res) => {
this.menuList = res.children;
});
this.bus.$on('layoutMobileResize', (res) => {
this.initMenuFixed(res.clientWidth);
});
// 菜单滚动条监听
this.bus.$on('updateElScrollBar', () => {
setTimeout(() => {
this.$refs.layoutAsideRef.update();
}, 300);
});
},
methods: {
// 设置/过滤路由(非静态路由/是否显示在菜单中)
setFilterRoutes() {
if (this.$store.state.themeConfig.themeConfig.layout === 'columns') return false;
this.menuList = this.filterRoutesFun(this.$store.state.routesList.routesList);
},
// 设置/过滤路由 递归函数
filterRoutesFun(arr) {
return arr
.filter((item) => !item.meta.isHide)
.map((item) => {
item = Object.assign({}, item);
if (item.children) item.children = this.filterRoutesFun(item.children);
return item;
});
},
// 设置菜单导航是否固定(移动端)
initMenuFixed(clientWidth) {
this.clientWidth = clientWidth;
},
},
// 页面销毁时
destroyed() {
// 取消菜单滚动条监听
this.bus.$off('updateElScrollBar', () => {});
},
};
</script>
+233
View File
@@ -0,0 +1,233 @@
<template>
<div class="layout-columns-aside">
<el-scrollbar>
<ul>
<li
v-for="(v, k) in columnsAsideList"
:key="k"
@click="onColumnsAsideMenuClick(v)"
ref="columnsAsideOffsetTopRefs"
:class="{ 'layout-columns-active': liIndex === k }"
:title="$t(v.meta.title)"
>
<div :class="setColumnsAsidelayout" v-if="!v.meta.isLink || (v.meta.isLink && v.meta.isIframe)">
<i :class="v.meta.icon"></i>
<div class="font12">
{{
$t(v.meta.title) && $t(v.meta.title).length >= 4
? $t(v.meta.title).substr(0, setColumnsAsidelayout === 'columns-vertical' ? 4 : 3)
: $t(v.meta.title)
}}
</div>
</div>
<div :class="setColumnsAsidelayout" v-else>
<a :href="v.meta.isLink" target="_blank">
<i :class="v.meta.icon"></i>
<div class="font12">
{{
$t(v.meta.title) && $t(v.meta.title).length >= 4
? $t(v.meta.title).substr(0, setColumnsAsidelayout === 'columns-vertical' ? 4 : 3)
: $t(v.meta.title)
}}
</div>
</a>
</div>
</li>
<div ref="columnsAsideActiveRef" :class="setColumnsAsideStyle"></div>
</ul>
</el-scrollbar>
</div>
</template>
<script>
export default {
name: 'layoutColumnsAside',
data() {
return {
columnsAsideList: [],
liIndex: 0,
difference: 0,
routeSplit: [],
};
},
computed: {
// 设置分栏高亮风格
setColumnsAsideStyle() {
return this.$store.state.themeConfig.themeConfig.columnsAsideStyle;
},
// 设置分栏布局风格
setColumnsAsidelayout() {
return this.$store.state.themeConfig.themeConfig.columnsAsideLayout;
},
},
mounted() {
this.setFilterRoutes();
},
methods: {
// 设置菜单高亮位置移动
setColumnsAsideMove(k) {
if (k === undefined) return false;
const els = this.$refs.columnsAsideOffsetTopRefs;
this.liIndex = k;
this.$refs.columnsAsideActiveRef.style.top = `${els[k].offsetTop + this.difference}px`;
},
// 菜单高亮点击事件
onColumnsAsideMenuClick(v) {
let { path, redirect } = v;
if (redirect) this.$router.push(redirect);
else this.$router.push(path);
// 一个路由设置自动收起菜单
// https://gitee.com/lyt-top/vue-next-admin/issues/I6HW7H
if (!v.children || v.children.length <= 1) this.$store.state.themeConfig.themeConfig.isCollapse = true;
else if (v.children.length > 1) this.$store.state.themeConfig.themeConfig.isCollapse = false;
},
// 设置高亮动态位置
onColumnsAsideDown(k) {
this.$nextTick(() => {
this.setColumnsAsideMove(k);
});
},
// 设置/过滤路由(非静态路由/是否显示在菜单中)
setFilterRoutes() {
if (this.$store.state.routesList.routesList.length <= 0) return false;
this.columnsAsideList = this.filterRoutesFun(this.$store.state.routesList.routesList);
const resData = this.setSendChildren(this.$route.path);
if (Object.keys(resData).length <= 0) return false;
this.onColumnsAsideDown(resData.item[0].k);
// 刷新时,初始化一个路由设置自动收起菜单
// https://gitee.com/lyt-top/vue-next-admin/issues/I6HW7H
resData.children.length <= 1
? (this.$store.state.themeConfig.themeConfig.isCollapse = true)
: (this.$store.state.themeConfig.themeConfig.isCollapse = false);
this.bus.$emit('setSendColumnsChildren', resData);
},
// 传送当前子级数据到菜单中
setSendChildren(path) {
const currentPathSplit = path.split('/');
let currentData = {};
this.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;
},
// 路由过滤递归函数
filterRoutesFun(arr) {
return arr
.filter((item) => !item.meta.isHide)
.map((item) => {
item = Object.assign({}, item);
if (item.children) item.children = this.filterRoutesFun(item.children);
return item;
});
},
// tagsView 点击时,根据路由查找下标 columnsAsideList,实现左侧菜单高亮
setColumnsMenuHighlight(path) {
this.routeSplit = path.split('/');
this.routeSplit.shift();
const routeFirst = `/${this.routeSplit[0]}`;
const currentSplitRoute = this.columnsAsideList.find((v) => v.path === routeFirst);
if (!currentSplitRoute) return false;
// 延迟拿值,防止取不到
setTimeout(() => {
this.onColumnsAsideDown(currentSplitRoute.k);
}, 0);
},
},
watch: {
// 监听 vuex 数据变化
'$store.state': {
handler(val) {
val.themeConfig.themeConfig.columnsAsideStyle === 'columnsRound' ? (this.difference = 3) : (this.difference = 0);
if (val.routesList.routesList.length === this.columnsAsideList.length) return false;
this.setFilterRoutes();
},
deep: true,
},
// 监听路由的变化
$route: {
handler(to) {
this.setColumnsMenuHighlight(to.path);
this.bus.$emit('setSendColumnsChildren', this.setSendChildren(to.path));
},
deep: true,
},
},
};
</script>
<style scoped lang="scss">
.layout-columns-aside {
width: 70px;
height: 100%;
background: var(--prev-bg-columnsMenuBar);
ul {
position: relative;
li {
color: var(--prev-bg-columnsMenuBarColor);
width: 100%;
height: 50px;
text-align: center;
display: flex;
cursor: pointer;
position: relative;
z-index: 1;
.columns-vertical {
margin: auto;
.columns-vertical-title {
padding-top: 1px;
}
}
.columns-horizontal {
display: flex;
height: 50px;
width: 100%;
align-items: center;
padding: 0 5px;
i {
margin-right: 3px;
}
a {
display: flex;
.columns-horizontal-title {
padding-top: 1px;
}
}
}
a {
text-decoration: none;
color: var(--prev-bg-columnsMenuBarColor);
}
}
.layout-columns-active,
.layout-columns-active a {
color: var(--prev-color-text-white);
transition: 0.3s ease-in-out;
}
.columns-round {
background: var(--prev-color-primary);
color: var(--prev-color-text-white);
position: absolute;
left: 50%;
top: 2px;
height: 50px;
width: 65px;
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>
+24
View File
@@ -0,0 +1,24 @@
<template>
<el-header class="layout-header" :height="setHeaderHeight">
<NavBarsIndex />
</el-header>
</template>
<script>
import NavBarsIndex from '@/layout/navBars/index.vue';
export default {
name: 'layoutHeader',
components: { NavBarsIndex },
data() {
return {};
},
computed: {
// 设置顶部 header 的具体高度
setHeaderHeight() {
let { isTagsview, layout } = this.$store.state.themeConfig.themeConfig;
if (isTagsview && layout !== 'classic') return '84px';
else return '50px';
},
},
};
</script>
+93
View File
@@ -0,0 +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 />
<Footers v-if="getThemeConfig.isFooter" />
</el-scrollbar>
<Links
: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>
import LayoutParentView from '@/layout/routerView/parent.vue';
import Footers from '@/layout/footer/index.vue';
import Links from '@/layout/routerView/link.vue';
import Iframes from '@/layout/routerView/iframes.vue';
export default {
name: 'layoutMain',
components: { LayoutParentView, Footers, Links, Iframes },
data() {
return {
headerHeight: '',
currentRouteMeta: {},
isShowLink: false,
};
},
computed: {
// 获取布局配置信息
getThemeConfig() {
return this.$store.state.themeConfig.themeConfig;
},
},
mounted() {
this.initHeaderHeight();
this.initCurrentRouteMeta(this.$route.meta);
},
methods: {
// 初始化当前路由 meta 信息
initCurrentRouteMeta(meta) {
this.isShowLink = false;
this.currentRouteMeta = meta;
setTimeout(() => {
this.isShowLink = true;
}, 100);
},
// 设置 main 的高度
initHeaderHeight() {
let { isTagsview } = this.$store.state.themeConfig.themeConfig;
if (isTagsview) return (this.headerHeight = `84px`);
else return (this.headerHeight = `50px`);
},
// 子组件触发更新
onGetCurrentRouteMeta() {
this.initCurrentRouteMeta(this.$route.meta);
},
},
watch: {
// 监听 vuex 数据变化
'$store.state.themeConfig.themeConfig': {
handler(val) {
this.headerHeight = val.isTagsview ? '84px' : '50px';
if (val.isFixedHeaderChange !== val.isFixedHeader) {
if (!this.$refs.layoutScrollbarRef) return false;
this.$refs.layoutScrollbarRef.update();
}
},
deep: true,
},
// 监听路由的变化
$route: {
handler(to) {
this.initCurrentRouteMeta(to.meta);
this.$refs.layoutScrollbarRef.wrap.scrollTop = 0;
},
deep: true,
},
},
};
</script>
+29
View File
@@ -0,0 +1,29 @@
<template>
<div class="layout-footer mt15">
<div class="layout-footer-warp">
<div>智慧校园</div>
<div class="mt5">版权所有数字校园教育管理平台</div>
</div>
</div>
</template>
<script>
export default {
name: "layoutFooter",
data() {
return {};
},
};
</script>
<style scoped lang="scss">
.layout-footer {
width: 100%;
display: flex;
&-warp {
margin: auto;
color: var(--prev-color-text-secondary);
text-align: center;
}
}
</style>
+51
View File
@@ -0,0 +1,51 @@
<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'" />
</template>
<script>
import { Local } from '@/utils/storage.js';
export default {
name: 'layout',
components: {
Defaults: () => import('@/layout/main/defaults.vue'),
Classic: () => import('@/layout/main/classic.vue'),
Transverse: () => import('@/layout/main/transverse.vue'),
Columns: () => import('@/layout/main/columns.vue'),
},
computed: {
// 获取布局配置信息
getThemeConfig() {
return this.$store.state.themeConfig.themeConfig;
},
},
created() {
this.onLayoutResize();
window.addEventListener('resize', this.onLayoutResize);
},
methods: {
// 窗口大小改变时(适配移动端)
onLayoutResize() {
if (!Local.get('oldLayout')) Local.set('oldLayout', this.$store.state.themeConfig.themeConfig.layout);
const clientWidth = document.body.clientWidth;
if (clientWidth < 1000) {
this.$store.state.themeConfig.themeConfig.isCollapse = false;
this.bus.$emit('layoutMobileResize', {
layout: 'defaults',
clientWidth,
});
} else {
this.bus.$emit('layoutMobileResize', {
layout: Local.get('oldLayout') ? Local.get('oldLayout') : this.$store.state.themeConfig.themeConfig.layout,
clientWidth,
});
}
},
},
distroyed() {
window.removeEventListener('resize', this.onLayoutResize);
},
};
</script>
+78
View File
@@ -0,0 +1,78 @@
<template>
<div class="layout-logo" v-if="setShowLogo" @click="onThemeConfigChange">
<!-- <img :src="logo" class="layout-logo-medium-img" /> -->
<!-- <span>{{ getThemeConfig.globalTitle }}</span> -->
<span>数字校园教育管理平台</span>
</div>
<div class="layout-logo-size" v-else @click="onThemeConfigChange">
<img :src="logo" class="layout-logo-size-img" />
</div>
</template>
<script>
export default {
name: "layoutLogo",
data() {
return {
logo: require("@/assets/logo.png"),
};
},
computed: {
// 获取布局配置信息
getThemeConfig() {
console.log(this.$store.state.themeConfig);
return this.$store.state.themeConfig.themeConfig;
},
// 设置 logo 是否显示
setShowLogo() {
let { isCollapse, layout } = this.$store.state.themeConfig.themeConfig;
return !isCollapse || layout === "classic" || document.body.clientWidth < 1000;
},
},
methods: {
// logo 点击实现菜单展开/收起
onThemeConfigChange() {
if (this.$store.state.themeConfig.themeConfig.layout === "transverse") return false;
this.$store.state.themeConfig.themeConfig.isCollapse = !this.$store.state
.themeConfig.themeConfig.isCollapse;
},
},
};
</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(--prev-color-primary);
font-size: 16px;
cursor: pointer;
animation: logoAnimation 0.3s ease-in-out;
&:hover {
span {
opacity: 0.9;
}
}
&-medium-img {
width: 20px;
margin-right: 5px;
position: relative;
top: 2px;
}
}
.layout-logo-size {
width: 100%;
height: 50px;
display: flex;
cursor: pointer;
&-img {
width: 20px;
margin: auto;
animation: logoAnimation 0.3s ease-in-out;
}
}
</style>
+30
View File
@@ -0,0 +1,30 @@
<template>
<el-container class="layout-container flex-center">
<Headers />
<el-container class="layout-mian-height-50">
<Asides />
<div class="flex-center layout-backtop">
<TagsView v-if="getThemeConfig.isTagsview" />
<Mains />
</div>
</el-container>
<el-backtop target=".layout-backtop .el-main .el-scrollbar__wrap"></el-backtop>
</el-container>
</template>
<script>
import Asides from '@/layout/component/aside.vue';
import Headers from '@/layout/component/header.vue';
import Mains from '@/layout/component/main.vue';
import TagsView from '@/layout/navBars/tagsView/tagsView.vue';
export default {
name: 'layoutClassic',
components: { Asides, Headers, Mains, TagsView },
computed: {
// 获取布局配置信息
getThemeConfig() {
return this.$store.state.themeConfig.themeConfig;
},
},
};
</script>
+33
View File
@@ -0,0 +1,33 @@
<template>
<el-container class="layout-container">
<ColumnsAside />
<div class="layout-columns-warp">
<Asides />
<el-container class="flex-center layout-backtop">
<Headers v-if="isFixedHeader" />
<el-scrollbar>
<Headers v-if="!isFixedHeader" />
<Mains />
</el-scrollbar>
</el-container>
</div>
<el-backtop target=".layout-backtop .el-scrollbar__wrap"></el-backtop>
</el-container>
</template>
<script>
import Asides from '@/layout/component/aside.vue';
import Headers from '@/layout/component/header.vue';
import Mains from '@/layout/component/main.vue';
import ColumnsAside from '@/layout/component/columnsAside.vue';
export default {
name: 'layoutColumns',
components: { Asides, Headers, Mains, ColumnsAside },
computed: {
// 是否开启固定 header
isFixedHeader() {
return this.$store.state.themeConfig.themeConfig.isFixedHeader;
},
},
};
</script>
+41
View File
@@ -0,0 +1,41 @@
<template>
<el-container class="layout-container">
<Asides />
<el-container class="flex-center layout-backtop">
<Headers v-if="isFixedHeader" />
<el-scrollbar ref="layoutDefaultsScrollbarRef">
<Headers v-if="!isFixedHeader" />
<Mains />
</el-scrollbar>
</el-container>
<el-backtop target=".layout-backtop .el-scrollbar__wrap"></el-backtop>
</el-container>
</template>
<script>
import Asides from '@/layout/component/aside.vue';
import Headers from '@/layout/component/header.vue';
import Mains from '@/layout/component/main.vue';
export default {
name: 'layoutDefaults',
components: { Asides, Headers, Mains },
data() {
return {};
},
computed: {
// 是否开启固定 header
isFixedHeader() {
return this.$store.state.themeConfig.themeConfig.isFixedHeader;
},
},
watch: {
// 监听路由的变化
$route: {
handler() {
this.$refs.layoutDefaultsScrollbarRef.wrap.scrollTop = 0;
},
deep: true,
},
},
};
</script>
+16
View File
@@ -0,0 +1,16 @@
<template>
<el-container class="layout-container flex-center layout-backtop">
<Headers />
<Mains />
<el-backtop target=".layout-backtop .el-main .el-scrollbar__wrap"></el-backtop>
</el-container>
</template>
<script>
import Headers from '@/layout/component/header.vue';
import Mains from '@/layout/component/main.vue';
export default {
name: 'layoutTransverse',
components: { Headers, Mains },
};
</script>
@@ -0,0 +1,139 @@
<template>
<div class="layout-navbars-breadcrumb" :style="{ display: isShowBreadcrumb }">
<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.path">
<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>{{ $t(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>{{ $t(v.meta.title) }}
</a>
</el-breadcrumb-item>
</transition-group>
</el-breadcrumb>
</div>
</template>
<script>
import { Local } from '@/utils/storage.js';
export default {
name: 'layoutBreadcrumb',
data() {
return {
breadcrumbList: [],
routeSplit: [],
routeSplitFirst: '',
routeSplitIndex: 1,
};
},
computed: {
// 获取布局配置信息
getThemeConfig() {
return this.$store.state.themeConfig.themeConfig;
},
// 动态设置经典、横向布局不显示
isShowBreadcrumb() {
const { layout, isBreadcrumb } = this.$store.state.themeConfig.themeConfig;
if (layout === 'classic' || layout === 'transverse') {
return 'none';
} else {
return isBreadcrumb ? '' : 'none';
}
},
},
mounted() {
this.initRouteSplit(this.$route.path);
},
methods: {
// breadcrumb 当前项点击时
onBreadcrumbClick(v) {
const { redirect, path } = v;
if (redirect) this.$router.push(redirect);
else this.$router.push(path);
},
// breadcrumb icon 点击菜单展开与收起
onThemeConfigChange() {
this.$store.state.themeConfig.themeConfig.isCollapse = !this.$store.state.themeConfig.themeConfig.isCollapse;
this.setLocalThemeConfig();
},
// 存储布局配置
setLocalThemeConfig() {
Local.remove('themeConfigPrev');
Local.set('themeConfigPrev', this.$store.state.themeConfig.themeConfig);
},
// 递归设置 breadcrumb
getBreadcrumbList(arr) {
arr.map((item) => {
this.routeSplit.map((v, k, arrs) => {
if (this.routeSplitFirst === item.path) {
this.routeSplitFirst += `/${arrs[this.routeSplitIndex]}`;
this.breadcrumbList.push(item);
this.routeSplitIndex++;
if (item.children) this.getBreadcrumbList(item.children);
}
});
});
},
// 当前路由分割处理
initRouteSplit(path) {
this.breadcrumbList = [
{
path: '/',
meta: {
title: this.$store.state.routesList.routesList[0].meta.title,
icon: this.$store.state.routesList.routesList[0].meta.icon,
},
},
];
this.routeSplit = path.split('/');
this.routeSplit.shift();
this.routeSplitFirst = `/${this.routeSplit[0]}`;
this.routeSplitIndex = 1;
this.getBreadcrumbList(this.$store.state.routesList.routesList);
},
},
// 监听路由的变化
watch: {
$route: {
handler(newVal) {
this.initRouteSplit(newVal.path);
},
deep: true,
},
},
};
</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(--prev-bg-topBarColor);
opacity: 0.8;
&:hover {
opacity: 1;
}
}
.layout-navbars-breadcrumb-span {
opacity: 0.7;
color: var(--prev-bg-topBarColor);
}
.layout-navbars-breadcrumb-iconfont {
font-size: 14px;
margin-right: 5px;
}
}
</style>
+77
View File
@@ -0,0 +1,77 @@
<template>
<div class="layout-navbars-breadcrumb-index">
<Logo v-if="setIsShowLogo" />
<Breadcrumb />
<Horizontal :menuList="menuList" v-if="isLayoutTransverse" />
<User />
</div>
</template>
<script>
import Breadcrumb from '@/layout/navBars/breadcrumb/breadcrumb.vue';
import User from '@/layout/navBars/breadcrumb/user.vue';
import Logo from '@/layout/logo/index.vue';
import Horizontal from '@/layout/navMenu/horizontal.vue';
export default {
name: 'layoutNavBars',
components: { Breadcrumb, User, Logo, Horizontal },
data() {
return {
menuList: [],
};
},
computed: {
// 设置 logo 是否显示
setIsShowLogo() {
let { isShowLogo, layout } = this.$store.state.themeConfig.themeConfig;
return (isShowLogo && layout === 'classic') || (isShowLogo && layout === 'transverse');
},
// 设置是否显示横向菜单
isLayoutTransverse() {
let { layout, isClassicSplitMenu } = this.$store.state.themeConfig.themeConfig;
return layout === 'transverse' || (isClassicSplitMenu && layout === 'classic');
},
},
mounted() {
this.setFilterRoutes();
},
methods: {
// 设置路由的过滤
setFilterRoutes() {
this.menuList = this.filterRoutesFun(this.$store.state.routesList.routesList);
},
// 设置路由的过滤递归函数
filterRoutesFun(arr) {
return arr
.filter((item) => !item.meta.isHide)
.map((item) => {
item = Object.assign({}, item);
if (item.children) item.children = this.filterRoutesFun(item.children);
return item;
});
},
},
watch: {
// 监听 vuex 数据变化
'$store.state': {
handler(val) {
if (val.routesList.routesList.length === this.menuList.length) return false;
this.setFilterRoutes();
},
deep: true,
},
},
};
</script>
<style scoped lang="scss">
.layout-navbars-breadcrumb-index {
height: 50px;
display: flex;
align-items: center;
padding-right: 15px;
overflow: hidden;
background: var(--prev-bg-topBar);
border-bottom: 1px solid var(--prev-border-color-lighter);
}
</style>
+100
View File
@@ -0,0 +1,100 @@
<template>
<div class="layout-search-dialog">
<el-dialog :visible.sync="isShowSearch" width="300px" destroy-on-close :modal="false" fullscreen :show-close="false">
<el-autocomplete
v-model="menuQuery"
:fetch-suggestions="menuSearch"
:placeholder="$t('message.user.searchPlaceholder')"
prefix-icon="el-icon-search"
ref="layoutMenuAutocompleteRef"
@select="onHandleSelect"
@blur="onSearchBlur"
>
<template slot-scope="{ item }">
<div><i :class="item.meta.icon" class="mr10"></i>{{ $t(item.meta.title) }}</div>
</template>
</el-autocomplete>
</el-dialog>
</div>
</template>
<script>
export default {
name: 'layoutBreadcrumbSearch',
data() {
return {
isShowSearch: false,
menuQuery: '',
tagsViewList: [],
};
},
methods: {
// 搜索弹窗打开
openSearch() {
this.menuQuery = '';
this.isShowSearch = true;
this.initTageView();
this.$nextTick(() => {
this.$refs.layoutMenuAutocompleteRef.focus();
});
},
// 搜索弹窗关闭
closeSearch() {
setTimeout(() => {
this.isShowSearch = false;
}, 150);
},
// 菜单搜索数据过滤
menuSearch(queryString, cb) {
let results = queryString ? this.tagsViewList.filter(this.createFilter(queryString)) : this.tagsViewList;
cb(results);
},
// 菜单搜索过滤
createFilter(queryString) {
return (restaurant) => {
return (
restaurant.path.toLowerCase().indexOf(queryString.toLowerCase()) > -1 ||
restaurant.meta.title.toLowerCase().indexOf(queryString.toLowerCase()) > -1 ||
this.$t(restaurant.meta.title).toLowerCase().indexOf(queryString.toLowerCase()) > -1
);
};
},
// 初始化菜单数据
initTageView() {
if (this.tagsViewList.length > 0) return false;
this.$store.state.tagsViewRoutes.tagsViewRoutes.map((v) => {
if (!v.meta.isHide) this.tagsViewList.push({ ...v });
});
},
// 当前菜单选中时
onHandleSelect(item) {
let { path, redirect } = item;
if (item.meta.isLink && !item.meta.isIframe) window.open(item.meta.isLink);
else if (redirect) this.$router.push(redirect);
else this.$router.push(path);
this.closeSearch();
},
// input 失去焦点时
onSearchBlur() {
this.closeSearch();
},
},
};
</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%);
}
}
</style>
+538
View File
@@ -0,0 +1,538 @@
<template>
<div class="layout-breadcrumb-seting">
<el-drawer
:title="$t('message.layout.configTitle')"
:visible.sync="getThemeConfig.isDrawer"
direction="rtl"
destroy-on-close
size="240px"
@close="onDrawerClose"
>
<el-scrollbar class="layout-breadcrumb-seting-bar">
<!-- 全局主题 -->
<el-divider content-position="left">{{ $t('message.layout.oneTitle') }}</el-divider>
<div class="layout-breadcrumb-seting-bar-flex">
<div class="layout-breadcrumb-seting-bar-flex-label">primary</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-color-picker v-model="getThemeConfig.primary" size="small" @change="onColorPickerChange"> </el-color-picker>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsDark') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch v-model="getThemeConfig.isIsDark" :width="35" @change="onAddDarkChange"></el-switch>
</div>
</div>
<!-- 界面设置 -->
<el-divider content-position="left">{{ $t('message.layout.threeTitle') }}</el-divider>
<div class="layout-breadcrumb-seting-bar-flex">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.threeIsCollapse') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch v-model="getThemeConfig.isCollapse" :width="35" @change="setLocalThemeConfig"></el-switch>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.threeIsUniqueOpened') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch v-model="getThemeConfig.isUniqueOpened" :width="35" @change="setLocalThemeConfig"></el-switch>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.threeIsFixedHeader') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch v-model="getThemeConfig.isFixedHeader" :width="35" @change="setLocalThemeConfig"></el-switch>
</div>
</div>
<!-- 界面显示 -->
<el-divider content-position="left">{{ $t('message.layout.fourTitle') }}</el-divider>
<div class="layout-breadcrumb-seting-bar-flex">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsShowLogo') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch v-model="getThemeConfig.isShowLogo" :width="35" @change="setLocalThemeConfig"></el-switch>
</div>
</div>
<div
class="layout-breadcrumb-seting-bar-flex mt15"
:style="{ opacity: getThemeConfig.layout === 'classic' || getThemeConfig.layout === 'transverse' ? 0.5 : 1 }"
>
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsBreadcrumb') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch
v-model="getThemeConfig.isBreadcrumb"
:disabled="getThemeConfig.layout === 'classic' || getThemeConfig.layout === 'transverse'"
:width="35"
@change="setLocalThemeConfig"
></el-switch>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsBreadcrumbIcon') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch v-model="getThemeConfig.isBreadcrumbIcon" :width="35" @change="setLocalThemeConfig"></el-switch>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsTagsview') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch v-model="getThemeConfig.isTagsview" :width="35" @change="setLocalThemeConfig"></el-switch>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsTagsviewIcon') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch v-model="getThemeConfig.isTagsviewIcon" :width="35" @change="setLocalThemeConfig"></el-switch>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsCacheTagsView') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch v-model="getThemeConfig.isCacheTagsView" :width="35" @change="setLocalThemeConfig"></el-switch>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsFooter') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch v-model="getThemeConfig.isFooter" :width="35" @change="setLocalThemeConfig"></el-switch>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsGrayscale') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch v-model="getThemeConfig.isGrayscale" :width="35" @change="onAddFilterChange('grayscale')"></el-switch>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsInvert') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch v-model="getThemeConfig.isInvert" :width="35" @change="onAddFilterChange('invert')"></el-switch>
</div>
</div>
<!-- 其它设置 -->
<el-divider content-position="left">{{ $t('message.layout.fiveTitle') }}</el-divider>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fiveTagsStyle') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-select v-model="getThemeConfig.tagsStyle" placeholder="请选择" size="mini" style="width: 90px" @change="setLocalThemeConfig">
<el-option label="风格1" value="tags-style-one"></el-option>
</el-select>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fiveAnimation') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-select v-model="getThemeConfig.animation" placeholder="请选择" size="mini" style="width: 90px" @change="setLocalThemeConfig">
<el-option label="slide-right" value="slide-right"></el-option>
<el-option label="slide-left" value="slide-left"></el-option>
<el-option label="opacitys" value="opacitys"></el-option>
</el-select>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fiveColumnsAsideStyle') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-select v-model="getThemeConfig.columnsAsideStyle" placeholder="请选择" size="mini" style="width: 90px" @change="setLocalThemeConfig">
<el-option label="圆角" value="columns-round"></el-option>
<el-option label="卡片" value="columns-card"></el-option>
</el-select>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15 mb28">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fiveColumnsAsideLayout') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-select v-model="getThemeConfig.columnsAsideLayout" placeholder="请选择" size="mini" style="width: 90px" @change="setLocalThemeConfig">
<el-option label="水平" value="columns-horizontal"></el-option>
<el-option label="垂直" value="columns-vertical"></el-option>
</el-select>
</div>
</div>
<!-- 布局切换 -->
<el-divider content-position="left">{{ $t('message.layout.sixTitle') }}</el-divider>
<div class="layout-drawer-content-flex">
<!-- defaults 布局 -->
<div class="layout-drawer-content-item" @click="onSetLayout('defaults')">
<section class="el-container el-circular" :class="{ 'drawer-layout-active': getThemeConfig.layout === 'defaults' }">
<aside class="el-aside" style="width: 20px"></aside>
<section class="el-container is-vertical">
<header class="el-header" style="height: 10px"></header>
<main class="el-main"></main>
</section>
</section>
<div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': getThemeConfig.layout === 'defaults' }">
<div class="layout-tips-box">
<p class="layout-tips-txt">{{ $t('message.layout.sixDefaults') }}</p>
</div>
</div>
</div>
<!-- classic 布局 -->
<div class="layout-drawer-content-item" @click="onSetLayout('classic')">
<section class="el-container is-vertical el-circular" :class="{ 'drawer-layout-active': getThemeConfig.layout === 'classic' }">
<header class="el-header" style="height: 10px"></header>
<section class="el-container">
<aside class="el-aside" style="width: 20px"></aside>
<section class="el-container is-vertical">
<main class="el-main"></main>
</section>
</section>
</section>
<div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': getThemeConfig.layout === 'classic' }">
<div class="layout-tips-box">
<p class="layout-tips-txt">{{ $t('message.layout.sixClassic') }}</p>
</div>
</div>
</div>
<!-- transverse 布局 -->
<div class="layout-drawer-content-item" @click="onSetLayout('transverse')">
<section class="el-container is-vertical el-circular" :class="{ 'drawer-layout-active': getThemeConfig.layout === 'transverse' }">
<header class="el-header" style="height: 10px"></header>
<section class="el-container">
<section class="el-container is-vertical">
<main class="el-main"></main>
</section>
</section>
</section>
<div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': getThemeConfig.layout === 'transverse' }">
<div class="layout-tips-box">
<p class="layout-tips-txt">{{ $t('message.layout.sixTransverse') }}</p>
</div>
</div>
</div>
<!-- columns 布局 -->
<div class="layout-drawer-content-item" @click="onSetLayout('columns')">
<section class="el-container el-circular" :class="{ 'drawer-layout-active': getThemeConfig.layout === 'columns' }">
<aside class="el-aside-dark" style="width: 10px"></aside>
<aside class="el-aside" style="width: 20px"></aside>
<section class="el-container is-vertical">
<header class="el-header" style="height: 10px"></header>
<main class="el-main"></main>
</section>
</section>
<div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': getThemeConfig.layout === 'columns' }">
<div class="layout-tips-box">
<p class="layout-tips-txt">{{ $t('message.layout.sixColumns') }}</p>
</div>
</div>
</div>
</div>
<div class="copy-config">
<el-alert :title="$t('message.layout.tipText')" type="warning" :closable="false"> </el-alert>
<el-button
size="small"
class="copy-config-btn"
icon="el-icon-document-copy"
type="primary"
ref="copyConfigBtnRef"
@click="onCopyConfigClick"
>{{ $t('message.layout.copyText') }}
</el-button>
<el-button size="small" class="copy-config-btn-reset" type="info" icon="el-icon-refresh-right" @click="onResetConfigClick">
{{ $t('message.layout.resetText') }}
</el-button>
</div>
</el-scrollbar>
</el-drawer>
</div>
</template>
<script>
import ClipboardJS from 'clipboard';
import { Local } from '@/utils/storage.js';
import { useChangeColor } from '@/utils/theme.js';
import config from '/package.json';
export default {
name: 'layoutBreadcrumbSeting',
computed: {
// 获取布局配置信息
getThemeConfig() {
return this.$store.state.themeConfig.themeConfig;
},
},
created() {
// 判断当前布局是否不相同,不相同则初始化当前布局的样式,防止监听窗口大小改变时,布局配置logo、菜单背景等部分布局失效问题
if (!Local.get('frequency')) this.initSetLayoutChange();
Local.set('frequency', 1);
// 监听窗口大小改变,非默认布局,设置成默认布局(适配移动端)
this.bus.$on('layoutMobileResize', (res) => {
if (this.$store.state.themeConfig.themeConfig.layout === res.layout) return false;
this.$store.state.themeConfig.themeConfig.layout = res.layout;
this.$store.state.themeConfig.themeConfig.isDrawer = false;
this.$store.state.themeConfig.themeConfig.isCollapse = false;
this.initSetLayoutChange();
});
},
mounted() {
this.initLayoutConfig();
},
methods: {
// 全局主题
onColorPickerChange() {
if (!this.getThemeConfig.primary) return;
// 颜色加深
document.documentElement.style.setProperty('--prev-color-primary', this.getThemeConfig.primary);
// 颜色变浅
for (let i = 1; i <= 9; i++) {
document.documentElement.style.setProperty(
`--prev-color-primary-light-${i}`,
`${useChangeColor().getLightColor(this.getThemeConfig.primary, i / 10)}`
);
}
this.setLocalThemeConfig();
},
// 深色模式
onAddDarkChange() {
const body = document.documentElement;
if (this.getThemeConfig.isIsDark) body.setAttribute('data-theme', 'dark');
else body.setAttribute('data-theme', '');
this.setLocalThemeConfig();
},
// 初始化:刷新页面时,设置了值,直接取缓存中的值进行初始化
initLayoutConfig() {
window.addEventListener('load', () => {
// 默认样式
this.onColorPickerChange();
// 灰色模式
if (this.$store.state.themeConfig.themeConfig.isGrayscale) this.onAddFilterChange('grayscale');
// 色弱模式
if (this.$store.state.themeConfig.themeConfig.isInvert) this.onAddFilterChange('invert');
// 深色模式
if (this.$store.state.themeConfig.themeConfig.isIsDark) this.onAddDarkChange();
// 语言国际化
if (Local.get('themeConfigPrev')) this.$i18n.locale = Local.get('themeConfigPrev').globalI18n;
});
},
// 存储布局配置
setLocalThemeConfig() {
Local.remove('themeConfigPrev');
Local.set('themeConfigPrev', this.$store.state.themeConfig.themeConfig);
this.setLocalThemeConfigStyle();
},
// 存储布局配置全局主题样式(html根标签)
setLocalThemeConfigStyle() {
Local.set('themeConfigStyle', document.documentElement.style.cssText);
},
// 布局配置弹窗打开
openDrawer() {
this.$store.state.themeConfig.themeConfig.isDrawer = true;
},
// 关闭弹窗时,初始化变量
onDrawerClose() {
this.$store.state.themeConfig.themeConfig.isDrawer = false;
this.setLocalThemeConfig();
},
// 灰色模式/色弱模式
onAddFilterChange(attr) {
if (attr === 'grayscale') {
if (this.$store.state.themeConfig.themeConfig.isGrayscale) this.$store.state.themeConfig.themeConfig.isInvert = false;
} else {
if (this.$store.state.themeConfig.themeConfig.isInvert) this.$store.state.themeConfig.themeConfig.isGrayscale = false;
}
const cssAttr =
attr === 'grayscale'
? `grayscale(${this.$store.state.themeConfig.themeConfig.isGrayscale ? 1 : 0})`
: `invert(${this.$store.state.themeConfig.themeConfig.isInvert ? '80%' : '0%'})`;
const appEle = document.body;
appEle.setAttribute('style', `filter: ${cssAttr};`);
this.setLocalThemeConfig();
},
// 布局切换
onSetLayout(layout) {
Local.set('oldLayout', layout);
if (this.$store.state.themeConfig.themeConfig.layout === layout) return false;
this.$store.state.themeConfig.themeConfig.layout = layout;
this.$store.state.themeConfig.themeConfig.isDrawer = false;
this.initSetLayoutChange();
},
// 设置布局切换,重置主题样式
initSetLayoutChange() {
if (this.$store.state.themeConfig.themeConfig.layout === 'classic') {
this.onBgColorPickerChange('menuBar', '#ffffff');
this.onBgColorPickerChange('menuBarColor', '#606266');
this.onBgColorPickerChange('topBar', '#ffffff');
this.onBgColorPickerChange('topBarColor', '#606266');
} else if (this.$store.state.themeConfig.themeConfig.layout === 'transverse') {
this.onBgColorPickerChange('menuBarColor', '#ffffff');
this.onBgColorPickerChange('topBar', '#545c64');
this.onBgColorPickerChange('topBarColor', '#ffffff');
} else if (this.$store.state.themeConfig.themeConfig.layout === 'columns') {
this.onBgColorPickerChange('menuBar', '#ffffff');
this.onBgColorPickerChange('menuBarColor', '#606266');
this.onBgColorPickerChange('topBar', '#ffffff');
this.onBgColorPickerChange('topBarColor', '#606266');
} else {
this.onBgColorPickerChange('menuBar', '#545c64');
this.onBgColorPickerChange('menuBarColor', '#eaeaea');
this.onBgColorPickerChange('topBar', '#ffffff');
this.onBgColorPickerChange('topBarColor', '#606266');
}
},
// 菜单 / 顶栏背景等
onBgColorPickerChange(bg, rgb) {
document.documentElement.style.setProperty(`--prev-bg-${bg}`, rgb);
this.setLocalThemeConfigStyle();
},
// 一键复制配置
onCopyConfigClick() {
this.$store.state.themeConfig.themeConfig.isDrawer = false;
let clipboardJS = new ClipboardJS('.copy-config-btn', {
text: () => JSON.stringify(this.$store.state.themeConfig.themeConfig),
});
clipboardJS.on('success', () => {
this.$message.success('配置复制成功');
this.isDrawer = false;
clipboardJS.destroy();
});
clipboardJS.on('error', () => {
this.$message.error('配置复制失败');
});
},
// 一键恢复默认
onResetConfigClick() {
Local.clear();
window.location.reload();
Local.set('version', config.version);
},
},
};
</script>
<style scoped lang="scss">
.layout-breadcrumb-seting-bar {
height: calc(100vh - 50px);
padding: 0 15px;
::v-deep .el-scrollbar__view {
overflow-x: hidden !important;
}
.layout-breadcrumb-seting-bar-flex {
display: flex;
align-items: center;
&-label {
flex: 1;
color: var(--prev-color-text-primary);
}
}
.layout-drawer-content-flex {
overflow: hidden;
display: flex;
flex-wrap: wrap;
align-content: flex-start;
margin: 0 -5px;
.layout-drawer-content-item {
width: 50%;
height: 70px;
cursor: pointer;
border: 1px solid transparent;
position: relative;
padding: 5px;
.el-container {
height: 100%;
.el-aside-dark {
background-color: var(--prev-color-seting-header);
}
.el-aside {
background-color: var(--prev-color-seting-aside);
}
.el-header {
background-color: var(--prev-color-seting-header);
}
.el-main {
background-color: var(--prev-color-seting-main);
}
}
.el-circular {
border-radius: 2px;
overflow: hidden;
border: 1px solid transparent;
transition: all 0.3s ease-in-out;
}
.drawer-layout-active {
border: 1px solid;
border-color: var(--prev-color-primary);
}
.layout-tips-warp,
.layout-tips-warp-active {
transition: all 0.3s ease-in-out;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
border: 1px solid;
border-color: var(--prev-color-primary-light-5);
border-radius: 100%;
padding: 4px;
.layout-tips-box {
transition: inherit;
width: 30px;
height: 30px;
z-index: 9;
border: 1px solid;
border-color: var(--prev-color-primary-light-5);
border-radius: 100%;
.layout-tips-txt {
transition: inherit;
position: relative;
top: 5px;
font-size: 12px;
line-height: 1;
letter-spacing: 2px;
white-space: nowrap;
color: var(--prev-color-primary-light-5);
text-align: center;
transform: rotate(30deg);
left: -1px;
background-color: var(--prev-color-seting-main);
width: 32px;
height: 17px;
line-height: 17px;
}
}
}
.layout-tips-warp-active {
border: 1px solid;
border-color: var(--prev-color-primary);
.layout-tips-box {
border: 1px solid;
border-color: var(--prev-color-primary);
.layout-tips-txt {
color: var(--prev-color-primary) !important;
background-color: var(--prev-color-seting-main) !important;
}
}
}
&:hover {
.el-circular {
transition: all 0.3s ease-in-out;
border: 1px solid;
border-color: var(--prev-color-primary);
}
.layout-tips-warp {
transition: all 0.3s ease-in-out;
border-color: var(--prev-color-primary);
.layout-tips-box {
transition: inherit;
border-color: var(--prev-color-primary);
.layout-tips-txt {
transition: inherit;
color: var(--prev-color-primary) !important;
background-color: var(--prev-color-seting-main) !important;
}
}
}
}
}
}
.copy-config {
margin: 10px 0;
.copy-config-btn {
width: 100%;
margin-top: 15px;
}
.copy-config-btn-reset {
width: 100%;
margin: 10px 0 0;
}
}
}
</style>
+323
View File
@@ -0,0 +1,323 @@
<template>
<div class="layout-navbars-breadcrumb-user" :style="{ flex: layoutUserFlexNum }">
<el-dropdown
:show-timeout="70"
:hide-timeout="50"
trigger="click"
@command="onComponentSizeChange"
>
<div class="layout-navbars-breadcrumb-user-icon">
<i class="iconfont icon-ziti" :title="$t('message.user.title0')"></i>
</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="" :disabled="disabledSize === ''">{{
$t("message.user.dropdownDefault")
}}</el-dropdown-item>
<el-dropdown-item command="medium" :disabled="disabledSize === 'medium'">{{
$t("message.user.dropdownMedium")
}}</el-dropdown-item>
<el-dropdown-item command="small" :disabled="disabledSize === 'small'">{{
$t("message.user.dropdownSmall")
}}</el-dropdown-item>
<el-dropdown-item command="mini" :disabled="disabledSize === 'mini'">{{
$t("message.user.dropdownMini")
}}</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-dropdown
:show-timeout="70"
:hide-timeout="50"
trigger="click"
@command="onLanguageChange"
>
<div class="layout-navbars-breadcrumb-user-icon">
<i
class="iconfont"
:class="disabledI18n === 'en' ? 'icon-fuhao-yingwen' : 'icon-fuhao-zhongwen'"
:title="$t('message.user.title1')"
></i>
</div>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="zh-cn" :disabled="disabledI18n === 'zh-cn'"
>简体中文</el-dropdown-item
>
<el-dropdown-item command="en" :disabled="disabledI18n === 'en'"
>English</el-dropdown-item
>
<el-dropdown-item command="zh-tw" :disabled="disabledI18n === 'zh-tw'"
>繁體中文</el-dropdown-item
>
</el-dropdown-menu>
</el-dropdown>
<div class="layout-navbars-breadcrumb-user-icon" @click="onSearchClick">
<i class="el-icon-search" :title="$t('message.user.title2')"></i>
</div>
<div class="layout-navbars-breadcrumb-user-icon" @click="onLayoutSetingClick">
<i class="icon-skin iconfont" :title="$t('message.user.title3')"></i>
</div>
<div class="layout-navbars-breadcrumb-user-icon">
<el-popover
placement="bottom"
trigger="click"
v-model="isShowUserNewsPopover"
:width="300"
popper-class="el-popover-pupop-user-news"
>
<el-badge
:is-dot="true"
@click.stop="isShowUserNewsPopover = !isShowUserNewsPopover"
slot="reference"
>
<i class="el-icon-bell" :title="$t('message.user.title4')"></i>
</el-badge>
<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 ? $t('message.user.title6') : $t('message.user.title5')"
:class="!isScreenfull ? 'icon-fullscreen' : 'icon-tuichuquanping'"
></i>
</div>
<el-dropdown :show-timeout="70" :hide-timeout="50" @command="onDropdownCommand">
<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>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="/home">{{
$t("message.user.dropdown1")
}}</el-dropdown-item>
<el-dropdown-item command="wareHouse">{{
$t("message.user.dropdown6")
}}</el-dropdown-item>
<el-dropdown-item command="/personal">{{
$t("message.user.dropdown2")
}}</el-dropdown-item>
<el-dropdown-item command="/404">{{
$t("message.user.dropdown3")
}}</el-dropdown-item>
<el-dropdown-item command="/401">{{
$t("message.user.dropdown4")
}}</el-dropdown-item>
<el-dropdown-item divided command="logOut">{{
$t("message.user.dropdown5")
}}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<Search ref="searchRef" />
</div>
</template>
<script>
import screenfull from "screenfull";
import { Session, Local } from "@/utils/storage.js";
import UserNews from "@/layout/navBars/breadcrumb/userNews.vue";
import Search from "@/layout/navBars/breadcrumb/search.vue";
export default {
name: "layoutBreadcrumbUser",
components: { UserNews, Search },
data() {
return {
isScreenfull: false,
isShowUserNewsPopover: false,
disabledI18n: "zh-cn",
disabledSize: "",
};
},
computed: {
// 获取用户信息
getUserInfos() {
return this.$store.state.userInfos.userInfos;
},
// 设置弹性盒子布局 flex
layoutUserFlexNum() {
let { layout, isClassicSplitMenu } = this.$store.state.themeConfig.themeConfig;
let num = "";
if (
layout === "defaults" ||
(layout === "classic" && !isClassicSplitMenu) ||
layout === "columns"
)
num = 1;
else num = null;
return num;
},
},
mounted() {
if (Local.get("themeConfigPrev")) {
this.initI18n();
this.initComponentSize();
}
},
methods: {
// 搜索点击
onSearchClick() {
this.$refs.searchRef.openSearch();
},
// 布局配置点击
onLayoutSetingClick() {
this.bus.$emit("openSetingsDrawer");
},
// 全屏点击
onScreenfullClick() {
if (!screenfull.isEnabled) {
this.$message.warning("暂不不支持全屏");
return false;
}
screenfull.toggle();
screenfull.on("change", () => {
if (screenfull.isFullscreen) this.isScreenfull = true;
else this.isScreenfull = false;
});
// 监听菜单 horizontal.vue 滚动条高度更新
this.bus.$emit("updateElScrollBar");
},
// 组件大小改变
onComponentSizeChange(size) {
Local.remove("themeConfigPrev");
this.$store.state.themeConfig.themeConfig.globalComponentSize = size;
Local.set("themeConfigPrev", this.$store.state.themeConfig.themeConfig);
this.$ELEMENT.size = size;
this.initComponentSize();
window.location.reload();
},
// 语言切换
onLanguageChange(lang) {
Local.remove("themeConfigPrev");
this.$store.state.themeConfig.themeConfig.globalI18n = lang;
Local.set("themeConfigPrev", this.$store.state.themeConfig.themeConfig);
this.$i18n.locale = lang;
this.initI18n();
},
// 初始化言语国际化
initI18n() {
switch (Local.get("themeConfigPrev").globalI18n) {
case "zh-cn":
this.disabledI18n = "zh-cn";
break;
case "en":
this.disabledI18n = "en";
break;
case "zh-tw":
this.disabledI18n = "zh-tw";
break;
}
},
// 初始化全局组件大小
initComponentSize() {
switch (Local.get("themeConfigPrev").globalComponentSize) {
case "":
this.disabledSize = "";
break;
case "medium":
this.disabledSize = "medium";
break;
case "small":
this.disabledSize = "small";
break;
case "mini":
this.disabledSize = "mini";
break;
}
},
// `dropdown 下拉菜单` 当前项点击
onDropdownCommand(path) {
if (path === "logOut") {
setTimeout(() => {
this.$msgbox({
closeOnClickModal: false,
closeOnPressEscape: false,
title: this.$t("message.user.logOutTitle"),
message: this.$t("message.user.logOutMessage"),
showCancelButton: true,
confirmButtonText: this.$t("message.user.logOutConfirm"),
cancelButtonText: this.$t("message.user.logOutCancel"),
beforeClose: (action, instance, done) => {
if (action === "confirm") {
instance.confirmButtonLoading = true;
instance.confirmButtonText = this.$t("message.user.logOutExit");
setTimeout(() => {
done();
setTimeout(() => {
instance.confirmButtonLoading = false;
}, 300);
}, 700);
} else {
done();
}
},
})
.then(() => {
// 清除缓存/token等
Session.clear();
// 使用 reload 时,不需要调用 resetRoute() 重置路由
window.location.reload();
})
.catch(() => {});
}, 150);
} else if (path === "wareHouse") {
window.open("https://gitee.com/lyt-top/vue-next-admin");
} else {
this.$router.push(path);
}
},
},
};
</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(--prev-bg-topBarColor);
height: 50px;
line-height: 50px;
display: flex;
align-items: center;
&:hover {
background: var(--prev-color-hover);
i {
display: inline-block;
animation: logoAnimation 0.3s ease-in-out;
}
}
}
& ::v-deep .el-dropdown {
color: var(--prev-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>
+130
View File
@@ -0,0 +1,130 @@
<template>
<div class="layout-navbars-breadcrumb-user-news">
<div class="head-box">
<div class="head-box-title">{{ $t("message.user.newTitle") }}</div>
<div class="head-box-btn" v-if="newsList.length > 0" @click="onAllReadClick">
{{ $t("message.user.newBtn") }}
</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>
<div class="content-box-empty" v-else>
<div class="content-box-empty-margin">
<i class="el-icon-s-promotion"></i>
<div class="mt15">{{ $t("message.user.newDesc") }}</div>
</div>
</div>
</div>
<div class="foot-box" @click="onGoToGiteeClick" v-if="newsList.length > 0">
{{ $t("message.user.newGo") }}
</div>
</div>
</template>
<script>
export default {
name: "layoutBreadcrumbUserNews",
data() {
return {
newsList: [
{
label: "暂无",
value: "暂无",
time: "2023-8-15",
},
{
label: "暂无",
value: "暂无",
time: "2023-8-15",
},
],
};
},
methods: {
// 全部已读点击
onAllReadClick() {
this.newsList = [];
},
// 前往通知中心点击
onGoToGiteeClick() {
window.open("https://www.baidu.com/");
},
},
};
</script>
<style scoped lang="scss">
.layout-navbars-breadcrumb-user-news {
.head-box {
display: flex;
border-bottom: 1px solid var(--prev-border-color-lighter);
box-sizing: border-box;
color: var(--prev-color-text-primary);
justify-content: space-between;
height: 35px;
align-items: center;
.head-box-btn {
color: var(--prev-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: var(--prev-color-text-secondary);
margin-top: 5px;
margin-bottom: 5px;
}
.content-box-time {
color: var(--prev-color-text-secondary);
}
}
.content-box-empty {
height: 260px;
display: flex;
.content-box-empty-margin {
margin: auto;
text-align: center;
i {
font-size: 60px;
}
}
}
}
.foot-box {
height: 35px;
color: var(--prev-color-primary);
font-size: 13px;
cursor: pointer;
opacity: 0.8;
display: flex;
align-items: center;
justify-content: center;
border-top: 1px solid var(--prev-border-color-lighter);
&:hover {
opacity: 1;
}
}
::v-deep(.el-empty__description p) {
font-size: 13px;
}
}
</style>
+34
View File
@@ -0,0 +1,34 @@
<template>
<div class="layout-navbars-container">
<BreadcrumbIndex />
<TagsView v-if="setShowTagsView" />
</div>
</template>
<script>
import BreadcrumbIndex from '@/layout/navBars/breadcrumb/index.vue';
import TagsView from '@/layout/navBars/tagsView/tagsView.vue';
export default {
name: 'layoutNavBars',
components: { BreadcrumbIndex, TagsView },
data() {
return {};
},
computed: {
// 设置是否显示 tagsView
setShowTagsView() {
let { layout, isTagsview } = this.$store.state.themeConfig.themeConfig;
return layout !== 'classic' && isTagsview;
},
},
};
</script>
<style scoped lang="scss">
.layout-navbars-container {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
</style>
+110
View File
@@ -0,0 +1,110 @@
<template>
<div>
<transition name="el-zoom-in-center">
<ul
class="el-dropdown-menu el-popper el-dropdown-menu--medium custom-contextmenu"
:style="`top: ${dropdowns.y}px;left: ${dropdowns.x}px;`"
x-placement="bottom-end"
id="contextmenu"
v-show="isShow"
>
<li class="el-dropdown-menu__item" v-for="(v, k) in dropdownList" :key="k" @click="onCurrentContextmenuClick(v.id)">
<template v-if="!v.affix">
<i :class="v.icon"></i>
<span>{{ $t(v.txt) }}</span>
</template>
</li>
<div x-arrow class="popper__arrow" :style="{ left: `${arrowLeft}px` }"></div>
</ul>
</transition>
</div>
</template>
<script>
export default {
name: 'layoutTagsViewContextmenu',
props: {
dropdown: {
type: Object,
},
},
data() {
return {
isShow: false,
dropdownList: [
{ id: 0, txt: 'message.tagsView.refresh', affix: false, icon: 'el-icon-refresh-right' },
{ id: 1, txt: 'message.tagsView.close', affix: false, icon: 'el-icon-close' },
{ id: 2, txt: 'message.tagsView.closeOther', affix: false, icon: 'el-icon-circle-close' },
{ id: 3, txt: 'message.tagsView.closeAll', affix: false, icon: 'el-icon-folder-delete' },
],
path: {},
arrowLeft: 5,
};
},
computed: {
dropdowns() {
// 99 为 `Dropdown 下拉菜单` 的宽度
if (this.dropdown.x + 99 > document.documentElement.clientWidth) {
return {
x: document.documentElement.clientWidth - 99 - 5,
y: this.dropdown.y,
};
} else {
return this.dropdown;
}
},
},
mounted() {
// 监听页面监听进行右键菜单的关闭
document.body.addEventListener('click', this.closeContextmenu);
},
methods: {
// 当前项菜单点击
onCurrentContextmenuClick(id) {
this.$emit('currentContextmenuClick', { id, path: this.path });
},
// 打开右键菜单:判断是否固定,固定则不显示关闭按钮
openContextmenu(item) {
this.path = item.path;
item.meta.isAffix ? (this.dropdownList[1].affix = true) : (this.dropdownList[1].affix = false);
this.closeContextmenu();
setTimeout(() => {
this.isShow = true;
}, 80);
},
// 关闭右键菜单
closeContextmenu() {
this.isShow = false;
},
},
destroyed() {
// 页面卸载时,移除右键菜单监听事件
document.body.removeEventListener('click', this.closeContextmenu);
},
// 监听下拉菜单位置
watch: {
dropdown: {
handler({ x }) {
if (x + 99 > document.documentElement.clientWidth) this.arrowLeft = 99 - (document.documentElement.clientWidth - x);
else this.arrowLeft = 10;
},
deep: true,
},
},
};
</script>
<style scoped lang="scss">
.custom-contextmenu {
transform-origin: center top;
z-index: 2190;
position: fixed;
.el-dropdown-menu__item {
font-size: 12px !important;
white-space: nowrap;
i {
font-size: 12px !important;
}
}
}
</style>
+406
View File
@@ -0,0 +1,406 @@
<template>
<div class="layout-navbars-tagsview">
<el-scrollbar ref="scrollbarRef" @wheel.native.prevent="onHandleScroll">
<ul class="layout-navbars-tagsview-ul" :class="setTagsStyle" ref="tagsUlRef">
<li
v-for="(v, k) in tagsViewList"
:key="k"
class="layout-navbars-tagsview-ul-li"
:data-name="v.name"
:class="{ 'is-active': v.path === tagsRoutePath }"
@contextmenu.prevent="onContextmenu(v, $event)"
@click="onTagsClick(v, k)"
ref="tagsRefs"
>
<i class="iconfont icon-webicon318 layout-navbars-tagsview-ul-li-iconfont font14" v-if="v.path === tagsRoutePath"></i>
<i
class="layout-navbars-tagsview-ul-li-iconfont font14 is-tagsview-icon"
:class="v.meta.icon"
v-if="v.path !== tagsRoutePath && getThemeConfig.isTagsviewIcon"
></i>
<span>{{ $t(v.meta.title) }}</span>
<i
class="el-icon-refresh-right layout-navbars-tagsview-ul-li-icon ml5"
v-if="v.path === tagsRoutePath"
@click.stop="refreshCurrentTagsView(v.path)"
></i>
<i class="el-icon-close layout-navbars-tagsview-ul-li-icon ml5" v-if="!v.meta.isAffix" @click.stop="closeCurrentTagsView(v.path)"></i>
</li>
</ul>
</el-scrollbar>
<Contextmenu :dropdown="tagsDropdown" ref="tagsContextmenu" @currentContextmenuClick="onCurrentContextmenuClick" />
</div>
</template>
<script>
import Contextmenu from '@/layout/navBars/tagsView/contextmenu';
import { Session } from '@/utils/storage.js';
export default {
name: 'tagsView',
components: { Contextmenu },
data() {
return {
userInfo: {},
tagsViewList: [],
tagsDropdown: {
x: '',
y: '',
},
tagsRefsIndex: 0,
tagsRoutePath: this.$route.path,
tagsViewRoutesList: [],
};
},
computed: {
// 获取布局配置信息
getThemeConfig() {
return this.$store.state.themeConfig.themeConfig;
},
// 动态设置 tagsView 风格样式
setTagsStyle() {
return this.$store.state.themeConfig.themeConfig.tagsStyle;
},
},
created() {
// 监听非本页面调用 0 刷新当前,1 关闭当前,2 关闭其它,3 关闭全部
this.bus.$on('onCurrentContextmenuClick', (data) => {
this.onCurrentContextmenuClick(data);
});
},
mounted() {
this.getTagsViewRoutes();
},
methods: {
// 获取路由信息
getRoutesList() {
return this.$store.state.routesList.routesList;
},
// 当前的 tagsView 项点击时
onTagsClick(v, k) {
this.tagsRoutePath = v.path;
this.tagsRefsIndex = k;
this.$router.push(v);
},
// 获取 tagsView 的下标:用于处理 tagsView 点击时的横向滚动
getTagsRefsIndex(path) {
if (this.tagsViewList.length > 0) {
this.tagsRefsIndex = this.tagsViewList.findIndex((item) => item.path === path);
}
},
// 鼠标滚轮滚动
onHandleScroll(e) {
this.$refs.scrollbarRef.$refs.wrap.scrollLeft += e.wheelDelta / 4;
},
// tagsView 横向滚动
tagsViewmoveToCurrentTag() {
this.$nextTick(() => {
const tagsRefs = this.$refs.tagsRefs;
if (tagsRefs.length <= 0) return false;
// 当前 li 元素
let liDom = tagsRefs[this.tagsRefsIndex];
// 当前 li 元素下标
let liIndex = this.tagsRefsIndex;
// 当前 ul 下 li 元素总长度
let liLength = tagsRefs.length;
// 最前 li
let liFirst = tagsRefs[0];
// 最后 li
let liLast = tagsRefs[tagsRefs.length - 1];
// 当前滚动条的值
let scrollRefs = this.$refs.scrollbarRef.$refs.wrap;
// 当前滚动条滚动宽度
let scrollS = scrollRefs.scrollWidth;
// 当前滚动条偏移宽度
let offsetW = scrollRefs.offsetWidth;
// 当前滚动条偏移距离
let scrollL = scrollRefs.scrollLeft;
// 上一个 tags li dom
let liPrevTag = tagsRefs[this.tagsRefsIndex - 1];
// 下一个 tags li dom
let liNextTag = tagsRefs[this.tagsRefsIndex + 1];
// 上一个 tags li dom 的偏移距离
let beforePrevL = '';
// 下一个 tags li dom 的偏移距离
let afterNextL = '';
if (liDom === liFirst) {
// 头部
scrollRefs.scrollLeft = 0;
} else if (liDom === liLast) {
// 尾部
scrollRefs.scrollLeft = scrollS - offsetW;
} else {
// 非头/尾部
if (liIndex === 0) beforePrevL = liFirst?.offsetLeft - 5;
else beforePrevL = liPrevTag?.offsetLeft - 5;
if (liIndex === liLength) afterNextL = liLast?.offsetLeft + liLast.offsetWidth + 5;
else afterNextL = liNextTag?.offsetLeft + liNextTag.offsetWidth + 5;
if (afterNextL > scrollL + offsetW) {
scrollRefs.scrollLeft = afterNextL - offsetW;
} else if (beforePrevL < scrollL) {
scrollRefs.scrollLeft = beforePrevL;
}
}
// 更新滚动条,防止不出现
this.updateScrollbar();
});
},
// 更新滚动条显示
updateScrollbar() {
this.$refs.scrollbarRef.update();
},
// 递归查找当前路径下的组件信息
filterCurrentMenu(arr, currentPath, callback) {
arr.map((item) => {
if (item.path === currentPath) {
callback(item);
return false;
}
item = Object.assign({}, item);
if (item.children) {
item.children = this.filterCurrentMenu(item.children, currentPath, callback);
}
});
},
// 数组对象去重
duplicate(arr) {
let newobj = {};
arr = arr.reduce((preVal, curVal) => {
newobj[curVal.path] ? '' : (newobj[curVal.path] = preVal.push(curVal));
return preVal;
}, []);
return arr;
},
// 获取 vuex 中的 tagsViewRoutes 列表
getTagsViewRoutes() {
this.tagsRoutePath = this.$route.path;
this.tagsViewList = [];
if (!this.$store.state.themeConfig.themeConfig.isCacheTagsView) Session.remove('tagsViewList');
this.tagsViewRoutesList = this.$store.state.tagsViewRoutes.tagsViewRoutes;
this.initTagsViewList();
},
// 存储 tagsViewList 到浏览器临时缓存中,页面刷新时,保留记录
addBrowserSetSession(tagsViewList) {
Session.set('tagsViewList', tagsViewList);
},
// 初始化设置了 tagsView 数据
initTagsViewList() {
if (Session.get('tagsViewList') && this.$store.state.themeConfig.themeConfig.isCacheTagsView) {
this.tagsViewList = Session.get('tagsViewList');
} else {
this.tagsViewRoutesList.map((v) => {
if (v.meta.isAffix && !v.meta.isHide) this.tagsViewList.push({ ...v });
});
this.addTagsView(this.$route.path);
}
// 初始化当前元素(li)的下标
this.getTagsRefsIndex(this.$route.path);
// 添加初始化横向滚动条移动到对应位置
this.tagsViewmoveToCurrentTag();
},
// 添加 tagsView:未设置隐藏(isHide)也添加到在 tagsView 中
addTagsView(path, to) {
if (this.tagsViewList.some((v) => v.path === path)) return false;
const item = this.tagsViewRoutesList.find((v) => v.path === path);
if (item.meta.isLink && !item.meta.isIframe) return false;
item.query = to?.query ? to?.query : this.$route.query;
this.tagsViewList.push({ ...item });
this.addBrowserSetSession(this.tagsViewList);
},
// 右键菜单点击时显示菜单列表
onContextmenu(v, e) {
let { clientX, clientY } = e;
this.tagsDropdown.x = clientX;
this.tagsDropdown.y = clientY;
this.$refs.tagsContextmenu.openContextmenu(v);
},
// 当前项右键菜单点击
onCurrentContextmenuClick(data) {
let { id, path } = data;
let currentTag = this.tagsViewList.find((v) => v.path === path);
switch (id) {
case 0:
this.refreshCurrentTagsView(path);
this.$router.push({ path, query: currentTag.query });
console.log('======================')
break;
case 1:
this.closeCurrentTagsView(path);
break;
case 2:
this.$router.push({ path, query: currentTag.query });
this.closeOtherTagsView(path);
break;
case 3:
this.closeAllTagsView(path);
break;
}
},
// 1、刷新当前 tagsView
refreshCurrentTagsView(path) {
console.log('刷新当前 tagsView', path);
this.bus.$emit('onTagsViewRefreshRouterView', path);
},
// 2、关闭当前 tagsView:当前项 `tags-view` icon 关闭时点击,如果是设置了固定的(isAffix),不可以关闭
closeCurrentTagsView(path) {
this.tagsViewList.map((v, k, arr) => {
if (!v.meta.isAffix) {
if (v.path === path) {
this.tagsViewList.splice(k, 1);
setTimeout(() => {
// 最后一个
if (this.tagsViewList.length === k) this.$router.push({ path: arr[arr.length - 1].path, query: arr[arr.length - 1].query });
// 否则,跳转到下一个
else this.$router.push({ path: arr[k].path, query: arr[k].query });
}, 0);
}
}
});
this.addBrowserSetSession(this.tagsViewList);
},
// 3、关闭其它 tagsView:如果是设置了固定的(isAffix),不进行关闭
closeOtherTagsView(path) {
this.tagsViewList = [];
this.tagsViewRoutesList.map((v) => {
if (v.meta.isAffix && !v.meta.isHide) this.tagsViewList.push({ ...v });
});
this.addTagsView(path);
},
// 4、关闭全部 tagsView:如果是设置了固定的(isAffix),不进行关闭
closeAllTagsView(path) {
this.tagsViewList = [];
this.tagsViewRoutesList.map((v) => {
if (v.meta.isAffix && !v.meta.isHide) {
this.tagsViewList.push({ ...v });
if (this.tagsViewList.some((v) => v.path === path)) this.$router.push({ path, query: this.$route.query });
else this.$router.push({ path: v.path, query: this.$route.query });
}
});
this.addBrowserSetSession(this.tagsViewList);
},
},
watch: {
// 监听路由变化
$route: {
handler(to) {
this.tagsRoutePath = to.path;
this.addTagsView(to.path, to);
this.getTagsRefsIndex(to.path);
this.tagsViewmoveToCurrentTag();
},
deep: true,
},
},
destroyed() {
// 取消非本页面调用监听(fun/tagsView
this.bus.$off('onCurrentContextmenuClick');
},
};
</script>
<style scoped lang="scss">
.layout-navbars-tagsview {
flex: 1;
background-color: var(--prev-bg-white);
border-bottom: 1px solid var(--prev-border-color-lighter);
& ::v-deep .is-vertical {
display: none !important;
}
&-ul {
list-style: none;
margin: 0;
padding: 0;
width: 100%;
height: 34px;
display: flex;
align-items: center;
white-space: nowrap;
color: var(--prev-color-text-regular);
font-size: 12px;
padding: 0 15px;
&-li {
height: 26px;
line-height: 26px;
display: flex;
align-items: center;
border: 1px solid var(--prev-border-color-lighter);
padding: 0 12px 0 15px;
margin-right: 5px;
border-radius: 2px;
position: relative;
z-index: 0;
cursor: pointer;
justify-content: space-between;
transition: all 0.3s cubic-bezier(0.2, 1, 0.3, 1);
&::before {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: var(--prev-color-primary);
z-index: -1;
opacity: 0;
transform: scale3d(0.7, 1, 1);
transition: transform 0.3s, opacity 0.3s;
transition-timing-function: cubic-bezier(0.2, 1, 0.3, 1);
}
&:hover {
color: var(--prev-color-text-white);
transition: all 0.3s cubic-bezier(0.2, 1, 0.3, 1);
border-color: transparent;
&::before {
opacity: 1;
transform: translate3d(0, 0, 0);
border-radius: 2px;
}
.is-tagsview-icon {
color: var(--prev-color-text-white);
transition: all 0.3s cubic-bezier(0.2, 1, 0.3, 1);
}
}
&-iconfont {
position: relative;
left: -5px;
top: 1px;
color: var(--prev-color-text-white);
}
&-icon {
border-radius: 100%;
position: relative;
height: 14px;
width: 14px;
text-align: center;
line-height: 14px;
top: 1px;
}
.is-tagsview-icon {
color: var(--prev-color-text-regular);
transition: all 0.3s cubic-bezier(0.2, 1, 0.3, 1);
}
}
.is-active {
color: var(--prev-color-text-white);
transition: all 0.3s cubic-bezier(0.2, 1, 0.3, 1);
border-color: transparent;
&::before {
opacity: 1;
transform: translate3d(0, 0, 0);
border-radius: 2px;
}
}
}
& ::-webkit-scrollbar {
display: none !important;
}
// // 风格2
// .tags-style-two {
// }
// // 风格3
// .tags-style-three {
// }
// // 风格4
// .tags-style-four {
// }
}
</style>
+138
View File
@@ -0,0 +1,138 @@
<template>
<div class="el-menu-horizontal-warp">
<el-scrollbar @wheel.native.prevent="onElMenuHorizontalScroll" ref="elMenuHorizontalScrollRef">
<el-menu router :default-active="defaultActive" background-color="transparent" mode="horizontal" @select="onHorizontalSelect">
<template v-for="val in menuList">
<el-submenu :index="val.path" v-if="val.children && val.children.length > 0" :key="val.path">
<template slot="title">
<i :class="val.meta.icon ? val.meta.icon : ''"></i>
<span>{{ $t(val.meta.title) }}</span>
</template>
<SubItem :chil="val.children" />
</el-submenu>
<template v-else>
<el-menu-item :index="val.path" :key="val.path">
<template slot="title" v-if="!val.meta.isLink || (val.meta.isLink && val.meta.isIframe)">
<i :class="val.meta.icon ? val.meta.icon : ''"></i>
{{ $t(val.meta.title) }}
</template>
<template slot="title" v-else>
<a :href="val.meta.isLink" target="_blank">
<i :class="val.meta.icon ? val.meta.icon : ''"></i>
{{ $t(val.meta.title) }}
</a>
</template>
</el-menu-item>
</template>
</template>
</el-menu>
</el-scrollbar>
</div>
</template>
<script>
import SubItem from '@/layout/navMenu/subItem.vue';
export default {
name: 'navMenuHorizontal',
components: { SubItem },
props: {
menuList: {
type: Array,
default: () => [],
},
},
data() {
return {
defaultActive: null,
};
},
mounted() {
this.initElMenuOffsetLeft();
this.setCurrentRouterHighlight(this.$route.path);
},
methods: {
// 设置横向滚动条可以鼠标滚轮滚动
onElMenuHorizontalScroll(e) {
const eventDelta = e.wheelDelta || -e.deltaY * 40;
this.$refs.elMenuHorizontalScrollRef.$refs.wrap.scrollLeft = this.$refs.elMenuHorizontalScrollRef.$refs.wrap.scrollLeft + eventDelta / 4;
},
// 初始化数据,页面刷新时,滚动条滚动到对应位置
initElMenuOffsetLeft() {
this.$nextTick(() => {
let els = document.querySelector('.el-menu.el-menu--horizontal li.is-active');
if (!els) return false;
this.$refs.elMenuHorizontalScrollRef.$refs.wrap.scrollLeft = els.offsetLeft;
});
},
// 路由过滤递归函数
filterRoutesFun(arr) {
return arr
.filter((item) => !item.meta.isHide)
.map((item) => {
item = Object.assign({}, item);
if (item.children) item.children = this.filterRoutesFun(item.children);
return item;
});
},
// 传送当前子级数据到菜单中
setSendClassicChildren(path) {
const currentPathSplit = path.split('/');
let currentData = {};
this.filterRoutesFun(this.$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;
},
// 菜单激活回调
onHorizontalSelect(path) {
this.bus.$emit('setSendClassicChildren', this.setSendClassicChildren(path));
},
// 设置页面当前路由高亮
setCurrentRouterHighlight(path) {
const currentPathSplit = path.split('/');
if (this.$store.state.themeConfig.themeConfig.layout === 'classic') {
this.defaultActive = `/${currentPathSplit[1]}`;
} else {
this.defaultActive = path;
}
},
},
watch: {
// 监听路由的变化
$route: {
handler(to) {
this.setCurrentRouterHighlight(to.path);
},
deep: true,
},
},
};
</script>
<style scoped lang="scss">
.el-menu-horizontal-warp {
flex: 1;
overflow: hidden;
margin-right: 30px;
::v-deep .el-scrollbar__bar.is-vertical {
display: none;
}
::v-deep .el-scrollbar__wrap {
overflow-y: hidden !important;
}
::v-deep a {
width: 100%;
}
.el-menu.el-menu--horizontal {
display: flex;
height: 100%;
width: 100%;
box-sizing: border-box;
}
}
</style>
+41
View File
@@ -0,0 +1,41 @@
<template>
<div>
<template v-for="val in chil">
<el-submenu :index="val.path" :key="val.path" v-if="val.children && val.children.length > 0">
<template slot="title">
<i :class="val.meta.icon"></i>
<span>{{ $t(val.meta.title) }}</span>
</template>
<sub-item :chil="val.children" />
</el-submenu>
<template v-else>
<el-menu-item :index="val.path" :key="val.path">
<template v-if="!val.meta.isLink || (val.meta.isLink && val.meta.isIframe)">
<i :class="val.meta.icon ? val.meta.icon : ''"></i>
<span>{{ $t(val.meta.title) }}</span>
</template>
<template v-else>
<a :href="val.meta.isLink" target="_blank">
<i :class="val.meta.icon ? val.meta.icon : ''"></i>
{{ $t(val.meta.title) }}
</a>
</template>
</el-menu-item>
</template>
</template>
</div>
</template>
<script>
export default {
name: 'subItem',
props: {
chil: {
type: Array,
default() {
return [];
},
},
},
};
</script>
+73
View File
@@ -0,0 +1,73 @@
<template>
<el-menu
router
background-color="transparent"
:default-active="defaultActive"
:collapse="setIsCollapse"
:unique-opened="getThemeConfig.isUniqueOpened"
:collapse-transition="false"
>
<template v-for="val in menuList">
<el-submenu :index="val.path" v-if="val.children && val.children.length > 0" :key="val.path">
<template slot="title">
<i :class="val.meta.icon ? val.meta.icon : ''"></i>
<span>{{ $t(val.meta.title) }}</span>
</template>
<SubItem :chil="val.children" />
</el-submenu>
<template v-else>
<el-menu-item :index="val.path" :key="val.path">
<i :class="val.meta.icon ? val.meta.icon : ''"></i>
<template slot="title" v-if="!val.meta.isLink || (val.meta.isLink && val.meta.isIframe)">
<span>{{ $t(val.meta.title) }}</span>
</template>
<template slot="title" v-else>
<a :href="val.meta.isLink" target="_blank">{{ $t(val.meta.title) }}</a>
</template>
</el-menu-item>
</template>
</template>
</el-menu>
</template>
<script>
import SubItem from '@/layout/navMenu/subItem.vue';
export default {
name: 'navMenuVertical',
components: { SubItem },
props: {
menuList: {
type: Array,
default() {
return [];
},
},
},
data() {
return {
defaultActive: this.$route.path,
};
},
computed: {
// 获取布局配置信息
getThemeConfig() {
return this.$store.state.themeConfig.themeConfig;
},
// 设置左侧菜单是否展开/收起
setIsCollapse() {
return document.body.clientWidth < 1000 ? false : this.$store.state.themeConfig.themeConfig.isCollapse;
},
},
watch: {
// 监听路由的变化
$route: {
handler(to) {
this.defaultActive = to.path;
const clientWidth = document.body.clientWidth;
if (clientWidth < 1000) this.$store.state.themeConfig.themeConfig.isCollapse = false;
},
deep: true,
},
},
};
</script>
+46
View File
@@ -0,0 +1,46 @@
<template>
<div>
<div class="layout-view-bg-white flex h100" v-loading="iframeLoading">
<iframe :src="meta.isLink" frameborder="0" height="100%" width="100%" id="iframe"></iframe>
</div>
</div>
</template>
<script>
export default {
name: 'layoutIfameView',
props: {
meta: {
type: Object,
default: () => {},
},
},
data() {
return {
iframeLoading: true,
};
},
created() {
this.bus.$on('onTagsViewRefreshRouterView', (path) => {
if (this.$route.path !== path) return false;
this.$emit('getCurrentRouteMeta');
});
},
mounted() {
this.initIframeLoad();
},
methods: {
// 初始化页面加载 loading
initIframeLoad() {
this.$nextTick(() => {
this.iframeLoading = true;
const iframe = document.getElementById('iframe');
if (!iframe) return false;
iframe.onload = () => {
this.iframeLoading = false;
};
});
},
},
};
</script>
+83
View File
@@ -0,0 +1,83 @@
<template>
<div class="layout-scrollbar layout-link-container">
<div class="layout-view-bg-white flex layout-view-link">
<div class="layout-link-warp">
<i class="layout-link-icon iconfont icon-xingqiu"></i>
<div class="layout-link-msg">页面 "{{ $t(meta.title) }}" 已在新窗口中打开</div>
<el-button class="mt30" round size="small" @click="onGotoFullPage">
<i class="iconfont icon-lianjie"></i>
<span>立即前往体验</span>
</el-button>
</div>
</div>
</div>
</template>
<script>
import { verifyUrl } from '@/utils/toolsValidate';
export default {
name: 'layoutLinkView',
props: {
meta: {
type: Object,
default: () => {},
},
},
methods: {
// 立即前往
onGotoFullPage() {
const { origin, pathname } = window.location;
if (verifyUrl(this.meta.isLink)) window.open(this.meta.isLink);
else window.open(`${origin}${pathname}#${this.meta.isLink}`);
},
},
};
</script>
<style scoped lang="scss">
.layout-link-container {
.layout-link-warp {
margin: auto;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
i.layout-link-icon {
position: relative;
font-size: 100px;
color: var(--prev-color-primary);
&::after {
content: '';
position: absolute;
left: 50px;
top: 0;
width: 15px;
height: 100px;
background: linear-gradient(
rgba(255, 255, 255, 0.01),
rgba(255, 255, 255, 0.01),
rgba(255, 255, 255, 0.01),
rgba(255, 255, 255, 0.05),
rgba(255, 255, 255, 0.05),
rgba(255, 255, 255, 0.05),
rgba(235, 255, 255, 0.5),
rgba(255, 255, 255, 0.05),
rgba(255, 255, 255, 0.05),
rgba(255, 255, 255, 0.05),
rgba(255, 255, 255, 0.01),
rgba(255, 255, 255, 0.01),
rgba(255, 255, 255, 0.01)
);
transform: rotate(-15deg);
animation: toRight 5s linear infinite;
}
}
.layout-link-msg {
font-size: 12px;
color: var(--prev-bg-topBarColor);
opacity: 0.7;
margin-top: 15px;
}
}
}
</style>
+47
View File
@@ -0,0 +1,47 @@
<template>
<div class="h100">
<transition :name="setTransitionName" mode="out-in">
<keep-alive :include="keepAliveNameList">
<router-view :key="refreshRouterViewKey" />
</keep-alive>
</transition>
</div>
</template>
<script>
export default {
name: 'parent',
data() {
return {
refreshRouterViewKey: null,
keepAliveNameList: [],
keepAliveNameNewList: [],
};
},
created() {
// 页面加载前,处理缓存,页面刷新时路由缓存处理
this.keepAliveNameList = this.getKeepAliveNames();
this.bus.$on('onTagsViewRefreshRouterView', (path) => {
if (this.$route.path !== path) return false;
this.keepAliveNameList = this.getKeepAliveNames().filter((name) => this.$route.name !== name);
this.refreshRouterViewKey = this.$route.path;
this.$nextTick(() => {
this.refreshRouterViewKey = null;
this.keepAliveNameList = this.getKeepAliveNames();
});
});
},
computed: {
// 设置主界面切换动画
setTransitionName() {
return this.$store.state.themeConfig.themeConfig.animation;
},
},
methods: {
// 获取路由缓存列表(name),默认路由全部缓存
getKeepAliveNames() {
return this.$store.state.keepAliveNames.keepAliveNames;
},
},
};
</script>
+123
View File
@@ -0,0 +1,123 @@
<template>
<div
class="sponsors-container"
title="点击前往体验"
v-show="sponsors.isShow"
@click="onSponsorsClick"
>
<el-carousel
height="240px"
indicator-position="none"
:arrow="setCarouselShow"
@change="onCarouselChange"
>
<el-carousel-item v-for="(v, k) in sponsors.list" :key="k">
<img :src="v.url" class="sponsors-img" />
<div class="sponsors-text" v-html="v.text"></div>
</el-carousel-item>
</el-carousel>
<div class="sponsors-close" title="关闭赞助商" @click.stop="onCloseSponsors">
<i class="el-icon-close"></i>
</div>
</div>
</template>
<script>
import sponsorsOne from "@/assets/ccflowRightNextAdmin.png";
export default {
name: "layoutSponsors",
data() {
return {
sponsors: {
list: [
{
url: sponsorsOne,
text: `自创建鼎盛无际后台管理系统模板`,
link: "http://www.ccflow.org/",
},
],
isShow: false,
index: 0,
},
};
},
computed: {
// 设置轮播图箭头显示
setCarouselShow() {
return this.sponsors.list.length <= 1 ? "never" : "hover";
},
},
methods: {
// 关闭赞助商
onCloseSponsors() {
this.sponsors.isShow = false;
},
// 轮播图改变时
onCarouselChange(e) {
this.sponsors.index = e;
},
// 当前项内容点击
onSponsorsClick() {
window.open(this.sponsors.list[this.sponsors.index].link);
},
// 延迟显示,防止影响其它界面加载
delayShow() {
setTimeout(() => {
this.sponsors.isShow = true;
}, 3000);
},
},
mounted() {
this.delayShow();
},
};
</script>
<style scoped lang="scss">
.sponsors-container {
position: fixed;
right: 15px;
bottom: 15px;
z-index: 3;
width: 200px;
background-color: var(--prev-bg-main-color);
box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.12);
border-radius: 5px;
overflow: hidden;
cursor: pointer;
.sponsors-img {
width: 100%;
height: 80px;
}
.sponsors-text {
padding: 10px;
color: var(--prev-color-text-regular);
font-size: 14px;
}
.sponsors-close {
width: 60px;
height: 60px;
border-radius: 100%;
background: rgba(0, 0, 0, 0.05);
transition: all 0.3s ease;
position: absolute;
right: -35px;
bottom: -35px;
z-index: 5;
i {
position: absolute;
left: 9px;
top: 9px;
color: #afafaf;
transition: all 0.3s ease;
}
&:hover {
transition: all 0.3s ease;
i {
color: var(--prev-color-primary);
transition: all 0.3s ease;
}
}
}
}
</style>
+164
View File
@@ -0,0 +1,164 @@
<template>
<div class="upgrade-dialog">
<el-dialog
:visible.sync="isUpgrade"
width="300px"
destroy-on-close
:show-close="false"
:close-on-click-modal="false"
:close-on-press-escape="false"
>
<div class="upgrade-title">
<div class="upgrade-title-warp">
<span class="upgrade-title-warp-txt">{{ $t("message.upgrade.title") }}</span>
<span class="upgrade-title-warp-version">{{ version }}</span>
</div>
</div>
<div class="upgrade-content">
{{ getThemeConfig.globalTitle }} {{ $t("message.upgrade.msg") }}
<div class="mt5">
<el-link
type="primary"
class="font12"
href="https://gitee.com/lyt-top/vue-next-admin/blob/vue-prev-admin/CHANGELOG.md"
target="_black"
>
CHANGELOG.md
</el-link>
</div>
<div class="upgrade-content-desc mt5">{{ $t("message.upgrade.desc") }}</div>
</div>
<div class="upgrade-btn">
<el-button round size="small" @click="onCancel">{{
$t("message.upgrade.btnOne")
}}</el-button>
<el-button
type="primary"
disabled="disabled"
round
size="small"
@click="onUpgrade"
:loading="isLoading"
>{{ btnTxt }}</el-button
>
</div>
</el-dialog>
</div>
</template>
<script>
import { Local } from "@/utils/storage";
import config from "/package.json";
export default {
data() {
return {
isUpgrade: false,
version: config.version,
isLoading: false,
btnTxt: "",
};
},
computed: {
// 获取布局配置信息
getThemeConfig() {
return this.$store.state.themeConfig.themeConfig;
},
},
methods: {
// 残忍拒绝
onCancel() {
this.isUpgrade = false;
},
// 马上更新
onUpgrade() {
this.isLoading = true;
this.btnTxt = this.$t("message.upgrade.btnTwoLoading");
setTimeout(() => {
Local.clear();
window.location.reload();
Local.set("version", this.version);
}, 2000);
},
// 延迟显示,防止刷新时界面显示太快
delayShow() {
setTimeout(() => {
this.isUpgrade = true;
}, 2000);
},
},
mounted() {
this.delayShow();
setTimeout(() => {
this.btnTxt = this.$t("message.upgrade.btnTwo");
}, 200);
},
};
</script>
<style scoped lang="scss">
.upgrade-dialog {
& ::v-deep .el-dialog {
.el-dialog__body {
padding: 0 !important;
}
.el-dialog__header {
display: none !important;
}
.upgrade-title {
text-align: center;
height: 130px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
&::after {
content: "";
position: absolute;
background-color: var(--prev-color-primary-light-1);
width: 130%;
height: 130px;
border-bottom-left-radius: 100%;
border-bottom-right-radius: 100%;
}
.upgrade-title-warp {
z-index: 1;
position: relative;
.upgrade-title-warp-txt {
color: var(--prev-color-text-white);
font-size: 22px;
letter-spacing: 3px;
}
.upgrade-title-warp-version {
background-color: var(--prev-color-primary-light-4);
color: var(--prev-color-text-white);
font-size: 12px;
position: absolute;
display: flex;
top: -2px;
right: -50px;
padding: 2px 4px;
border-radius: 2px;
}
}
}
.upgrade-content {
padding: 20px;
line-height: 22px;
color: var(--prev-color-text-regular);
.upgrade-content-desc {
color: var(--prev-color-text-placeholder);
font-size: 12px;
}
}
.upgrade-btn {
border-top: 1px solid var(--prev-border-color-lighter);
display: flex;
justify-content: space-around;
padding: 15px 20px;
.el-button {
width: 100%;
}
}
}
}
</style>
+41
View File
@@ -0,0 +1,41 @@
import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
import Particles from 'vue-particles';
import Element from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import '@/theme/index.scss';
import { i18n } from '@/i18n/index.js';
import { globalComponentSize } from '@/utils/componentSize.js';
import CommonTables from '@/components/CommonTables'
import CommonHead from '@/components/CommonHead'
import CommonTablesImg from '@/components/CommonTablesImg'
import Pagination from '@/components/pagination/index.vue'; // 分页器
import { formatDate } from './com';
// import { download } from '@/utils/request'
import VueCropper from 'vue-cropper'
Vue.use(VueCropper) //方便我们直接用
Vue.use(Particles);
Vue.use(Element, { i18n: (key, value) => i18n.t(key, value), size: globalComponentSize });
Vue.config.productionTip = false;
Vue.prototype.bus = new Vue();
Vue.prototype.formatDate = formatDate;
// Vue.prototype.download = download
// 注册全局组件
Vue.component(CommonTables.name,CommonTables)
Vue.component(CommonHead.name,CommonHead)
Vue.component('CommonTablesImg',CommonTablesImg)
Vue.component('Pagination', Pagination)
new Vue({
router,
store,
i18n,
render: (h) => h(App),
}).$mount('#app');
+291
View File
@@ -0,0 +1,291 @@
import Vue from 'vue';
import store from '../store';
import VueRouter from 'vue-router';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
import { Session } from '@/utils/storage';
import { PrevLoading } from '@/utils/loading.js';
import { useMenuApi } from '@/api/menu';
import adminbendirout from '../../public/admin';
const menuApi = useMenuApi();
// 解决 `element ui` 导航栏重复点菜单报错问题
const originalPush = VueRouter.prototype.push;
VueRouter.prototype.push = function push(location) {
return originalPush.call(this, location).catch((err) => err);
};
// 安装 VueRouter 插件
Vue.use(VueRouter);
// 定义动态路由
const dynamicRoutes = [
{
path: '/',
name: '/',
component: 'layout/index',
redirect: '/home',
meta: {
isKeepAlive: true,
},
children: [],
},
];
// 定义静态路由
const staticRoutes = [
{
path: '/login',
name: 'login',
component: () => import('@/views/login'),
meta: {
title: '登录',
},
},
{
path: '/404',
name: 'notFound',
component: () => import('@/views/error/404.vue'),
meta: {
title: 'message.staticRoutes.notFound',
},
},
{
path: '/401',
name: 'noPower',
component: () => import('@/views/error/401.vue'),
meta: {
title: 'message.staticRoutes.noPower',
},
},
];
// 加载静态路由
const createRouter = () =>
new VueRouter({
routes: staticRoutes,
});
// 创建路由
const router = createRouter();
// 加载 loading
PrevLoading.start();
// 多级嵌套数组处理成一维数组
export function formatFlatteningRoutes(arr) {
if (arr.length <= 0) return false;
for (let i = 0; i < arr.length; i++) {
if (arr[i].children) {
arr = arr.slice(0, i + 1).concat(arr[i].children, arr.slice(i + 1));
}
}
return arr;
}
// 处理 tagsViewList 数据,默认路由全部缓存
// isKeepAlive 处理 `name` 值,进行路由缓存
export function formatTwoStageRoutes(arr) {
if (arr.length <= 0) return false;
const newArr = [];
const cacheList = [];
arr.forEach((v) => {
newArr.push({ ...v });
cacheList.push(v.name);
store.dispatch('keepAliveNames/setCacheKeepAlive', cacheList);
});
return newArr;
}
// 判断路由 meta.roles 中是否包含当前登录用户权限字段
export function hasAuth(roles, route) {
if (route.meta && route.meta.roles) return roles.some((role) => route.meta.roles.includes(role));
else return true;
}
// 递归过滤有权限的路由
export function setFilterMenuFun(routes, role) {
const menu = [];
routes.forEach((route) => {
const item = { ...route };
if (hasAuth(role, item)) {
if (item.children) item.children = setFilterMenuFun(item.children, role);
menu.push(item);
}
});
return menu;
}
// 缓存多级嵌套数组处理后的一维数组(tagsView、菜单搜索中使用:未过滤隐藏的(isHide))
export function setCacheTagsViewRoutes(arr) {
// 先处理有权限的路由,否则 tagsView、菜单搜索中无权限的路由也将显示
let rolesRoutes = setFilterMenuFun(arr, store.state.userInfos.userInfos.roles);
// 添加到 vuex setTagsViewRoutes 中
store.dispatch('tagsViewRoutes/setTagsViewRoutes', formatTwoStageRoutes(formatFlatteningRoutes(rolesRoutes)));
}
// 递归处理多余的 layout : <router-view>,让需要访问的组件保持在第一层 layout 层。
// 因为 `keep-alive` 只能缓存二级路由
// 默认初始化时就执行
export function keepAliveSplice(to) {
if (to.matched && to.matched.length > 2) {
to.matched.map((v, k) => {
if (v.components.default instanceof Function) {
v.components.default().then((components) => {
if (components.default.name === 'parent') {
to.matched.splice(k, 1);
router.push({ path: to.path, query: to.query });
keepAliveSplice(to);
}
});
} else {
if (v.components.default.name === 'parent') {
to.matched.splice(k, 1);
keepAliveSplice(to);
}
}
});
}
}
// 处理后端返回的 `component` 路径,拼装实现懒加载
export function loadView(path) {
/**
* 打包成一个 js、一个 css
*/
// if (path.indexOf('layout') > -1) return () => Promise.resolve(require(`@/${path}`));
// else return () => Promise.resolve(require(`@/views/${path}`));
/**
* 打包成多个 js、多个 css
*/
if (path.indexOf('layout') > -1) return () => import(`@/${path}`);
else return () => import(`@/views/${path}`);
}
// 递归处理每一项 `component` 中的路径
export function dynamicRouter(routes) {
return routes.map((view) => {
if (view.component) view.component = loadView(view.component);
if (view.children) dynamicRouter(view.children);
return view;
});
}
// 添加路由,模拟数据与方法,可自行进行修改 admin
// 添加动态路由,`{ path: '*', redirect: '/404' }` 防止页面刷新,静态路由丢失问题
// next({ ...to, replace: true }) 动态路由 addRoute 完毕后才放行,防止刷新时 NProgress 进度条加载2次
// 文档地址:https://router.vuejs.org/zh/api/#router-addroutes
export function adminUser(router, to, next) {
resetRouter();
// 发请求获取路由表操作
// menuApi
// .getMenuAdmin()
// .then(async (res) => {
// // 获取路由表
// console.log(res.data);
// // 读取用户信息,获取对应权限进行判断
// store.dispatch('userInfos/setUserInfos');
// store.dispatch('routesList/setRoutesList', setFilterMenuFun(res.data, store.state.userInfos.userInfos.roles));
// dynamicRoutes[0].children = res.data;
// const awaitRoute = await dynamicRouter(dynamicRoutes);
// [...awaitRoute, { path: '*', redirect: '/404' }].forEach((route) => {
// router.addRoute({ ...route });
// });
// setCacheTagsViewRoutes(JSON.parse(JSON.stringify(res.data)));
// next({ ...to, replace: true });
// })
// .catch(() => {});
// 本地数据路由表操作
console.log(adminbendirout);
store.dispatch('userInfos/setUserInfos');
store.dispatch('routesList/setRoutesList', setFilterMenuFun(adminbendirout.data, store.state.userInfos.userInfos.roles));
dynamicRoutes[0].children = adminbendirout.data;
const awaitRoute = dynamicRouter(dynamicRoutes);
[...awaitRoute, { path: '*', redirect: '/404' }].forEach((route) => {
router.addRoute({ ...route });
});
setCacheTagsViewRoutes(JSON.parse(JSON.stringify(adminbendirout.data)));
next({ ...to, replace: true });
}
// 添加路由,模拟数据与方法,可自行进行修改 test
// 添加动态路由,`{ path: '*', redirect: '/404' }` 防止页面刷新,静态路由丢失问题
export function testUser(router, to, next) {
resetRouter();
menuApi
.getMenuTest()
.then(async (res) => {
// 读取用户信息,获取对应权限进行判断
store.dispatch('userInfos/setUserInfos');
store.dispatch('routesList/setRoutesList', setFilterMenuFun(res.data, store.state.userInfos.userInfos.roles));
dynamicRoutes[0].children = res.data;
const awaitRoute = await dynamicRouter(dynamicRoutes);
[...awaitRoute, { path: '*', redirect: '/404' }].forEach((route) => {
router.addRoute({ ...route });
});
setCacheTagsViewRoutes(JSON.parse(JSON.stringify(res.data)));
next({ ...to, replace: true });
})
.catch(() => {});
}
// 重置路由
export function resetRouter() {
router.matcher = createRouter().matcher;
}
// 延迟关闭进度条
export function delayNProgressDone(time = 300) {
setTimeout(() => {
NProgress.done();
}, time);
}
// 动态加载后端返回路由路由(模拟数据)
export function getRouterList(router, to, next) {
if (!Session.get('userInfo')) return false;
if (Session.get('userInfo').userName === 'admin') adminUser(router, to, next);
else if (Session.get('userInfo').userName === 'test') testUser(router, to, next);
}
// 路由加载前
router.beforeEach((to, from, next) => {
keepAliveSplice(to);
NProgress.configure({ showSpinner: false });
if (to.meta.title && to.path !== '/login') NProgress.start();
let token = Session.get('token');
if (to.path === '/login' && !token) {
NProgress.start();
next();
delayNProgressDone();
} else {
if (!token) {
NProgress.start();
next('/login');
Session.clear();
delayNProgressDone();
} else if (token && to.path === '/login') {
next('/home');
delayNProgressDone();
} else {
if (Object.keys(store.state.routesList.routesList).length <= 0) {
getRouterList(router, to, next);
} else {
next();
delayNProgressDone(0);
}
}
}
});
// 路由加载后
router.afterEach(() => {
PrevLoading.done();
delayNProgressDone();
});
// 导出路由
export default router;
+293
View File
@@ -0,0 +1,293 @@
import Vue from 'vue';
import store from '../store';
import VueRouter from 'vue-router';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
import { Session } from '@/utils/storage';
import { PrevLoading } from '@/utils/loading.js';
import { useMenuApi } from '@/api/menu';
import adminbendirout from '../../public/admin';
const menuApi = useMenuApi();
// 解决 `element ui` 导航栏重复点菜单报错问题
const originalPush = VueRouter.prototype.push;
VueRouter.prototype.push = function push(location) {
return originalPush.call(this, location).catch((err) => err);
};
// 安装 VueRouter 插件
Vue.use(VueRouter);
// 定义动态路由
const dynamicRoutes = [
{
path: '/',
name: '/',
component: 'layout/index',
redirect: '/home',
meta: {
isKeepAlive: true,
},
children: [],
},
];
// 定义静态路由
const staticRoutes = [
{
path: '/login',
name: 'login',
component: () => import('@/views/login'),
meta: {
title: '登录',
},
},
{
path: '/404',
name: 'notFound',
component: () => import('@/views/error/404.vue'),
meta: {
title: 'message.staticRoutes.notFound',
},
},
{
path: '/401',
name: 'noPower',
component: () => import('@/views/error/401.vue'),
meta: {
title: 'message.staticRoutes.noPower',
},
},
];
// 加载静态路由
const createRouter = () =>
new VueRouter({
routes: staticRoutes,
});
// 创建路由
const router = createRouter();
// 加载 loading
PrevLoading.start();
// 多级嵌套数组处理成一维数组
export function formatFlatteningRoutes(arr) {
if (arr.length <= 0) return false;
for (let i = 0; i < arr.length; i++) {
if (arr[i].children) {
arr = arr.slice(0, i + 1).concat(arr[i].children, arr.slice(i + 1));
}
}
return arr;
}
// 处理 tagsViewList 数据,默认路由全部缓存
// isKeepAlive 处理 `name` 值,进行路由缓存
export function formatTwoStageRoutes(arr) {
if (arr.length <= 0) return false;
const newArr = [];
const cacheList = [];
arr.forEach((v) => {
newArr.push({ ...v });
cacheList.push(v.name);
store.dispatch('keepAliveNames/setCacheKeepAlive', cacheList);
});
return newArr;
}
// 判断路由 meta.roles 中是否包含当前登录用户权限字段
export function hasAuth(roles, route) {
if (route.meta && route.meta.roles) return roles.some((role) => route.meta.roles.includes(role));
else return true;
}
// 递归过滤有权限的路由
export function setFilterMenuFun(routes, role) {
const menu = [];
routes.forEach((route) => {
const item = { ...route };
if (hasAuth(role, item)) {
if (item.children) item.children = setFilterMenuFun(item.children, role);
menu.push(item);
}
});
return menu;
}
// 缓存多级嵌套数组处理后的一维数组(tagsView、菜单搜索中使用:未过滤隐藏的(isHide))
export function setCacheTagsViewRoutes(arr) {
// 先处理有权限的路由,否则 tagsView、菜单搜索中无权限的路由也将显示
let rolesRoutes = setFilterMenuFun(arr, store.state.userInfos.userInfos.roles);
// 添加到 vuex setTagsViewRoutes 中
store.dispatch('tagsViewRoutes/setTagsViewRoutes', formatTwoStageRoutes(formatFlatteningRoutes(rolesRoutes)));
}
// 递归处理多余的 layout : <router-view>,让需要访问的组件保持在第一层 layout 层。
// 因为 `keep-alive` 只能缓存二级路由
// 默认初始化时就执行
export function keepAliveSplice(to) {
if (to.matched && to.matched.length > 2) {
to.matched.map((v, k) => {
if (v.components.default instanceof Function) {
v.components.default().then((components) => {
if (components.default.name === 'parent') {
to.matched.splice(k, 1);
router.push({ path: to.path, query: to.query });
keepAliveSplice(to);
}
});
} else {
if (v.components.default.name === 'parent') {
to.matched.splice(k, 1);
keepAliveSplice(to);
}
}
});
}
}
// 处理后端返回的 `component` 路径,拼装实现懒加载
export function loadView(path) {
/**
* 打包成一个 js、一个 css
*/
// if (path.indexOf('layout') > -1) return () => Promise.resolve(require(`@/${path}`));
// else return () => Promise.resolve(require(`@/views/${path}`));
/**
* 打包成多个 js、多个 css
*/
if (path.indexOf('layout') > -1) return () => import(`@/${path}`);
else return () => import(`@/views/${path}`);
}
// 递归处理每一项 `component` 中的路径
export function dynamicRouter(routes) {
return routes.map((view) => {
if (view.component) view.component = loadView(view.component);
if (view.children) dynamicRouter(view.children);
return view;
});
}
// 添加路由,模拟数据与方法,可自行进行修改 admin
// 添加动态路由,`{ path: '*', redirect: '/404' }` 防止页面刷新,静态路由丢失问题
// next({ ...to, replace: true }) 动态路由 addRoute 完毕后才放行,防止刷新时 NProgress 进度条加载2次
// 文档地址:https://router.vuejs.org/zh/api/#router-addroutes
export function adminUser(router, to, next) {
resetRouter();
// 发请求获取路由表操作
// menuApi
// .getMenuAdmin()
// .then(async (res) => {
// // 获取路由表
// console.log(res.data);
// // 读取用户信息,获取对应权限进行判断
// store.dispatch('userInfos/setUserInfos');
// store.dispatch('routesList/setRoutesList', setFilterMenuFun(res.data, store.state.userInfos.userInfos.roles));
// dynamicRoutes[0].children = res.data;
// const awaitRoute = await dynamicRouter(dynamicRoutes);
// [...awaitRoute, { path: '*', redirect: '/404' }].forEach((route) => {
// router.addRoute({ ...route });
// });
// setCacheTagsViewRoutes(JSON.parse(JSON.stringify(res.data)));
// next({ ...to, replace: true });
// })
// .catch(() => {});
// 本地数据路由表操作
console.log(adminbendirout);
store.dispatch('userInfos/setUserInfos');
store.dispatch('routesList/setRoutesList', setFilterMenuFun(adminbendirout.data, store.state.userInfos.userInfos.roles));
dynamicRoutes[0].children = adminbendirout.data;
const awaitRoute = dynamicRouter(dynamicRoutes);
[...awaitRoute, { path: '*', redirect: '/404' }].forEach((route) => {
router.addRoute({ ...route });
});
setCacheTagsViewRoutes(JSON.parse(JSON.stringify(adminbendirout.data)));
next({ ...to, replace: true });
}
// 添加路由,模拟数据与方法,可自行进行修改 test
// 添加动态路由,`{ path: '*', redirect: '/404' }` 防止页面刷新,静态路由丢失问题
export function testUser(router, to, next) {
resetRouter();
menuApi
.getMenuTest()
.then(async (res) => {
// 读取用户信息,获取对应权限进行判断
store.dispatch('userInfos/setUserInfos');
store.dispatch('routesList/setRoutesList', setFilterMenuFun(res.data, store.state.userInfos.userInfos.roles));
dynamicRoutes[0].children = res.data;
const awaitRoute = await dynamicRouter(dynamicRoutes);
[...awaitRoute, { path: '*', redirect: '/404' }].forEach((route) => {
router.addRoute({ ...route });
});
setCacheTagsViewRoutes(JSON.parse(JSON.stringify(res.data)));
next({ ...to, replace: true });
})
.catch(() => {});
}
// 重置路由
export function resetRouter() {
router.matcher = createRouter().matcher;
}
// 延迟关闭进度条
export function delayNProgressDone(time = 300) {
setTimeout(() => {
NProgress.done();
}, time);
}
// 动态加载后端返回路由路由(模拟数据)
export function getRouterList(router, to, next) {
if (!localStorage.getItem('token')) return false;
if (localStorage.getItem('token') ) {
console.log('777777777777')
adminUser(router, to, next)
}else if (localStorage.getItem('userInfo').userName === 'test') testUser(router, to, next);
}
// 路由加载前
router.beforeEach((to, from, next) => {
keepAliveSplice(to);
NProgress.configure({ showSpinner: false });
if (to.meta.title && to.path !== '/login') NProgress.start();
let token = Session.get('token');
if (to.path === '/login' && !token) {
NProgress.start();
next();
delayNProgressDone();
} else {
if (!token) {
NProgress.start();
next('/login');
Session.clear();
delayNProgressDone();
} else if (token && to.path === '/login') {
next('/home');
delayNProgressDone();
} else {
if (Object.keys(store.state.routesList.routesList).length <= 0) {
getRouterList(router, to, next);
} else {
next();
delayNProgressDone(0);
}
}
}
});
// 路由加载后
router.afterEach(() => {
PrevLoading.done();
delayNProgressDone();
});
// 导出路由
export default router;
+81
View File
@@ -0,0 +1,81 @@
import Vue from 'vue';
import Vuex from 'vuex';
import { Session } from '@/utils/storage';
import { login } from '../views/login/api.js'
// import { login } from '@/login/api.js'
import jsonwebtoken from 'jsonwebtoken'
Vue.use(Vuex);
let moduleFn = require.context('./modules', false, /\.js$/);
let modules = moduleFn.keys().reduce((p, c) => {
let mod = moduleFn(c).default;
mod = { ...mod, namespaced: true };
let modName = c.match(/\.\/(\w+)\.js$/)[1];
p[modName] = mod;
return p;
}, {});
const state = {
imgUrl: 'https://hxhl.lzyyj.com/prod-api/file/upload/face',
uploadHeader: {
Authorization: `${Session.get('token')}`
},
campusCalendarTempentUrl: process.env.VUE_APP_BASE_API, //
token: localStorage.getItem('token') || '',
refreshToken: localStorage.getItem('refreshToken') || '', // 刷新token
user: localStorage.getItem('user') ? JSON.parse(localStorage.getItem('user')) : {}, // 用户信息
school: localStorage.getItem('school') ? JSON.parse(localStorage.getItem('school')) : {}, // 学校 默认获取的第一个
roles: localStorage.getItem('roles') ? JSON.parse(localStorage.getItem('roles')) : [], // 权限 是家长或教师
classify: localStorage.getItem('classify') ? JSON.parse(localStorage.getItem('classify')) : {} // 用户为班主任的班级 默认查找的第一个
}
const mutations = {
changeToken( state, newToken ) {
state.token = newToken
localStorage.setItem('token', newToken)
},
changeRefreshToken( state, newRefreshToken ) {
state.refreshToken = newRefreshToken
localStorage.setItem('refreshToken', newRefreshToken)
},
changeUser( state, newUser ) {
state.user = newUser
localStorage.setItem('user', JSON.stringify(newUser) )
},
setSchool( state, newSchool){
localStorage.setItem('school', JSON.stringify(newSchool) )
state.school = newSchool
},
setRoles( state, newRoles){
localStorage.setItem('roles', JSON.stringify(newRoles) )
state.roles = newRoles
},
setClassify( state, newClassify){
localStorage.setItem('classify', JSON.stringify(newClassify) )
state.classify = newClassify
},
}
const actions = {
loginIn(store, obj) {
return new Promise((resolve, reject) =>{
login(obj).then(res =>{
console.log('=========================')
console.log(res)
store.commit('changeToken',res.token_type + ' ' + res.access_token )
store.commit('changeRefreshToken', res.refresh_token )
console.log(jsonwebtoken.decode(res.access_token))
store.commit('changeUser', jsonwebtoken.decode(res.access_token) )
resolve(res)
}).catch(err =>{
reject(err)
})
})
}
}
export default new Vuex.Store({ state, modules, mutations, actions });
+20
View File
@@ -0,0 +1,20 @@
const keepAliveNamesModule = {
namespaced: true,
state: {
keepAliveNames: [],
},
mutations: {
// 设置路由缓存(name字段)
getCacheKeepAlive(state, data) {
state.keepAliveNames = data;
},
},
actions: {
// 设置路由缓存(name字段)
async setCacheKeepAlive({ commit }, data) {
commit('getCacheKeepAlive', data);
},
},
};
export default keepAliveNamesModule;
+16
View File
@@ -0,0 +1,16 @@
const loginConfig = {
namespaced: true,
state: {
loginConfig: { // 登录配置信息
client_id: 'test-client',
client_secret: '123456',
grant_type: 'dswj_multiple',
login_type: 'sms_login',
},
},
mutations: {
},
};
export default loginConfig;
+20
View File
@@ -0,0 +1,20 @@
const routesListModule = {
namespaced: true,
state: {
routesList: [],
},
mutations: {
// 设置路由,菜单中使用到
getRoutesList(state, data) {
state.routesList = data;
},
},
actions: {
// 设置路由,菜单中使用到
async setRoutesList({ commit }, data) {
commit('getRoutesList', data);
},
},
};
export default routesListModule;
+20
View File
@@ -0,0 +1,20 @@
const tagsViewRoutesModule = {
namespaced: true,
state: {
tagsViewRoutes: [],
},
mutations: {
// 设置 TagsView 路由
getTagsViewRoutes(state, data) {
state.tagsViewRoutes = data;
},
},
actions: {
// 设置 TagsView 路由
async setTagsViewRoutes({ commit }, data) {
commit('getTagsViewRoutes', data);
},
},
};
export default tagsViewRoutesModule;
+122
View File
@@ -0,0 +1,122 @@
/**
* 2020.05.28 by lyt 优化
* 修改一下配置时,需要每次都清理 `window.localStorage` 浏览器永久缓存,配置才会生效
*/
const themeConfigModule = {
namespaced: true,
state: {
themeConfig: {
// 是否开启布局配置抽屉
isDrawer: false,
/**
* 全局主题
*/
// 默认 primary 主题颜色
primary: '#409eff',
// 是否开启深色模式
isIsDark: false,
/**
* 菜单 / 顶栏
* 请注意:
* 需要同时修改 `/@/theme/common/var.scss` 对应的值,
* 不提供像 vue-next-admin 一样的实现
*/
// 默认顶栏导航背景颜色
topBar: '#ffffff',
// 默认顶栏导航字体颜色
topBarColor: '#606266',
// 默认菜单导航背景颜色
menuBar: '#545c64',
// 默认菜单导航字体颜色
menuBarColor: '#eaeaea',
// 默认分栏菜单背景颜色
columnsMenuBar: '#545c64',
// 默认分栏菜单字体颜色
columnsMenuBarColor: '#e6e6e6',
/**
* 界面设置
*/
// 是否开启菜单水平折叠效果
isCollapse: false,
// 是否开启菜单手风琴效果
isUniqueOpened: false,
// 是否开启固定 Header
isFixedHeader: false,
/**
* 界面显示
*/
// 是否开启侧边栏 Logo
isShowLogo: true,
// 是否开启 Breadcrumb
isBreadcrumb: true,
// 是否开启 Breadcrumb 图标
isBreadcrumbIcon: false,
// 是否开启 Tagsview
isTagsview: true,
// 是否开启 Tagsview 图标
isTagsviewIcon: false,
// 是否开启 TagsView 缓存
isCacheTagsView: false,
// 是否开启 Footer 底部版权信息
isFooter: false,
// 是否开启灰色模式
isGrayscale: false,
// 是否开启色弱模式
isInvert: false,
/**
* 其它设置
*/
// 默认 Tagsview 风格,可选 1、 tags-style-one,自行扩展:
// 1、需修改 @/layout/navBars/breadcrumb/setings.vue `getThemeConfig.tagsStyle` el-option
// 2、需修改 @/layout/navBars/tagsView/tagsView.vue 代码最底部注释部分 css 样式
tagsStyle: 'tags-style-one',
// 主页面切换动画:可选值"<slide-right|slide-left|opacitys>",默认 slide-right
animation: 'slide-right',
// 分栏高亮风格:可选值"<columns-round|columns-card>",默认 columns-round
columnsAsideStyle: 'columns-round',
// 分栏布局风格:可选值"<columns-horizontal|columns-vertical>",默认 columns-horizontal
columnsAsideLayout: 'columns-vertical',
/**
* 布局切换
* 注意:为了演示,切换布局时,颜色会被还原成默认,代码位置:/@/layout/navBars/breadcrumb/setings.vue
* 中的 `initSetLayoutChange(设置布局切换,重置主题样式)` 方法
*/
// 布局切换:可选值"<defaults|classic|transverse|columns>",默认 defaults
layout: 'defaults',
/**
* 全局网站标题 / 副标题
*/
// 网站主标题(菜单导航、浏览器当前网页标题)
globalTitle: '数字校园教育管理平台',
// 网站副标题(登录页顶部文字)
globalViceTitle: '数字校园教育管理平台',
// 网站描述(登录页顶部文字)
globalViceDes: '数字校园教育管理平台',
// 默认初始语言,可选值"<zh-cn|en|zh-tw>",默认 zh-cn
globalI18n: 'zh-cn',
// 默认全局组件大小,可选值"<|medium|small|mini>",默认 ''
globalComponentSize: 'mini',
},
},
mutations: {
// 设置布局配置
getThemeConfig(state, data) {
state.themeConfig = data;
},
},
actions: {
// 设置布局配置
setThemeConfig({ commit }, data) {
commit('getThemeConfig', data);
},
},
};
export default themeConfigModule;
+39
View File
@@ -0,0 +1,39 @@
import { Session } from '@/utils/storage.js';
const userInfosModule = {
namespaced: true,
state: {
userInfos: {},
userInfosDD:{}
},
mutations: {
// 设置用户信息
getUserInfos(state, data) {
state.userInfos = data;
},
// 设置钉钉用户信息
setUserInfosDD(state, data) {
state.userInfosDD = data;
},
},
actions: {
// 设置用户信息
async setUserInfos({ commit }, data) {
if (data) {
commit('getUserInfos', data);
} else {
if (Session.get('userInfo')) commit('getUserInfos', Session.get('userInfo'));
}
},
// 设置钉钉用户信息
async setUserInfosDD({ commit }, data) {
if (data) {
commit('setUserInfosDD', data);
} else {
if (Session.get('setUserInfosDD')) commit('setUserInfosDD', Session.get('setUserInfosDD'));
}
},
},
};
export default userInfosModule;
+240
View File
@@ -0,0 +1,240 @@
/* 初始化样式
------------------------------- */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
outline: none;
}
:root {
--prev-bg-menuBar: #545c64;
--prev-bg-menuBarColor: #eaeaea;
--prev-bg-topBar: #ffffff;
--prev-bg-topBarColor: #606266;
--prev-bg-columnsMenuBar: #545c64;
--prev-bg-columnsMenuBarColor: #e6e6e6;
--prev-bg-main-color: #f8f8f8;
--prev-bg-color: #f5f7fa;
--prev-bg-white: #ffffff;
--prev-color-primary: #409eff;
--prev-color-text-white: #ffffff;
--prev-color-text-black: #000000;
--prev-color-text-primary: #303133;
--prev-color-text-regular: #606266;
--prev-color-text-secondary: #909399;
--prev-color-text-placeholder: #c0c4cc;
--prev-color-hover: rgba(0, 0, 0, 0.04);
--prev-color-seting-main: #e9eef3;
--prev-color-seting-aside: #d3dce6;
--prev-color-seting-header: #b3c0d1;
--prev-border-color-hover: #c0c4cc;
--prev-border-color-base: #dcdfe6;
--prev-border-color-light: #e4e7ed;
--prev-border-color-lighter: #ebeef5;
--prev-border-color-extra-light: #f2f6fc;
}
html,
body,
#app {
width: 100%;
height: 100%;
background-color: var(--prev-bg-main-color);
font-size: 14px;
}
/* 主布局样式
------------------------------- */
.layout-container {
width: 100%;
height: 100%;
.layout-aside {
background: var(--prev-bg-menuBar);
box-shadow: 2px 0 6px rgb(0 21 41 / 1%);
height: inherit;
position: relative;
z-index: 1;
display: flex;
flex-direction: column;
overflow-x: hidden !important;
.el-scrollbar__view {
overflow: hidden;
}
}
.layout-header {
padding: 0 !important;
}
.layout-main {
padding: 0 !important;
overflow: hidden;
width: 100%;
background-color: var(--prev-bg-main-color);
}
.el-scrollbar {
width: 100%;
}
.layout-view-bg-white {
background: var(--prev-bg-white);
width: 100%;
height: 100%;
border-radius: 4px;
border: 1px solid var(--prev-border-color-lighter);
}
.layout-el-aside-br-color {
border-right: 1px solid rgb(238, 238, 238);
}
.layout-aside-width-default {
width: 220px !important;
transition: width 0.3s ease;
}
.layout-aside-width64 {
width: 64px !important;
transition: width 0.3s ease;
}
.layout-aside-width1 {
width: 1px !important;
transition: width 0.3s ease;
}
.layout-scrollbar {
@extend .el-scrollbar;
padding: 15px;
}
.layout-mian-height-50 {
height: calc(100vh - 50px);
}
.layout-columns-warp {
flex: 1;
display: flex;
overflow: hidden;
}
.layout-hide {
display: none;
}
}
/* 进度条颜色
------------------------------- */
#nprogress .bar {
background: var(--prev-color-primary) !important;
}
/* flex 弹性布局
------------------------------- */
.flex {
display: flex;
}
.flex-auto {
flex: 1;
}
.flex-center {
@extend .flex;
flex-direction: column;
width: 100%;
overflow: hidden;
}
.flex-margin {
margin: auto;
}
.flex-warp {
display: flex;
flex-wrap: wrap;
align-content: flex-start;
margin: 0 -5px;
.flex-warp-item {
padding: 5px;
.flex-warp-item-box {
width: 100%;
height: 100%;
}
}
}
/* 宽高 100%
------------------------------- */
.w100 {
width: 100% !important;
}
.h100 {
height: 100% !important;
}
.vh100 {
height: 100vh !important;
}
.max100vh {
max-height: 100vh !important;
}
.min100vh {
min-height: 100vh !important;
}
/* 颜色值
------------------------------- */
.color-primary {
color: var(--prev-color-primary);
}
.color-success {
color: var(--prev-color-success);
}
.color-warning {
color: var(--prev-color-warning);
}
.color-danger {
color: var(--prev-color-danger);
}
.color-info {
color: var(--prev-color-info);
}
/* 溢出省略号
------------------------------- */
.one-text-overflow {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.two-text-overflow {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
.overflow {
overflow: hidden !important;
}
/* 字体大小全局样式
------------------------------- */
@for $i from 10 through 32 {
.font#{$i} {
font-size: #{$i}px !important;
}
}
/* 外边距、内边距全局样式
------------------------------- */
@for $i from 5 through 35 {
.mt#{$i} {
margin-top: #{$i}px !important;
}
.mr#{$i} {
margin-right: #{$i}px !important;
}
.mb#{$i} {
margin-bottom: #{$i}px !important;
}
.ml#{$i} {
margin-left: #{$i}px !important;
}
.pt#{$i} {
padding-top: #{$i}px !important;
}
.pr#{$i} {
padding-right: #{$i}px !important;
}
.pb#{$i} {
padding-bottom: #{$i}px !important;
}
.pl#{$i} {
padding-left: #{$i}px !important;
}
}
+1
View File
@@ -0,0 +1 @@
@import 'common/transition.scss';
+102
View File
@@ -0,0 +1,102 @@
/* 页面切换动画
------------------------------- */
.slide-right-enter-active,
.slide-right-leave-active,
.slide-left-enter-active,
.slide-left-leave-active {
will-change: transform;
transition: all 0.3s ease;
}
// slide-right
.slide-right-enter {
opacity: 0;
transform: translateX(-20px);
}
.slide-right-leave-active {
opacity: 0;
transform: translateX(20px);
}
// slide-left
.slide-left-enter-from {
@extend .slide-right-leave-active;
}
.slide-left-leave-to {
@extend .slide-right-enter;
}
// opacitys
.opacitys-enter-active,
.opacitys-leave-active {
will-change: transform;
transition: all 0.3s ease;
}
.opacitys-enter,
.opacitys-leave-active {
opacity: 0;
}
/* Breadcrumb 面包屑过渡动画
------------------------------- */
.breadcrumb-enter-active,
.breadcrumb-leave-active {
transition: all 0.3s;
}
.breadcrumb-enter,
.breadcrumb-leave-active {
opacity: 0;
transform: translateX(20px);
}
.breadcrumb-move {
transition: all 0.3s;
}
.breadcrumb-leave-active {
position: absolute;
}
/* logo 过渡动画
------------------------------- */
@keyframes logoAnimation {
0% {
transform: scale(0);
}
80% {
transform: scale(1.2);
}
100% {
transform: scale(1);
}
}
/* 404、401 过渡动画
------------------------------- */
@keyframes error-num {
0% {
transform: translateY(60px);
opacity: 0;
}
100% {
transform: translateY(0);
opacity: 1;
}
}
@keyframes error-img {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
/* 左右左 link.vue
------------------------------- */
@keyframes toRight {
0% {
left: -5px;
}
50% {
left: 100%;
}
100% {
left: -5px;
}
}
+109
View File
@@ -0,0 +1,109 @@
/* 深色模式样式
------------------------------- */
[data-theme='dark'] {
--prev-bg-menuBar: #191919 !important;
--prev-bg-menuBarColor: #dadada !important;
--prev-bg-topBar: #191919 !important;
--prev-bg-topBarColor: #dadada !important;
--prev-bg-columnsMenuBar: #191919 !important;
--prev-bg-columnsMenuBarColor: #dadada !important;
--prev-bg-main-color: #1f1f1f !important;
--prev-bg-color: rgba(0, 0, 0, 0.3) !important;
--prev-bg-white: #191919 !important;
--prev-color-text-black: #ffffff !important;
--prev-color-text-primary: #dadada !important;
--prev-color-text-regular: #dadada !important;
--prev-color-text-secondary: #a3a3a3 !important;
--prev-color-hover: rgba(0, 0, 0, 0.3) !important;
--prev-color-seting-main: #505050 !important;
--prev-color-seting-aside: #3c3c3c !important;
--prev-color-seting-header: #303030 !important;
--prev-border-color-hover: #616161 !important;
--prev-border-color-base: #333333 !important;
--prev-border-color-light: #333333 !important;
--prev-border-color-lighter: #333333 !important;
--prev-border-color-extra-light: #333333 !important;
// menu
.layout-aside {
border-right: 1px solid var(--prev-border-color-lighter) !important;
}
// drawer
.el-drawer {
border-left: 1px solid var(--prev-border-color-lighter) !important;
}
// button
.el-button--default {
background: var(--prev-bg-white);
color: var(--prev-color-text-primary);
border-color: var(--prev-border-color-lighter);
&:hover,
&:focus {
color: var(--prev-color-primary) !important;
background: var(--prev-color-primary-light-8) !important;
border-color: var(--prev-color-primary-light-6) !important;
}
&:focus {
border-color: var(--prev-color-primary-light-1) !important;
}
&:active {
border-color: var(--prev-color-primary-light-6) !important;
}
}
// tag
.el-tag.el-tag--info {
background-color: var(--prev-bg-white) !important;
border-color: var(--prev-border-color-light) !important;
color: var(--prev-color-text-regular) !important;
}
// switch
.el-switch:not(.is-checked) {
.el-switch__core {
border-color: var(--prev-border-color-base) !important;
background-color: var(--prev-border-color-base) !important;
}
}
// TimePicker
.el-time-spinner__item.active:not(.disabled) {
color: var(--prev-color-primary) !important;
}
// date
.el-date-table td.in-range div,
.el-date-table td.in-range div:hover,
.el-date-table.is-week-mode .el-date-table__row.current div,
.el-date-table.is-week-mode .el-date-table__row:hover div,
.el-date-table td.selected div,
.el-month-table td.in-range div,
.el-month-table td.in-range div:hover {
background-color: var(--prev-bg-color) !important;
}
// transfer
.el-transfer-panel,
.el-transfer-panel .el-transfer-panel__header {
background-color: var(--prev-bg-color) !important;
}
// loading
.el-loading-mask {
background-color: var(--prev-bg-color) !important;
}
// dropdown
.el-dropdown-menu__item:focus,
.el-dropdown-menu__item:not(.is-disabled):hover {
background-color: var(--prev-color-hover) !important;
}
// dialog
.el-dialog,
.el-calendar {
border: 1px solid var(--prev-border-color-lighter);
}
}
+219
View File
@@ -0,0 +1,219 @@
/* 防止页面切换时,滚动条高度不变的问题(滚动条高度非滚动条滚动高度)
------------------------------- */
.el-scrollbar {
overflow: hidden;
position: relative;
height: 100%;
}
.el-scrollbar__wrap {
overflow: auto !important;
overflow-x: hidden !important;
max-height: 100%; /*防止页面切换时,滚动条高度不变的问题(滚动条高度非滚动条滚动高度)*/
}
.el-select-dropdown .el-scrollbar__wrap {
overflow-x: scroll !important;
}
.el-select-dropdown__wrap {
max-height: 274px !important; /*修复Select 选择器高度问题*/
}
.el-autocomplete-suggestion__wrap {
max-height: 280px !important;
}
/* Button 按钮
------------------------------- */
// 第三方字体图标大小
.el-button i.iconfont,
.el-button i.fa {
font-size: 14px !important;
margin-right: 5px;
}
.el-button--medium i.iconfont,
.el-button--medium i.fa {
font-size: 14px !important;
margin-right: 5px;
}
.el-button--small i.iconfont,
.el-button--small i.fa {
font-size: 12px !important;
margin-right: 5px;
}
.el-button--mini i.iconfont,
.el-button--mini i.fa {
font-size: 12px !important;
margin-right: 5px;
}
/* Dialog 对话框
------------------------------- */
.el-overlay,
.el-dialog__wrapper {
display: flex;
align-items: center;
justify-content: center;
.el-dialog {
margin: 0 auto !important;
.el-dialog__body {
padding: 20px !important;
}
}
}
.el-dialog__body {
max-height: calc(90vh - 111px) !important;
overflow-y: auto;
overflow-x: hidden;
}
/* Alert 警告
------------------------------- */
.el-alert--warning.is-light {
border: 1px solid rgba(230, 162, 60, 0.3) !important;
}
.el-alert--success.is-light {
border: 1px solid rgba(103, 194, 58, 0.3) !important;
}
.el-alert--info.is-light {
border: 1px solid rgba(144, 147, 153, 0.3) !important;
}
.el-alert--error.is-light {
border: 1px solid rgba(245, 108, 108, 0.3) !important;
}
/* Table 表格
------------------------------- */
.el-table-column--selection {
.el-checkbox {
margin-right: unset !important;
}
}
.el-table::before,
.el-table--group::after,
.el-table--border::after {
z-index: 99 !important;
}
/* 下拉选择器/时间选择器滚动条
------------------------------- */
.el-select-dropdown .el-scrollbar__wrap,
.el-picker-panel .el-scrollbar__wrap {
overflow-x: scroll !important;
}
/* NavMenu 导航菜单
------------------------------- */
// 默认样式修改
.el-menu {
border-right: none !important;
}
.el-menu-item,
.el-submenu__title {
height: 50px !important;
line-height: 50px !important;
color: var(--prev-bg-menuBarColor) !important;
transition: none !important;
}
// horizontal 水平方向时
.el-menu--horizontal > .el-menu-item.is-active,
.el-menu--horizontal > .el-submenu.is-active .el-submenu__title {
border-bottom: 3px solid !important;
border-bottom-color: var(--prev-color-primary) !important;
color: var(--prev-color-primary) !important;
}
.el-menu--horizontal .el-menu-item:not(.is-disabled):focus,
.el-menu--horizontal .el-menu-item:not(.is-disabled):hover,
.el-menu--horizontal > .el-submenu:focus .el-submenu__title,
.el-menu--horizontal > .el-submenu:hover .el-submenu__title,
.el-menu--horizontal .el-menu .el-menu-item.is-active,
.el-menu--horizontal .el-menu .el-submenu.is-active > .el-submenu__title {
color: var(--prev-color-primary) !important;
}
.el-menu.el-menu--horizontal {
border-bottom: none !important;
}
.el-menu--horizontal > .el-menu-item,
.el-menu--horizontal > .el-submenu .el-submenu__title {
color: var(--bg-topBarColor) !important;
}
// 外部链接时
.el-menu-item a,
.el-menu-item a:hover,
.el-menu-item i,
.el-submenu__title i {
color: inherit;
text-decoration: none;
}
.el-menu-item a {
width: 86%;
display: inline-block;
}
// 默认 hover 时
.el-menu-item:hover,
.el-submenu__title:hover {
color: var(--prev-color-primary) !important;
background-color: transparent !important;
i {
color: var(--prev-color-primary) !important;
}
}
// 高亮时
.el-menu-item.is-active {
color: var(--prev-color-primary) !important;
}
.el-active-extend {
color: #ffffff !important;
background-color: var(--prev-color-primary) !important;
i {
color: #ffffff !important;
}
}
#add-is-active {
@extend .el-active-extend;
&:hover {
@extend .el-active-extend;
}
}
// 菜单收起时且是a链接
.is-dark a {
color: #ffffff !important;
text-decoration: none;
}
// 菜单收起时鼠标经过背景颜色/字体颜色
.el-menu--vertical {
background: var(--prev-bg-menuBar) !important;
}
.el-menu--horizontal {
.el-menu {
background: var(--bg-topBar) !important;
}
.el-menu-item,
.el-submenu__title {
color: var(--bg-topBarColor);
}
}
// 第三方图标字体间距/大小设置
.el-menu-item .iconfont,
.el-submenu .iconfont,
.el-menu-item .fa,
.el-submenu__title .fa {
font-size: 14px !important;
display: inline-block;
vertical-align: middle;
margin-right: 5px;
width: 24px;
text-align: center;
}
// element plus 本身字体图标
.el-submenu [class^='el-icon-'],
.el-menu-item [class^='el-icon-'] {
font-size: 14px !important;
}
// 去掉离开浏览器时,菜单的默认高亮
.el-menu-item:focus {
background-color: transparent !important;
}
/* Alert 警告
------------------------------- */
.el-alert__title {
word-break: break-all;
}
+7
View File
@@ -0,0 +1,7 @@
@import './base.scss';
@import './app.scss';
@import './other.scss';
@import './element.scss';
@import './media/media.scss';
@import './variables.scss';
@import './dark.scss';
+56
View File
@@ -0,0 +1,56 @@
.loading-prev {
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
z-index: 2;
background-color: var(--prev-bg-white);
}
.loading-prev .loading-prev-box {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.loading-prev .loading-prev-box-warp {
width: 80px;
height: 80px;
}
.loading-prev .loading-prev-box-warp .loading-prev-box-item {
width: 33.333333%;
height: 33.333333%;
background: var(--prev-color-primary);
float: left;
animation: loading-prev-animation 1.2s infinite ease;
border-radius: 1px;
}
.loading-prev .loading-prev-box-warp .loading-prev-box-item:nth-child(7) {
animation-delay: 0s;
}
.loading-prev .loading-prev-box-warp .loading-prev-box-item:nth-child(4),
.loading-prev .loading-prev-box-warp .loading-prev-box-item:nth-child(8) {
animation-delay: 0.1s;
}
.loading-prev .loading-prev-box-warp .loading-prev-box-item:nth-child(1),
.loading-prev .loading-prev-box-warp .loading-prev-box-item:nth-child(5),
.loading-prev .loading-prev-box-warp .loading-prev-box-item:nth-child(9) {
animation-delay: 0.2s;
}
.loading-prev .loading-prev-box-warp .loading-prev-box-item:nth-child(2),
.loading-prev .loading-prev-box-warp .loading-prev-box-item:nth-child(6) {
animation-delay: 0.3s;
}
.loading-prev .loading-prev-box-warp .loading-prev-box-item:nth-child(3) {
animation-delay: 0.4s;
}
@keyframes loading-prev-animation {
0%,
70%,
100% {
transform: scale3D(1, 1, 1);
}
35% {
transform: scale3D(0, 0, 1);
}
}
+12
View File
@@ -0,0 +1,12 @@
@import './index.scss';
/* 页面宽度小于800px
------------------------------- */
@media screen and (max-width: 800px) {
.el-dialog {
width: 90%;
}
.el-dialog.is-fullscreen {
width: 100% !important;
}
}
+35
View File
@@ -0,0 +1,35 @@
@import './index.scss';
/* 页面宽度小于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;
}
}
}
/* 页面宽度大于768px小于992px
------------------------------- */
@media screen and (min-width: $sm) and (max-width: $md) {
.error {
.error-flex {
padding-left: 30px !important;
}
}
}
+19
View File
@@ -0,0 +1,19 @@
@import './index.scss';
/* 页面宽度小于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 {
display: unset !important;
}
.login-form .el-form-item {
display: block !important;
}
}
+35
View File
@@ -0,0 +1,35 @@
@import './index.scss';
/* 页面宽度小于1200px
------------------------------- */
@media screen and (max-width: $lg) {
.home-recommend-row {
.home-recommend {
margin-bottom: 15px;
}
& .el-col:last-of-type,
& .el-col:nth-last-child(2) {
.home-recommend {
margin-bottom: 0;
}
}
}
.home-lg {
margin-bottom: 15px;
}
}
/* 页面宽度小于992px
------------------------------- */
@media screen and (max-width: $md) {
.home-recommend-row {
& .el-col:nth-last-child(2) {
margin-bottom: 15px;
}
& .el-col:last-of-type {
.home-recommend {
margin-bottom: 0;
}
}
}
}
+37
View File
@@ -0,0 +1,37 @@
/* 栅格布局(媒体查询变量)
* $xs <768px 响应式栅格
* $sm ≥768px 响应式栅格
* $md ≥992px 响应式栅格
* $lg ≥1200px 响应式栅格
* $xl ≥1920px 响应式栅格
------------------------------- */
$xs: 576px;
$sm: 768px;
$md: 992px;
$lg: 1200px;
$xl: 1920px;
/* 页面宽度小于576px
------------------------------- */
@media screen and (max-width: $xs) {
}
/* 页面宽度小于768px
------------------------------- */
@media screen and (max-width: $sm) {
}
/* 页面宽度大于768px小于992px
------------------------------- */
@media screen and (min-width: $sm) and (max-width: $md) {
}
/* 页面宽度大于992px小于1200px
------------------------------- */
@media screen and (min-width: $md) and (max-width: $lg) {
}
/* 页面宽度大于1920px
------------------------------- */
@media screen and (min-width: $xl) {
}
+55
View File
@@ -0,0 +1,55 @@
@import './index.scss';
/* 页面宽度小于576px
------------------------------- */
@media screen and (max-width: $xs) {
// 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;
}
}
}
/* 页面宽度小于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;
}
}
}
+32
View File
@@ -0,0 +1,32 @@
@import './index.scss';
/* 页面宽度小于576px
------------------------------- */
@media screen and (max-width: $xs) {
.login-weaper {
height: 420px !important;
.login-left {
display: none !important;
}
.login-right {
width: 100% !important;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
.login-main {
width: 94% !important;
}
}
}
}
/* 页面宽度大于576px小于992px
------------------------------- */
@media screen and (min-width: $xs) and (max-width: $md) {
.login-left {
display: none !important;
}
.login-right {
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
}
+7
View File
@@ -0,0 +1,7 @@
@import './login.scss';
@import './error.scss';
@import './home.scss';
@import './layout.scss';
@import './scrollbar.scss';
@import './dialog.scss';
@import './form.scss';
+13
View File
@@ -0,0 +1,13 @@
@import './index.scss';
/* 页面宽度小于768px
------------------------------- */
@media screen and (max-width: $sm) {
// element plus scrollbar
.el-scrollbar__bar.is-vertical {
width: 2px !important;
}
.el-scrollbar__bar.is-horizontal {
height: 2px !important;
}
}
View File
+952
View File
@@ -0,0 +1,952 @@
/* Button 按钮
------------------------------- */
// text
.el-button--text {
color: var(--prev-color-primary);
&:focus,
&:hover {
color: var(--prev-color-primary-light-3);
}
}
.el-button--text:active {
color: var(--prev-color-primary-light-3);
}
// default
.el-button--default:hover,
.el-button--default:focus {
color: var(--prev-color-primary);
background: var(--prev-color-primary-light-8);
border-color: var(--prev-color-primary-light-6);
}
.el-button--default.is-plain:hover,
.el-button--default.is-plain:focus {
color: var(--prev-color-primary);
background: var(--prev-bg-white);
border-color: var(--prev-color-primary-light-1);
}
.el-button--default:active {
color: var(--prev-color-primary);
background: var(--prev-bg-white);
border-color: var(--prev-color-primary-light-1);
}
// primary
.el-button--primary {
color: var(--prev-color-text-white) !important;
background: var(--prev-color-primary) !important;
border-color: var(--prev-color-primary) !important;
&:hover,
&:focus {
color: var(--prev-color-text-white) !important;
background: var(--prev-color-primary-light-3) !important;
border-color: var(--prev-color-primary-light-3) !important;
}
}
.el-button--primary.is-plain {
color: var(--prev-color-primary) !important;
background: var(--prev-color-primary-light-8) !important;
border-color: var(--prev-color-primary-light-6) !important;
&:hover,
&:focus {
color: var(--prev-color-text-white) !important;
background: var(--prev-color-primary) !important;
border-color: var(--prev-color-primary) !important;
}
}
.el-button--primary.is-disabled,
.el-button--primary.is-disabled:active,
.el-button--primary.is-disabled:focus,
.el-button--primary.is-disabled:hover {
color: var(--prev-color-primary) !important;
background: var(--prev-color-primary-light-7) !important;
border-color: var(--prev-color-primary-light-7) !important;
}
.el-button--primary.is-active,
.el-button--primary:active {
color: var(--prev-color-text-white) !important;
background: var(--prev-color-primary) !important;
border-color: var(--prev-color-primary) !important;
}
.el-button.is-disabled.is-plain,
.el-button.is-disabled.is-plain:focus,
.el-button.is-disabled.is-plain:hover {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-lighter);
color: var(--prev-color-text-placeholder);
}
/* Link 文字链接
------------------------------- */
// default
.el-link.el-link--default:hover {
color: var(--prev-color-primary-light-3);
}
// primary
.el-link.el-link--primary {
color: var(--prev-color-primary);
&:hover {
color: var(--prev-color-primary-light-3);
}
}
.el-link.el-link--default::after,
.el-link.is-underline:hover::after,
.el-link.el-link--primary.is-underline:hover::after,
.el-link.el-link--primary::after {
border-color: var(--prev-color-primary);
}
/* Radio 单选框
------------------------------- */
.el-radio,
.el-checkbox {
color: var(--prev-color-text-regular);
}
.el-radio__input.is-checked + .el-radio__label,
.el-radio-button__inner:hover {
color: var(--prev-color-primary);
}
.el-radio__input.is-checked .el-radio__inner {
background-color: var(--prev-color-primary);
border-color: var(--prev-color-primary);
}
.el-radio-button__orig-radio:checked + .el-radio-button__inner {
color: var(--prev-color-text-white);
background-color: var(--prev-color-primary);
border-color: var(--prev-color-primary);
box-shadow: -1px 0 0 0 var(--prev-color-primary);
}
.el-radio.is-bordered.is-checked,
.el-radio__inner:hover {
border-color: var(--prev-color-primary);
}
.el-radio-button__inner,
.el-checkbox-button__inner {
background-color: var(--prev-bg-white);
color: var(--prev-color-text-regular);
border-color: var(--prev-border-color-base);
}
.el-radio-button:first-child .el-radio-button__inner,
.el-checkbox-button:first-child .el-checkbox-button__inner {
border-left-color: var(--prev-border-color-base);
}
.el-radio.is-bordered,
.el-checkbox.is-bordered {
border-color: var(--prev-border-color-base);
}
/* Checkbox 多选框
------------------------------- */
.el-checkbox__input.is-checked + .el-checkbox__label,
.el-checkbox-button__inner:hover {
color: var(--prev-color-primary);
}
.el-checkbox__input.is-checked .el-checkbox__inner {
background-color: var(--prev-color-primary);
border-color: var(--prev-color-primary);
}
.el-checkbox__input.is-focus .el-checkbox__inner,
.el-checkbox__inner:hover,
.el-checkbox.is-bordered.is-checked,
.el-checkbox-button.is-focus .el-checkbox-button__inner {
border-color: var(--prev-color-primary);
}
.el-checkbox-button.is-checked .el-checkbox-button__inner {
color: var(--prev-color-text-white);
background-color: var(--prev-color-primary);
border-color: var(--prev-color-primary);
box-shadow: -1px 0 0 0 var(--prev-color-primary);
}
.el-checkbox-button.is-checked:first-child .el-checkbox-button__inner {
border-left-color: var(--prev-color-primary);
}
.el-checkbox__input.is-checked .el-checkbox__inner,
.el-checkbox__input.is-indeterminate .el-checkbox__inner {
background-color: var(--prev-color-primary);
border-color: var(--prev-color-primary);
}
.el-checkbox-button.is-disabled .el-checkbox-button__inner {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-base);
}
/* Input 输入框、InputNumber 计数器
------------------------------- */
// input-number
.el-input__inner:focus,
.el-input-number__decrease:hover:not(.is-disabled) ~ .el-input .el-input__inner:not(.is-disabled),
.el-input-number__increase:hover:not(.is-disabled) ~ .el-input .el-input__inner:not(.is-disabled),
.el-textarea__inner:focus {
border-color: var(--prev-color-primary) !important;
}
.el-input-number__increase:hover,
.el-input-number__decrease:hover {
color: var(--prev-color-primary);
}
.el-input-number__decrease,
.el-input-number__increase {
background-color: var(--prev-bg-color);
border-color: var(--prev-border-color-base) !important;
}
// input
.el-input__inner,
.el-textarea__inner {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-base);
color: var(--prev-color-text-regular);
&:hover {
border-color: var(--prev-border-color-hover);
}
}
.el-input.is-disabled .el-input__inner,
.el-textarea.is-disabled .el-textarea__inner {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-base);
}
.el-input-group__append,
.el-input-group__prepend {
background-color: var(--prev-bg-color);
color: var(--prev-color-text-regular);
border-color: var(--prev-border-color-base);
}
.el-input .el-input__count .el-input__count-inner {
background-color: var(--prev-bg-color);
}
// autocomplete
.el-autocomplete-suggestion {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-base);
}
.el-autocomplete-suggestion__wrap {
max-height: 280px !important;
}
// scss 循环
$positions: 'top', 'right', 'bottom', 'left';
@each $i in $positions {
.el-popper[x-placement^='#{$i}'] .popper__arrow {
border-#{$i}-color: var(--prev-border-color-base);
&::after {
border-#{$i}-color: var(--prev-bg-white);
}
}
}
.el-autocomplete-suggestion li {
color: var(--prev-color-text-regular);
}
.el-autocomplete-suggestion li.highlighted,
.el-autocomplete-suggestion li:hover {
background-color: var(--prev-color-hover);
}
/* Select 选择器
------------------------------- */
.el-range-editor.is-active,
.el-range-editor.is-active:hover,
.el-select .el-input.is-focus .el-input__inner,
.el-select .el-input__inner:focus {
border-color: var(--prev-color-primary);
}
.el-select-dropdown__item.selected {
color: var(--prev-color-primary);
}
.el-select-dropdown {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-light);
}
.el-select-dropdown__item {
color: var(--prev-color-text-regular);
}
.el-select-dropdown__item.hover,
.el-select-dropdown__item:hover {
background-color: var(--prev-color-hover);
}
.el-select-dropdown__item.is-disabled:hover {
background-color: var(--prev-bg-white);
}
.el-select .el-input.is-disabled .el-input__inner:hover {
border-color: var(--prev-border-color-light);
}
.el-select:hover .el-input__inner {
border-color: var(--prev-border-color-hover);
}
.el-select-dropdown.is-multiple .el-select-dropdown__item.selected {
background-color: var(--prev-bg-white);
}
.el-select-dropdown.is-multiple .el-select-dropdown__item.selected.hover {
background-color: var(--prev-color-hover);
}
.el-select-group__wrap:not(:last-of-type)::after {
background: var(--prev-border-color-light);
}
/* Cascader 级联选择器
------------------------------- */
.el-cascader .el-input .el-input__inner:focus,
.el-cascader .el-input.is-focus .el-input__inner {
border-color: var(--prev-color-primary);
}
.el-cascader-node.in-active-path,
.el-cascader-node.is-active,
.el-cascader-node.is-selectable.in-checked-path {
color: var(--prev-color-primary);
}
.el-cascader__dropdown {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-light);
}
.el-cascader-menu {
border-color: var(--prev-border-color-light);
color: var(--prev-color-text-regular);
}
.el-cascader-node:not(.is-disabled):focus,
.el-cascader-node:not(.is-disabled):hover {
background-color: var(--prev-color-hover);
}
/* Switch 开关
------------------------------- */
.el-switch.is-checked .el-switch__core {
border-color: var(--prev-color-primary);
background-color: var(--prev-color-primary);
}
.el-switch__label.is-active {
color: var(--prev-color-primary);
}
/* Slider 滑块
------------------------------- */
.el-slider__bar {
background-color: var(--prev-color-primary);
}
.el-slider__button {
border-color: var(--prev-color-primary);
}
.el-slider__runway {
background-color: var(--prev-border-color-light);
}
.el-slider__marks-text {
color: var(--prev-color-text-secondary);
}
/* TimePicker 时间选择器
------------------------------- */
.el-time-panel__btn.confirm,
.el-time-spinner__arrow:hover,
.time-select-item.selected:not(.disabled) {
color: var(--prev-color-primary);
}
.el-picker-panel {
border-color: var(--prev-border-color-light);
background-color: var(--prev-bg-white);
color: var(--prev-color-text-regular);
}
.time-select-item:hover,
.el-time-spinner__item:hover:not(.disabled):not(.active),
.el-time-spinner__wrapper.is-arrow .el-time-spinner__item:hover:not(.disabled):not(.active) {
background-color: var(--prev-color-hover);
}
.el-time-panel {
border-color: var(--prev-border-color-light);
background-color: var(--prev-bg-white);
}
.el-time-panel__footer,
.el-time-panel__content::after,
.el-time-panel__content::before,
.el-time-range-picker__body {
border-color: var(--prev-border-color-light);
}
.el-time-panel__btn,
.el-date-editor .el-range-separator {
color: var(--prev-color-text-primary);
}
.el-date-editor .el-range-input {
background-color: var(--prev-bg-white);
color: var(--prev-color-text-primary);
}
/* DatePicker 日期选择器
------------------------------- */
.el-date-table td.today span,
.el-date-table td.available:hover,
.el-date-picker__header-label.active,
.el-date-picker__header-label:hover,
.el-picker-panel__icon-btn:hover,
.el-year-table td.today .cell,
.el-year-table td .cell:hover,
.el-year-table td.current:not(.disabled) .cell,
.el-month-table td .cell:hover,
.el-month-table td.today .cell,
.el-month-table td.current:not(.disabled) .cell,
.el-picker-panel__shortcut:hover {
color: var(--prev-color-primary);
}
.el-date-table td.current:not(.disabled) span,
.el-date-table td.selected span {
color: var(--prev-color-text-white);
background-color: var(--prev-color-primary);
}
.el-date-table td.end-date span,
.el-date-table td.start-date span,
.el-month-table td.end-date .cell,
.el-month-table td.start-date .cell {
background-color: var(--prev-color-primary);
}
.el-date-table td.in-range div,
.el-date-table td.in-range div:hover,
.el-date-table.is-week-mode .el-date-table__row.current div,
.el-date-table.is-week-mode .el-date-table__row:hover div,
.el-date-table td.selected div {
background-color: var(--prev-color-primary-light-9);
}
.el-date-table th,
.el-date-picker__header--bordered,
.el-date-range-picker__content.is-left,
.el-date-picker__time-header,
.el-date-range-picker__time-header {
border-color: var(--prev-border-color-lighter);
}
.el-date-table th,
.el-date-picker__header-label,
.el-picker-panel__shortcut,
.el-month-table td .cell,
.el-year-table td .cell {
color: var(--prev-color-text-regular);
}
.el-date-table td.next-month,
.el-date-table td.prev-month {
color: var(--prev-border-color-hover);
}
.el-picker-panel__icon-btn {
color: var(--prev-color-text-primary);
}
.el-date-table td.disabled div {
background-color: var(--prev-bg-color);
}
.el-picker-panel [slot='sidebar'],
.el-picker-panel__sidebar,
.el-picker-panel__footer {
border-color: var(--prev-border-color-light);
background-color: var(--prev-bg-white);
}
.el-month-table td.end-date .cell,
.el-month-table td.start-date .cell {
color: var(--prev-color-text-white);
}
/* Upload 上传
------------------------------- */
.el-upload-list__item.is-success .el-upload-list__item-name:focus,
.el-upload-list__item.is-success .el-upload-list__item-name:hover,
.el-upload-list__item .el-icon-close-tip,
.el-upload-dragger .el-upload__text em {
color: var(--prev-color-primary);
}
.el-upload--picture-card,
.el-upload-dragger {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-light);
i {
color: var(--prev-color-text-regular);
}
}
.el-upload--picture-card:hover,
.el-upload:focus {
color: var(--prev-color-primary);
border-color: var(--prev-color-primary);
}
.el-upload-dragger:hover,
.el-upload:focus .el-upload-dragger {
border-color: var(--prev-color-primary);
}
.el-upload__tip,
.el-upload-list__item,
.el-upload-dragger .el-upload__text,
.el-upload-list__item-name,
.el-upload-list__item .el-icon-close {
color: var(--prev-color-text-regular);
}
.el-upload-list__item:hover {
background-color: var(--prev-bg-color);
}
/* ColorPicker 颜色选择器
------------------------------- */
.el-color-picker__trigger {
border-color: var(--prev-border-color-light);
}
/* Transfer 穿梭框
------------------------------- */
.el-transfer-panel__item:hover {
color: var(--prev-color-primary);
}
.el-transfer-panel,
.el-transfer-panel .el-transfer-panel__header {
border-color: var(--prev-border-color-lighter);
}
.el-transfer-panel .el-transfer-panel__footer {
border-color: var(--prev-border-color-lighter);
background-color: var(--prev-bg-white);
}
.el-transfer-panel .el-transfer-panel__header .el-checkbox .el-checkbox__label {
color: var(--prev-color-text-primary);
}
/* Form 表单
------------------------------- */
.el-form {
.el-form-item:last-of-type {
margin-bottom: 0 !important;
}
}
.el-form-item__label {
color: var(--prev-color-text-regular);
}
/* Table 表格
------------------------------- */
.el-table {
color: var(--prev-color-text-regular);
}
.el-table .descending .sort-caret.descending {
border-top-color: var(--prev-color-primary);
}
.el-table .ascending .sort-caret.ascending {
border-bottom-color: var(--prev-color-primary);
}
.el-table thead {
color: var(--prev-color-text-secondary);
}
.el-table td.el-table__cell,
.el-table th.el-table__cell.is-leaf,
.el-table--border,
.el-table--group {
border-color: var(--prev-border-color-lighter) !important;
}
.el-table th.el-table__cell,
.el-table tr {
background-color: var(--prev-bg-white);
}
.el-table--striped .el-table__body tr.el-table__row--striped td.el-table__cell,
.el-table--enable-row-hover .el-table__body tr:hover > td.el-table__cell {
background-color: var(--prev-bg-color);
}
.el-table--border::after,
.el-table--group::after,
.el-table::before {
background-color: var(--prev-border-color-lighter);
}
/* Tag 标签
------------------------------- */
// primary
.el-tag {
color: var(--prev-color-primary);
background-color: var(--prev-color-primary-light-8);
border-color: var(--prev-color-primary-light-6);
}
.el-tag .el-tag__close {
color: var(--prev-color-primary);
&:hover {
color: var(--prev-color-text-white);
background-color: var(--prev-color-primary);
}
}
.el-tag--dark {
color: var(--prev-color-text-white);
background-color: var(--prev-color-primary);
}
.el-tag--dark .el-tag__close {
color: var(--prev-color-text-white);
&:hover {
background-color: var(--prev-color-primary-light-3);
}
}
.el-tag--plain {
color: var(--prev-color-primary);
background-color: var(--prev-bg-white);
border-color: var(--prev-color-primary-light-3);
}
/* Progress 进度条
------------------------------- */
// primary
.el-progress-bar__inner {
background-color: var(--prev-color-primary) !important;
}
.el-progress-bar__outer {
background-color: var(--prev-border-color-lighter);
}
.el-progress__text {
color: var(--prev-color-text-regular);
}
/* Tree 树形控件
------------------------------- */
.el-tree {
background-color: var(--prev-bg-white);
color: var(--prev-color-text-regular);
}
.el-tree-node__content:hover,
.el-tree-node:focus > .el-tree-node__content {
background-color: var(--prev-bg-color);
}
/* Pagination 分页
------------------------------- */
.el-pager li.active,
.el-pager li:hover,
.el-pagination button:hover,
.el-pagination.is-background .el-pager li:not(.disabled):hover {
color: var(--prev-color-primary);
}
.el-pagination__sizes .el-input .el-input__inner:hover {
border-color: var(--prev-color-primary);
}
.el-pagination.is-background .el-pager li:not(.disabled).active {
background-color: var(--prev-color-primary);
color: var(--prev-color-text-white);
}
.el-pagination__total,
.el-pagination__jump {
color: var(--prev-color-text-regular);
}
.el-pagination button:disabled,
.el-pagination .btn-next,
.el-pagination .btn-prev {
background-color: var(--prev-bg-white);
}
.el-pagination .btn-next,
.el-pagination .btn-prev {
color: var(--prev-color-text-primary);
}
.el-pager li {
background-color: var(--prev-bg-white);
color: var(--prev-color-text-primary);
}
/* Badge 标记
------------------------------- */
// primary
.el-badge__content--primary {
background-color: var(--prev-color-primary);
}
/* Loading 加载
------------------------------- */
.el-loading-spinner .path {
stroke: var(--prev-color-primary);
}
.el-loading-spinner .el-loading-text,
.el-loading-spinner i {
color: var(--prev-color-primary);
}
/* Message 消息提示
------------------------------- */
// default/info
.el-message {
min-width: unset !important;
padding: 15px !important;
}
/* MessageBox 弹框
------------------------------- */
.el-message-box__headerbtn:focus .el-message-box__close,
.el-message-box__headerbtn:hover .el-message-box__close {
color: var(--prev-color-primary);
}
.el-message-box {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-lighter);
}
.el-message-box__title {
color: var(--prev-color-text-primary);
}
.el-message-box__content {
color: var(--prev-color-text-regular);
}
/* Notification 通知
------------------------------- */
.el-notification {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-lighter);
.el-notification__title {
color: var(--prev-color-text-primary);
}
.el-notification__content {
color: var(--prev-color-text-regular);
}
}
/* Tabs 标签页
------------------------------- */
.el-tabs__item.is-active,
.el-tabs__item:hover,
.el-tabs--border-card > .el-tabs__header .el-tabs__item.is-active,
.el-tabs--border-card > .el-tabs__header .el-tabs__item:not(.is-disabled):hover {
color: var(--prev-color-primary);
}
.el-tabs__active-bar {
background-color: var(--prev-color-primary);
}
.el-tabs__nav-wrap::after {
height: 1px !important;
}
.el-tabs__item {
color: var(--prev-color-text-primary);
}
.el-tabs__nav-wrap::after {
background-color: var(--prev-border-color-light);
}
.el-tabs--card > .el-tabs__header .el-tabs__item.is-active,
.el-tabs--card > .el-tabs__header .el-tabs__item,
.el-tabs--card > .el-tabs__header,
.el-tabs--card > .el-tabs__header .el-tabs__nav {
border-color: var(--prev-bg-color);
}
.el-tabs--border-card {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-base);
}
.el-tabs--border-card > .el-tabs__header {
background-color: var(--prev-bg-color);
border-color: var(--prev-border-color-light);
}
.el-tabs--border-card > .el-tabs__header .el-tabs__item.is-active {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-base);
}
/* Breadcrumb 面包屑
------------------------------- */
.el-breadcrumb__inner a:hover,
.el-breadcrumb__inner.is-link:hover {
color: var(--prev-color-primary);
}
.el-breadcrumb__inner a,
.el-breadcrumb__inner.is-link {
color: var(--bg-topBarColor);
font-weight: normal;
}
.el-breadcrumb__inner a,
.el-breadcrumb__inner.is-link {
color: var(--prev-color-text-black);
opacity: 0.7;
}
.el-breadcrumb__separator {
color: var(--prev-border-color-hover);
}
/* PageHeader 页头
------------------------------- */
.el-page-header__left {
color: var(--prev-color-text-black);
&::after {
background-color: var(--prev-border-color-base);
}
}
.el-page-header__content {
color: var(--prev-color-text-primary);
}
/* Dropdown 下拉菜单
------------------------------- */
.el-dropdown-menu__item:focus,
.el-dropdown-menu__item:not(.is-disabled):hover {
color: var(--prev-color-primary);
background-color: var(--prev-color-primary-light-9);
}
.el-dropdown-menu {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-lighter);
}
.el-dropdown-menu__item {
color: var(--prev-color-text-regular);
}
.el-dropdown-menu__item--divided {
border-color: var(--prev-border-color-lighter);
}
.el-dropdown-menu__item--divided:before {
background-color: var(--prev-bg-white);
}
/* Steps 步骤条
------------------------------- */
// default
.el-step__title.is-finish,
.el-step__description.is-finish,
.el-step__head.is-finish {
color: var(--prev-color-primary);
}
.el-step__head.is-finish {
border-color: var(--prev-color-primary);
}
/* Dialog 对话框
------------------------------- */
.el-dialog__headerbtn:focus .el-dialog__close,
.el-dialog__headerbtn:hover .el-dialog__close {
color: var(--prev-color-primary);
}
.el-dialog {
background-color: var(--prev-bg-white);
}
.el-dialog__title {
color: var(--prev-color-text-primary);
}
.el-dialog__body {
color: var(--prev-color-text-regular);
}
/* Popover 弹出框
------------------------------- */
.el-popover {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-lighter);
color: var(--prev-color-text-regular);
}
.el-popover__title {
color: var(--prev-color-text-primary);
}
/* Card 卡片
------------------------------- */
.el-card {
color: var(--prev-color-text-primary);
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-lighter);
}
.el-card__header {
padding: 15px 20px;
border-bottom-color: var(--prev-border-color-lighter);
}
/* Collapse 折叠面板
------------------------------- */
.el-collapse {
border-color: var(--prev-border-color-lighter);
}
.el-collapse-item__header {
color: var(--prev-color-text-primary);
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-lighter);
}
.el-collapse-item__wrap {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-lighter);
}
.el-collapse-item__content {
color: var(--prev-color-text-primary);
}
/* Timeline 时间线
------------------------------- */
// primary
.el-timeline-item__node--primary {
background-color: var(--prev-color-primary);
}
.el-timeline-item__content {
color: var(--prev-color-text-primary);
}
/* Divider 分割线
------------------------------- */
.el-divider {
background-color: var(--prev-border-color-base);
}
/* Calendar 日历
------------------------------- */
.el-calendar-table td {
color: var(--prev-color-text-black);
}
.el-calendar-table td.is-today {
color: var(--prev-color-primary) !important;
background-color: var(--prev-color-primary-light-9);
}
.el-calendar-table .el-calendar-day:hover,
.el-calendar-table td.is-selected {
background-color: var(--prev-color-primary-light-9);
color: var(--prev-color-primary) !important;
}
.el-calendar {
background-color: var(--prev-bg-white);
}
.el-calendar__title {
color: var(--prev-color-text-black);
}
.el-calendar__header,
.el-calendar-table tr:first-child td,
.el-calendar-table td,
.el-calendar-table tr td:first-child {
border-color: var(--prev-border-color-lighter);
}
.el-calendar-table thead th {
color: var(--prev-color-text-regular);
}
.el-calendar-table:not(.is-range) td.next,
.el-calendar-table:not(.is-range) td.prev {
color: var(--prev-color-text-placeholder);
}
.el-calendar__button-group {
.el-button {
color: var(--prev-color-text-regular);
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-base);
&:focus,
&:hover {
color: var(--prev-color-primary) !important;
background: var(--prev-color-primary-light-8) !important;
border-color: var(--prev-color-primary-light-6) !important;
}
&:active {
color: var(--prev-color-primary-light-3);
}
}
}
/* Backtop 回到顶部
------------------------------- */
.el-backtop {
color: var(--prev-color-primary);
&:hover {
background-color: var(--prev-color-primary-light-9);
}
}
/* scrollbar
------------------------------- */
.el-scrollbar__wrap {
overflow-x: hidden !important;
max-height: 100%; /*防止页面切换时,滚动条高度不变的问题(滚动条高度非滚动条滚动高度)*/
}
.el-select-dropdown .el-scrollbar__wrap {
overflow-x: scroll !important;
}
/* Drawer 抽屉
------------------------------- */
.el-drawer,
.el-divider__text {
background-color: var(--prev-bg-white);
}
.el-divider__text {
color: var(--prev-color-text-primary);
}
.el-drawer__close-btn:hover {
color: var(--prev-color-primary);
}
.el-drawer__body {
width: 100%;
height: 100%;
overflow: auto;
}
.el-drawer__header {
padding: 0 15px !important;
height: 50px;
display: flex;
align-items: center;
margin-bottom: 0 !important;
border-bottom: 1px solid var(--prev-border-color-lighter);
color: var(--prev-color-text-primary);
}
+4
View File
@@ -0,0 +1,4 @@
import { Local } from '@/utils/storage.js';
// 全局组件大小
export const globalComponentSize = Local.get('themeConfigPrev') ? Local.get('themeConfigPrev').globalComponentSize : '';
+134
View File
@@ -0,0 +1,134 @@
/*
* 年(Y) 可用1-4个占位符
* 月(m)、日(d)、小时(H)、分(M)、秒(S) 可用1-2个占位符
* 星期(W) 可用1-3个占位符
* 季度(q为阿拉伯数字,Q为中文数字)可用1或4个占位符
*
* let date = new Date()
* formatDate(date, "YYYY-mm-dd HH:MM:SS") // 2020-02-09 14:04:23
* formatDate(date, "YYYY-mm-dd HH:MM:SS Q") // 2020-02-09 14:09:03 一
* formatDate(date, "YYYY-mm-dd HH:MM:SS WWW") // 2020-02-09 14:45:12 星期日
* formatDate(date, "YYYY-mm-dd HH:MM:SS QQQQ") // 2020-02-09 14:09:36 第一季度
* formatDate(date, "YYYY-mm-dd HH:MM:SS WWW QQQQ") // 2020-02-09 14:46:12 星期日 第一季度
*/
export function formatDate(date, format) {
let we = date.getDay(); // 星期
let qut = Math.floor((date.getMonth() + 3) / 3).toString(); // 季度
const opt = {
'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 = {
// 中文数字 (星期)
'0': '日',
'1': '一',
'2': '二',
'3': '三',
'4': '四',
'5': '五',
'6': '六',
};
const quarter = {
// 中文数字(季度)
'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)) {
// 输入一个Q,只输出一个中文数字,输入4个Q,则拼接上字符串
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);
if (r) {
// 若输入的长度不为1,则前面补零
format = format.replace(r[1], RegExp.$1.length == 1 ? opt[k] : opt[k].padStart(RegExp.$1.length, '0'));
}
}
return format;
}
/**
* 10秒: 10 * 1000
* 1分: 60 * 1000
* 1小时: 60 * 60 * 1000
* 24小时:60 * 60 * 24 * 1000
* 3天: 60 * 60* 24 * 1000 * 3
*
* let data = new Date()
* formatPast(data) // 刚刚
* formatPast(data - 11 * 1000) // 11秒前
* formatPast(data - 2 * 60 * 1000) // 2分钟前
* formatPast(data - 60 * 60 * 2 * 1000) // 2小时前
* formatPast(data - 60 * 60 * 2 * 1000) // 2小时前
* formatPast(data - 60 * 60 * 71 * 1000) // 2天前
* 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, format = 'YYYY-mm-dd') {
// 传入格式处理、存储转换值
let t, s;
// 获取js 时间戳
let time = 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) {
let hour = 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 '夜里好';
}
}
+99
View File
@@ -0,0 +1,99 @@
import Vue from 'vue';
// 获取阿里字体图标
const getAlicdnIconfont = () => {
return new Promise((resolve, reject) => {
Vue.nextTick(() => {
const styles = 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 getElementPlusIconfont = () => {
return new Promise((resolve, reject) => {
Vue.nextTick(() => {
const styles = 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 getAwesomeIconfont = () => {
return new Promise((resolve, reject) => {
Vue.nextTick(() => {
const styles = 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 = {
// iconfont
ali: () => {
return getAlicdnIconfont();
},
// element plus
ele: () => {
return getElementPlusIconfont();
},
// fontawesome
awe: () => {
return getAwesomeIconfont();
},
};
// 导出方法
export default initIconfont;

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