mirror of
https://gitee.com/lyt-top/vue-next-admin
synced 2026-06-06 16:21:43 +08:00
'admin-22.03.04:同步master分支v2.0.2版本内容,具体查看master的CHANGELOG.md'
This commit is contained in:
@ -2,6 +2,10 @@
|
||||
|
||||
🎉🎉🔥 `vue-next-admin-template` 基于 (vue-next-admin-v1.1.2 版本) vue3.x 、Typescript、vite、Element plus 等,适配手机、平板、pc 的后台开源免费模板库(vue2.x 请切换 vue-prev-admin 分支)
|
||||
|
||||
## 2.0.2
|
||||
|
||||
- 🎉 同步 master 分支 v2.0.2 版本内容,具体查看 master CHANGELOG.md
|
||||
|
||||
## 0.2.2
|
||||
|
||||
`2021.12.21`
|
||||
|
||||
@ -82,18 +82,22 @@ cnpm run build
|
||||
|
||||
#### 💯 学习交流加 QQ 群
|
||||
|
||||
- 若加群了没同意(一般不会超过一天),那就是群满了,请换一个群试试
|
||||
- 若加群了没同意(一般秒过),那就是群满了(500 人群),请换一个群试试,3 群未满
|
||||
- 查看开发文档、<a href="https://lyt-top.gitee.io/vue-next-admin-preview/#/login" target="_blank">vue-next-admin</a> 开发文档正在编写中...
|
||||
- 群号码:
|
||||
1 群:<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=RdUY97Vx0T0vZ_1OOu-X1yFNkWgDwbjC&jump_from=webapi">665452019</a>
|
||||
2 群:<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=zVfy3gNy7pNWVK3kMduDzwU369PZg2fw&jump_from=webapi">766356862</a>
|
||||
3 群:<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=02EWb5P2JkP-8iwzaDadgFdxA0HSHPpn&jump_from=webapi">795345435</a>
|
||||
|
||||
<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=RdUY97Vx0T0vZ_1OOu-X1yFNkWgDwbjC&jump_from=webapi">
|
||||
<img src="https://gitee.com/lyt-top/vue-next-admin-images/raw/master/user/qq1.png" width="220" height="220" alt="vue-next-admin 讨论群" title="vue-next-admin 讨论群1"/>
|
||||
<img src="https://gitee.com/lyt-top/vue-next-admin-images/raw/master/user/qq1.png" width="220" height="220" alt="vue-next-admin 讨论群1" title="vue-next-admin 讨论群1"/>
|
||||
</a>
|
||||
<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=zVfy3gNy7pNWVK3kMduDzwU369PZg2fw&jump_from=webapi">
|
||||
<img src="https://gitee.com/lyt-top/vue-next-admin-images/raw/master/user/qq2.png" width="220" height="220" alt="vue-next-admin 讨论群" title="vue-next-admin 讨论群2"/>
|
||||
</a>
|
||||
<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=02EWb5P2JkP-8iwzaDadgFdxA0HSHPpn&jump_from=webapi">
|
||||
<img src="https://gitee.com/lyt-top/vue-next-admin-images/raw/master/user/qq3.png" width="220" height="220" alt="vue-next-admin 讨论群3" title="vue-next-admin 讨论群3"/>
|
||||
</a>
|
||||
|
||||
#### ❤️ 鸣谢列表
|
||||
|
||||
|
||||
42
package.json
42
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vue-next-admin-template",
|
||||
"version": "0.2.2",
|
||||
"version": "2.0.3",
|
||||
"description": "vue3 vite next admin template",
|
||||
"author": "lyt_20201208",
|
||||
"license": "MIT",
|
||||
@ -10,38 +10,38 @@
|
||||
"lint-fix": "eslint --fix --ext .js --ext .jsx --ext .vue src/"
|
||||
},
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "^0.2.4",
|
||||
"axios": "^0.24.0",
|
||||
"echarts": "^5.2.2",
|
||||
"element-plus": "^1.2.0-beta.6",
|
||||
"@element-plus/icons-vue": "^1.0.0",
|
||||
"axios": "^0.26.0",
|
||||
"echarts": "^5.3.0",
|
||||
"element-plus": "^2.0.4",
|
||||
"mitt": "^3.0.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"qrcodejs2-fixes": "^0.0.2",
|
||||
"screenfull": "^6.0.0",
|
||||
"screenfull": "^6.0.1",
|
||||
"sortablejs": "^1.14.0",
|
||||
"vue": "^3.2.20",
|
||||
"vue": "^3.2.31",
|
||||
"vue-clipboard3": "^1.0.1",
|
||||
"vue-router": "^4.0.12",
|
||||
"vue-router": "^4.0.13",
|
||||
"vuex": "^4.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/axios": "^0.14.0",
|
||||
"@types/clipboard": "^2.0.1",
|
||||
"@types/node": "^17.0.2",
|
||||
"@types/node": "^17.0.21",
|
||||
"@types/nprogress": "^0.2.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.8.0",
|
||||
"@typescript-eslint/parser": "^5.8.0",
|
||||
"@vitejs/plugin-vue": "^2.0.1",
|
||||
"@vue/compiler-sfc": "^3.2.26",
|
||||
"dotenv": "^10.0.0",
|
||||
"eslint": "^8.5.0",
|
||||
"eslint-plugin-vue": "^8.2.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.13.0",
|
||||
"@typescript-eslint/parser": "^5.13.0",
|
||||
"@vitejs/plugin-vue": "^2.2.4",
|
||||
"@vue/compiler-sfc": "^3.2.31",
|
||||
"dotenv": "^16.0.0",
|
||||
"eslint": "^8.10.0",
|
||||
"eslint-plugin-vue": "^8.5.0",
|
||||
"prettier": "^2.5.1",
|
||||
"sass": "^1.45.1",
|
||||
"sass-loader": "^12.4.0",
|
||||
"typescript": "^4.5.4",
|
||||
"vite": "^2.7.4",
|
||||
"vue-eslint-parser": "^8.0.1"
|
||||
"sass": "^1.49.9",
|
||||
"sass-loader": "^12.6.0",
|
||||
"typescript": "^4.6.2",
|
||||
"vite": "^2.8.6",
|
||||
"vue-eslint-parser": "^8.3.0"
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
|
||||
2
plugins.d.ts
vendored
2
plugins.d.ts
vendored
@ -1 +1,3 @@
|
||||
declare module 'vue-grid-layout';
|
||||
declare module 'sortablejs';
|
||||
declare module 'qrcodejs2-fixes';
|
||||
|
||||
19
src/App.vue
19
src/App.vue
@ -1,14 +1,17 @@
|
||||
<template>
|
||||
<router-view v-show="getThemeConfig.lockScreenTime !== 0" />
|
||||
<LockScreen v-if="getThemeConfig.isLockScreen" />
|
||||
<Setings ref="setingsRef" v-show="getThemeConfig.lockScreenTime !== 0" />
|
||||
<CloseFull />
|
||||
<el-config-provider :size="getGlobalComponentSize" :locale="zhCn">
|
||||
<router-view v-show="getThemeConfig.lockScreenTime !== 0" />
|
||||
<LockScreen v-if="getThemeConfig.isLockScreen" />
|
||||
<Setings ref="setingsRef" v-show="getThemeConfig.lockScreenTime !== 0" />
|
||||
<CloseFull />
|
||||
</el-config-provider>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, ref, getCurrentInstance, onBeforeMount, onMounted, nextTick, defineComponent, watch } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useStore } from '/@/store/index';
|
||||
import zhCn from 'element-plus/es/locale/lang/zh-cn';
|
||||
import other from '/@/utils/other';
|
||||
import { Local, Session } from '/@/utils/storage';
|
||||
import setIntroduction from '/@/utils/setIconfont';
|
||||
@ -19,7 +22,7 @@ export default defineComponent({
|
||||
name: 'app',
|
||||
components: { LockScreen, Setings, CloseFull },
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const { proxy } = <any>getCurrentInstance();
|
||||
const setingsRef = ref();
|
||||
const route = useRoute();
|
||||
const store = useStore();
|
||||
@ -27,6 +30,10 @@ export default defineComponent({
|
||||
const getThemeConfig = computed(() => {
|
||||
return store.state.themeConfig.themeConfig;
|
||||
});
|
||||
// 获取全局组件大小
|
||||
const getGlobalComponentSize = computed(() => {
|
||||
return other.globalComponentSize;
|
||||
});
|
||||
// 布局配置弹窗打开
|
||||
const openSetingsDrawer = () => {
|
||||
setingsRef.value.openDrawer();
|
||||
@ -64,7 +71,9 @@ export default defineComponent({
|
||||
}
|
||||
);
|
||||
return {
|
||||
zhCn,
|
||||
setingsRef,
|
||||
getGlobalComponentSize,
|
||||
getThemeConfig,
|
||||
};
|
||||
},
|
||||
|
||||
@ -4,24 +4,25 @@ import request from '/@/utils/request';
|
||||
* 用户登录
|
||||
* @param params 要传的参数值
|
||||
* @returns 返回接口数据
|
||||
* 登录api接口集合
|
||||
* @method signIn 用户登录
|
||||
* @method signOut 用户退出登录
|
||||
*/
|
||||
export function signIn(params: object) {
|
||||
return request({
|
||||
url: '/user/signIn',
|
||||
method: 'post',
|
||||
data: params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户退出登录
|
||||
* @param params 要传的参数值
|
||||
* @returns 返回接口数据
|
||||
*/
|
||||
export function signOut(params: object) {
|
||||
return request({
|
||||
url: '/user/signOut',
|
||||
method: 'post',
|
||||
data: params,
|
||||
});
|
||||
export function useLoginApi() {
|
||||
return {
|
||||
signIn: (params: object) => {
|
||||
return request({
|
||||
url: '/user/signIn',
|
||||
method: 'post',
|
||||
data: params,
|
||||
});
|
||||
},
|
||||
signOut: (params: object) => {
|
||||
return request({
|
||||
url: '/user/signOut',
|
||||
method: 'post',
|
||||
data: params,
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -3,32 +3,24 @@ import request from '/@/utils/request';
|
||||
/**
|
||||
* 后端控制菜单模拟json,路径在 https://gitee.com/lyt-top/vue-next-admin-images/tree/master/menu
|
||||
* 后端控制路由,isRequestRoutes 为 true,则开启后端控制路由
|
||||
* @method getMenuAdmin 获取后端动态路由菜单(admin)
|
||||
* @method getMenuTest 获取后端动态路由菜单(test)
|
||||
*/
|
||||
|
||||
/**
|
||||
* 获取后端动态路由菜单(admin)
|
||||
* @link 参考:https://gitee.com/lyt-top/vue-next-admin-images/tree/master/menu
|
||||
* @param params 要传的参数值,非必传
|
||||
* @returns 返回接口数据
|
||||
*/
|
||||
export function getMenuAdmin(params?: object) {
|
||||
return request({
|
||||
url: '/gitee/lyt-top/vue-next-admin-images/raw/master/menu/adminMenu-template.json',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取后端动态路由菜单(test)
|
||||
* @link 参考:https://gitee.com/lyt-top/vue-next-admin-images/tree/master/menu
|
||||
* @param params 要传的参数值,非必传
|
||||
* @returns 返回接口数据
|
||||
*/
|
||||
export function getMenuTest(params?: object) {
|
||||
return request({
|
||||
url: '/gitee/lyt-top/vue-next-admin-images/raw/master/menu/testMenu-template.json',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
export function useMenuApi() {
|
||||
return {
|
||||
getMenuAdmin: (params?: object) => {
|
||||
return request({
|
||||
url: '/gitee/lyt-top/vue-next-admin-images/raw/master/menu/adminMenu.json',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
},
|
||||
getMenuTest: (params?: object) => {
|
||||
return request({
|
||||
url: '/gitee/lyt-top/vue-next-admin-images/raw/master/menu/testMenu.json',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
1
src/assets/login-icon-two.svg
Normal file
1
src/assets/login-icon-two.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 26 KiB |
9
src/assets/logo-mini.svg
Normal file
9
src/assets/logo-mini.svg
Normal file
@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 50" width="64" height="50">
|
||||
<defs>
|
||||
<image width="64" height="50" id="img1" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAyCAYAAADsg90UAAAAAXNSR0IB2cksfwAACI5JREFUeJy1WgtsW9UZdvNq0xU6WhZoCCVx7Gunbld1GSsMdYpGREhwr+2IMbQWqRoTk+iWPZi2wWhm1kwEmqV52feRJrbvvd6DiUnbQCAemzY2xh4tSB0wOqZIqAtLYzultIWEpt13btLq+sap/R8nRzpK4vh+5/++85///8851yEk1V+hX6B0tyE3OWwt0x789VR78AKlZ0KBz1oxBE3+BdUW9PNuQ7nJbk/BDQ/v4hi0x44z1R64jyrAVCjQ/fLNN8/ZoUWdgqGc57AFE6I86giH+QRw6XI9QE4RBz3iTAyVW3EyQdEDUmeIIhyeFNtMHO/o0B4e8qYASfVvLk2p4BKgdnioFCAvEQeddhnyFivOpOgvBaFXiAKcygQDrk927S/zjkae5xUA/X3YI/C5AFwHLrSPw+2+YYfCMugiCvDaCbGt0hc9uAXuP1OEAPACZQ+fAGguQ9nGgglx0OfsOAhq24lBcG/YYQa/kWLIz3XlCW4B6mKRCoCMEQdNu3VpnRVnMhBYA2L/LVCATCooXuNJSHXFzv58P+mMyyu5RQDAKNntdLnNjoN0+NMCM0D8901NDkGXuyBAseRZn3Ubagu3AFjTd1GXAdZdpCqurMgSIBS4BwRn8wgwje/d4pV6yz2adGQJyM/bo/ZyC+DSlWqApIiDHqtPyFdlCyBeD4Lv5xHgr5mAWO4ZjTRh9s8tlQDoryIbrOISoLYvvAIALxIHnIHn3GnFmfDfztLhH/IEv/vYd72xyKElJM/6Gdjj4fYCuNA3yYMa6ogdBwQfvIwAk+mguHZz3+MbMPsfLrEALD3v5RfAkH3UOID+Jqqwj2ULIDZeJvhF2He8I0NfX2ry8wI85VSy41LBzaUPsXT4L/Iy0OUbrTgpsXUlyI7lEOAsvGOboPRdKejK28shAPqpek1etxjHArxAiXCo/pAdB2QPLRQg8BLcv8ITi4h4bnaZBGD2+IsQQG0DCDUyv2LfjcHVQyB93iLAecz+bvY/T1x6YrnImwIkVakIAeSrAfIucdCz7qRcY8VJh8RrQDplWfvHxttaVvkGe6vg/h8tpwDoR926wpcOb9CkEhQ4Mbrqym4rTkrcydLhs5bU95Wwwwx+311m8qxPQ4CtvE6AdKjcLlCrQkNJXNXdnYUD0t+eF+AE1v76rV0/qvTEo/8kkkGJq/yFLIKhPsgtgEszl8E4cdAxPHdllgDBwGZW9k6Fguaa9A4PtMEwkrDe0chhCPAZ/E5dNn/kPiWqGe5mVSH1rJCdze2w4rDNDsi/gdn/FPtb0KTfUmeyQenvuE45WCLQd6unsc3fwKeAw0yHX+Zwu247DpbB3emQv3R7x7du8GgybdtrKGc39Ty23rQnqfKk5y9wCwD1XACZJg56xGUMZFVhx1taytjPBnWAfuihyT+3TEiAQwC1Mhzmqwrr9QhbBoeJg36A6Ou0Y/kGe2qQ+mhiGspHDcODTZfs0eRr8fkE0Z4xpyGt4RJgTnX1carq8Jw9dhzv6BB5k+VJyK9t6+y8dNK74bGHMSHK00Scc/CC7fwC6MotAjX6GuqTzsTBkosYW/f9YKUnIb1OFiAW/c4Ce5Lq18jLKKnu5xaApTWBHn0n8Nz6ixhw4zvJ5HXlvU2R3gWui02XizwhrEznbTW9vQ64nUEckBUut13EQOHzFFUA70jErBv+09xcYrXHqUXK8H9qIXXapSs1dm4FN1SF95DdzlD72LMNUt/15CMvXT65NfzIRtQOq5FCv7jAHkPppdqDZ3YvZFZgY8WEQN8dvvFxpB8hLvWT3T8uyWxckG9CEfX38fk0ahGgmboMMIk/2xg5UJKbYZ62sf9RbI7UPxGJzLgT0R2Y/RM0z1HO+QZ6Gl/3+dh2Wmdb6HQwUJc9IfI6fPc40Z5xCLeW2wvw8Pfoy0B5mfoMAuYLn+7oKE0FxZqp+YvWTHugw24PvvtLIjZLh83cAghzmxHqASb5qntz/4EvsfEy7UHroepvJoKtWdUcPPKrVGwsA6k2FuYTAPXAGoC8RfYCStflqRvv3VuB4Hc1SI9bBJjAZ1VWe+p1+TqBHpfG+M8Ksa0EgLacAnhiETNzIPjdbztLPIfPWrME0CSkQ+UfxDFmkQ5v5RPAYcYBckFTcDfUWc+hwZsw06tA+EiOi5RoDns66ctA/Qm3AE4tuhYgZ5Zl9uPR32165PtlINoMwjM5jtPfSvn9WTe/iEufw7PUW+U3a2NSKZ8CTU0s+DyzHAJgq9yuNDaywxNtkQuVWaTDBqs5SIdsQt4hjsXOCvmvzrDu6Fdnebo3Hj3u69xXngoFqkH09KL3ie2BB6y2XCsfZNt1apnOqsL7uY/KoB57k+SDJRUhIZlX2iD4UJ4b5ef+3dqabY9hlunUdPt0XXyIryqs1yKVAv3qbPFuKNNedaAR5FeD4NE8AqRTwZ1ZmxqnHv0EcI4Rxz3hNqSqxThevrEXqpJq31IJgOD3TN3+h0tYmmPpLt9bJex80W4SRBzmEF7kE8Bhbo5aONwutwCx6K4JUVyByu/JfOTn+6EFAiTNN1uoAgxyC1BvqFcAZLJo8pr8rlvuq8wExfpFUl+u/s7/dt6R9UKkS5ergHeaOP6Yc2SQLw7Mqa6SDznsHakvzLAyoeAPCyRvVoXpUGCb1ZZqRWFnhdQXPWcg3Jac5App7C2MImf/5Kb+nupJ0X8FSL1NEOACEyyHPQ9QbWA73CIEkBuEIqrCzUO9CsNB6esCqQ8pAqD/Oe33l9vs2SLQd6svuhJSWW6GeVptLFKGbMD9eltjZ2cjw5m4o60ChF4lCvBeJhjIuntAYF4N3KNEO9Lwgmo+F/D5mNt1cbr/2OeD916qx+HSB4gCsDdNdmXZM7dbjRJtYXeZd/EJ4DDX3Q4uARLSj604yO23UgVA2jRy2EO+OkNX/w+fZNm8pw5QbAAAAABJRU5ErkJggg=="/>
|
||||
</defs>
|
||||
<style>
|
||||
tspan { white-space:pre }
|
||||
</style>
|
||||
<use id="Background" href="#img1" x="0" y="0" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
@ -17,7 +17,7 @@
|
||||
<SvgIcon
|
||||
:name="fontIconPrefix === '' ? prepend : fontIconPrefix"
|
||||
class="font14"
|
||||
v-if="fontIconPrefix === '' ? prepend?.indexOf('element') > -1 : fontIconPrefix?.indexOf('element') > -1"
|
||||
v-if="fontIconPrefix === '' ? prepend?.indexOf('ele-') > -1 : fontIconPrefix?.indexOf('ele-') > -1"
|
||||
/>
|
||||
<i v-else :class="fontIconPrefix === '' ? prepend : fontIconPrefix" class="font14"></i>
|
||||
</template>
|
||||
@ -56,16 +56,16 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { ref, toRefs, reactive, onMounted, nextTick, computed, watch } from 'vue';
|
||||
import { ref, toRefs, reactive, onMounted, nextTick, computed, watch, defineComponent } from 'vue';
|
||||
import initIconfont from '/@/utils/getStyleSheets';
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'iconSelector',
|
||||
emits: ['update:modelValue', 'get', 'clear'],
|
||||
props: {
|
||||
// 输入框前置内容
|
||||
prepend: {
|
||||
type: String,
|
||||
default: () => 'elementPointer',
|
||||
default: () => 'ele-Pointer',
|
||||
},
|
||||
// 输入框占位文本
|
||||
placeholder: {
|
||||
@ -75,7 +75,7 @@ export default {
|
||||
// 输入框占位文本
|
||||
size: {
|
||||
type: String,
|
||||
default: () => 'small',
|
||||
default: () => 'default',
|
||||
},
|
||||
// 弹窗标题
|
||||
title: {
|
||||
@ -109,7 +109,7 @@ export default {
|
||||
setup(props, { emit }) {
|
||||
const inputWidthRef = ref();
|
||||
const selectorScrollbarRef = ref();
|
||||
const state: any = reactive({
|
||||
const state = reactive({
|
||||
fontIconPrefix: '',
|
||||
fontIconVisible: false,
|
||||
fontIconWidth: 0,
|
||||
@ -122,6 +122,7 @@ export default {
|
||||
});
|
||||
// 处理 input 获取焦点时,modelValue 有值时,改变 input 的 placeholder 值
|
||||
const onIconFocus = () => {
|
||||
state.fontIconVisible = true;
|
||||
if (!props.modelValue) return false;
|
||||
state.fontIconSearch = '';
|
||||
state.fontIconPlaceholder = props.modelValue;
|
||||
@ -136,8 +137,8 @@ export default {
|
||||
// 处理 icon 双向绑定数值回显
|
||||
const initModeValueEcho = () => {
|
||||
if (props.modelValue === '') return false;
|
||||
state.fontIconPlaceholder = props.modelValue;
|
||||
state.fontIconPrefix = props.modelValue;
|
||||
(<string | undefined>state.fontIconPlaceholder) = props.modelValue;
|
||||
(<string | undefined>state.fontIconPrefix) = props.modelValue;
|
||||
};
|
||||
// 图标搜索及图标数据显示
|
||||
const fontIconSheetsFilterList = computed(() => {
|
||||
@ -165,7 +166,7 @@ export default {
|
||||
if (type === 'ali') {
|
||||
await initIconfont.ali().then((res: any) => {
|
||||
// 阿里字体图标使用 `iconfont xxx`
|
||||
state.fontIconSheetsList = res.map((i) => `iconfont ${i}`);
|
||||
state.fontIconSheetsList = res.map((i: string) => `iconfont ${i}`);
|
||||
});
|
||||
} else if (type === 'ele') {
|
||||
await initIconfont.ele().then((res: any) => {
|
||||
@ -174,7 +175,7 @@ export default {
|
||||
} else if (type === 'awe') {
|
||||
await initIconfont.awe().then((res: any) => {
|
||||
// fontawesome字体图标使用 `fa xxx`
|
||||
state.fontIconSheetsList = res.map((i) => `fa ${i}`);
|
||||
state.fontIconSheetsList = res.map((i: string) => `fa ${i}`);
|
||||
});
|
||||
}
|
||||
// 初始化 input 的 placeholder
|
||||
@ -208,9 +209,9 @@ export default {
|
||||
onMounted(() => {
|
||||
// 判断默认进来是什么类型图标,进行 tab 回显
|
||||
if (props.type === 'all') {
|
||||
if (props.modelValue?.indexOf('iconfont') > -1) onIconChange('ali');
|
||||
else if (props.modelValue?.indexOf('element') > -1) onIconChange('ele');
|
||||
else if (props.modelValue?.indexOf('fa') > -1) onIconChange('awe');
|
||||
if ((<any>props.modelValue)?.indexOf('iconfont') > -1) onIconChange('ali');
|
||||
else if ((<any>props.modelValue)?.indexOf('ele-') > -1) onIconChange('ele');
|
||||
else if ((<any>props.modelValue)?.indexOf('fa') > -1) onIconChange('awe');
|
||||
else onIconChange('ali');
|
||||
} else {
|
||||
onIconChange(props.type);
|
||||
@ -237,5 +238,5 @@ export default {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -1,7 +1,15 @@
|
||||
<script lang="ts">
|
||||
// 渲染函数:https://v3.cn.vuejs.org/guide/render-function.html
|
||||
import { h, resolveComponent, defineComponent } from 'vue';
|
||||
export default defineComponent({
|
||||
import { h, resolveComponent } from 'vue';
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface SvgIconProps {
|
||||
name: string;
|
||||
size: number;
|
||||
color: string;
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'svgIcon',
|
||||
props: {
|
||||
// svg 图标组件名字
|
||||
@ -11,18 +19,24 @@ export default defineComponent({
|
||||
// svg 大小
|
||||
size: {
|
||||
type: Number,
|
||||
default: () => 14,
|
||||
},
|
||||
// svg 颜色
|
||||
color: {
|
||||
type: String,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
if (props.name?.indexOf('element') > -1) {
|
||||
return () => h('i', { class: 'el-icon', style: `--font-size: ${props.size};--color: ${props.color}` }, [h(resolveComponent(props.name))]);
|
||||
} else {
|
||||
return () => h('i', { class: props.name, style: `font-size: ${props.size};color: ${props.color}` });
|
||||
}
|
||||
setup(props: SvgIconProps) {
|
||||
// 定义变量
|
||||
const linesString: any[] = ['https', 'http', '/src', '/assets', import.meta.env.VITE_PUBLIC_PATH];
|
||||
const onLineStyle: string = `font-size: ${props.size}px;color: ${props.color}`;
|
||||
const localsStyle: string = `width: ${props.size}px;height: ${props.size}px`;
|
||||
const eleSetStyle = { class: 'el-icon', style: onLineStyle };
|
||||
|
||||
// 逻辑判断
|
||||
if (props.name?.startsWith('ele-')) return () => h('i', eleSetStyle, [props.name === 'ele-' ? '' : h(resolveComponent(props.name))]);
|
||||
else if (linesString.find((str) => props.name?.startsWith(str))) return () => h('img', { src: props.name, style: localsStyle });
|
||||
else return () => h('i', { class: props.name, style: onLineStyle });
|
||||
},
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -10,23 +10,19 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive, computed, watch, getCurrentInstance, onBeforeMount } from 'vue';
|
||||
import { toRefs, reactive, computed, watch, getCurrentInstance, onBeforeMount, defineComponent } from 'vue';
|
||||
import { useStore } from '/@/store/index';
|
||||
import Logo from '/@/layout/logo/index.vue';
|
||||
import Vertical from '/@/layout/navMenu/vertical.vue';
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'layoutAside',
|
||||
components: { Logo, Vertical },
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const { proxy } = <any>getCurrentInstance();
|
||||
const store = useStore();
|
||||
const state: any = reactive({
|
||||
const state = reactive({
|
||||
menuList: [],
|
||||
clientWidth: '',
|
||||
});
|
||||
// 获取布局配置信息
|
||||
const getThemeConfig = computed(() => {
|
||||
return store.state.themeConfig.themeConfig;
|
||||
clientWidth: 0,
|
||||
});
|
||||
// 获取卡片全屏信息
|
||||
const isTagsViewCurrenFull = computed(() => {
|
||||
@ -35,8 +31,8 @@ export default {
|
||||
// 设置菜单展开/收起时的宽度
|
||||
const setCollapseStyle = computed(() => {
|
||||
const { layout, isCollapse, menuBar } = store.state.themeConfig.themeConfig;
|
||||
const asideBrColor =
|
||||
menuBar === '#FFFFFF' || menuBar === '#FFF' || menuBar === '#fff' || menuBar === '#ffffff' ? 'layout-el-aside-br-color' : '';
|
||||
const asideBrTheme = ['#FFFFFF', '#FFF', '#fff', '#ffffff'];
|
||||
const asideBrColor = asideBrTheme.includes(menuBar) ? 'layout-el-aside-br-color' : '';
|
||||
// 判断是否是手机端
|
||||
if (state.clientWidth <= 1000) {
|
||||
if (isCollapse) {
|
||||
@ -73,7 +69,10 @@ export default {
|
||||
// 关闭移动端蒙版
|
||||
const closeLayoutAsideMobileMode = () => {
|
||||
const el = document.querySelector('.layout-aside-mobile-mode');
|
||||
el && el.parentNode?.removeChild(el);
|
||||
el?.setAttribute('style', 'animation: error-img-two 0.3s');
|
||||
setTimeout(() => {
|
||||
el?.parentNode?.removeChild(el);
|
||||
}, 300);
|
||||
const clientWidth = document.body.clientWidth;
|
||||
if (clientWidth < 1000) store.state.themeConfig.themeConfig.isCollapse = false;
|
||||
document.body.setAttribute('class', '');
|
||||
@ -86,7 +85,7 @@ export default {
|
||||
// 设置/过滤路由(非静态路由/是否显示在菜单中)
|
||||
const setFilterRoutes = () => {
|
||||
if (store.state.themeConfig.themeConfig.layout === 'columns') return false;
|
||||
state.menuList = filterRoutesFun(store.state.routesList.routesList);
|
||||
(state.menuList as any) = filterRoutesFun(store.state.routesList.routesList);
|
||||
};
|
||||
// 路由过滤递归函数
|
||||
const filterRoutesFun = (arr: Array<object>) => {
|
||||
@ -149,11 +148,10 @@ export default {
|
||||
return {
|
||||
setCollapseStyle,
|
||||
setShowLogo,
|
||||
getThemeConfig,
|
||||
isTagsViewCurrenFull,
|
||||
onAsideEnterLeave,
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -43,19 +43,32 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { reactive, toRefs, ref, computed, onMounted, nextTick, getCurrentInstance, watch, onUnmounted } from 'vue';
|
||||
import { useRoute, useRouter, onBeforeRouteUpdate } from 'vue-router';
|
||||
import { reactive, toRefs, ref, computed, onMounted, nextTick, getCurrentInstance, watch, onUnmounted, defineComponent } from 'vue';
|
||||
import { useRoute, useRouter, onBeforeRouteUpdate, RouteRecordRaw } from 'vue-router';
|
||||
import { useStore } from '/@/store/index';
|
||||
export default {
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface ColumnsAsideState {
|
||||
columnsAsideList: any[];
|
||||
liIndex: number;
|
||||
liOldIndex: null | number;
|
||||
liHoverIndex: null | number;
|
||||
liOldPath: null | string;
|
||||
difference: number;
|
||||
routeSplit: string[];
|
||||
isNavHover: boolean;
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'layoutColumnsAside',
|
||||
setup() {
|
||||
const columnsAsideOffsetTopRefs: any = ref([]);
|
||||
const columnsAsideActiveRef = ref();
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const { proxy } = <any>getCurrentInstance();
|
||||
const store = useStore();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const state: any = reactive({
|
||||
const state = reactive<ColumnsAsideState>({
|
||||
columnsAsideList: [],
|
||||
liIndex: 0,
|
||||
liOldIndex: null,
|
||||
@ -86,7 +99,7 @@ export default {
|
||||
else router.push(path);
|
||||
};
|
||||
// 鼠标移入时,显示当前的子级菜单
|
||||
const onColumnsAsideMenuMouseenter = (v: Object, k: number) => {
|
||||
const onColumnsAsideMenuMouseenter = (v: RouteRecordRaw, k: number) => {
|
||||
let { path } = v;
|
||||
state.liOldPath = path;
|
||||
state.liOldIndex = k;
|
||||
@ -153,7 +166,7 @@ export default {
|
||||
if (!currentSplitRoute) return false;
|
||||
// 延迟拿值,防止取不到
|
||||
setTimeout(() => {
|
||||
onColumnsAsideDown(currentSplitRoute.k);
|
||||
onColumnsAsideDown((<any>currentSplitRoute).k);
|
||||
}, 0);
|
||||
};
|
||||
// 监听布局配置信息的变化,动态增加菜单高亮位置移动像素
|
||||
@ -198,18 +211,18 @@ export default {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.layout-columns-aside {
|
||||
width: 70px;
|
||||
height: 100%;
|
||||
background: var(--bg-columnsMenuBar);
|
||||
background: var(--next-bg-columnsMenuBar);
|
||||
ul {
|
||||
position: relative;
|
||||
li {
|
||||
color: var(--bg-columnsMenuBarColor);
|
||||
color: var(--next-bg-columnsMenuBarColor);
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
text-align: center;
|
||||
@ -241,22 +254,22 @@ export default {
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: var(--bg-columnsMenuBarColor);
|
||||
color: var(--next-bg-columnsMenuBarColor);
|
||||
}
|
||||
}
|
||||
.layout-columns-active {
|
||||
color: var(--color-whites) !important;
|
||||
color: var(--el-color-white);
|
||||
transition: 0.3s ease-in-out;
|
||||
}
|
||||
.layout-columns-hover {
|
||||
color: var(--color-primary);
|
||||
color: var(--el-color-primary);
|
||||
a {
|
||||
color: var(--color-primary);
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
.columns-round {
|
||||
background: var(--color-primary);
|
||||
color: var(--color-whites);
|
||||
background: var(--el-color-primary);
|
||||
color: var(--el-color-white);
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 2px;
|
||||
|
||||
@ -5,10 +5,10 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { computed, defineComponent } from 'vue';
|
||||
import { useStore } from '/@/store/index';
|
||||
import NavBarsIndex from '/@/layout/navBars/index.vue';
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'layoutHeader',
|
||||
components: { NavBarsIndex },
|
||||
setup() {
|
||||
@ -28,5 +28,5 @@ export default {
|
||||
isTagsViewCurrenFull,
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -3,32 +3,35 @@
|
||||
<el-scrollbar
|
||||
class="layout-scrollbar"
|
||||
ref="layoutScrollbarRef"
|
||||
:style="{
|
||||
minHeight: `calc(100vh - ${headerHeight})`,
|
||||
padding: currentRouteMeta.isLink && currentRouteMeta.isIframe ? 0 : '',
|
||||
transition: 'padding 0.3s ease-in-out',
|
||||
}"
|
||||
:style="{ padding: currentRouteMeta.isLink && currentRouteMeta.isIframe ? 0 : '', transition: 'padding 0.3s ease-in-out' }"
|
||||
>
|
||||
<LayoutParentView />
|
||||
<LayoutParentView :style="{ minHeight: `calc(100vh - ${headerHeight})` }" />
|
||||
<Footer v-if="getThemeConfig.isFooter" />
|
||||
</el-scrollbar>
|
||||
</el-main>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, toRefs, reactive, getCurrentInstance, watch, onBeforeMount } from 'vue';
|
||||
import { computed, defineComponent, toRefs, reactive, getCurrentInstance, watch, onMounted } from 'vue';
|
||||
import { useStore } from '/@/store/index';
|
||||
import { useRoute } from 'vue-router';
|
||||
import LayoutParentView from '/@/layout/routerView/parent.vue';
|
||||
import Footer from '/@/layout/footer/index.vue';
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface MainState {
|
||||
headerHeight: string | number;
|
||||
currentRouteMeta: any;
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'layoutMain',
|
||||
components: { LayoutParentView, Footer },
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const { proxy } = <any>getCurrentInstance();
|
||||
const route = useRoute();
|
||||
const store = useStore();
|
||||
const state = reactive({
|
||||
const state = reactive<MainState>({
|
||||
headerHeight: '',
|
||||
currentRouteMeta: {},
|
||||
});
|
||||
@ -47,25 +50,31 @@ export default defineComponent({
|
||||
state.currentRouteMeta = route.meta;
|
||||
};
|
||||
// 页面加载前
|
||||
onBeforeMount(() => {
|
||||
onMounted(async () => {
|
||||
await initGetMeta();
|
||||
initHeaderHeight();
|
||||
initGetMeta();
|
||||
});
|
||||
// 监听 themeConfig 配置文件的变化,更新菜单 el-scrollbar 的高度
|
||||
watch(store.state.themeConfig.themeConfig, (val) => {
|
||||
state.headerHeight = val.isTagsview ? '84px' : '50px';
|
||||
if (val.isFixedHeaderChange !== val.isFixedHeader) {
|
||||
if (!proxy.$refs.layoutScrollbarRef) return false;
|
||||
proxy.$refs.layoutScrollbarRef.update();
|
||||
}
|
||||
});
|
||||
// 监听路由变化
|
||||
watch(
|
||||
() => route.path,
|
||||
() => {
|
||||
state.currentRouteMeta = route.meta;
|
||||
const bool = state.currentRouteMeta.isLink && state.currentRouteMeta.isIframe;
|
||||
state.headerHeight = bool ? `85px` : `114px`;
|
||||
proxy.$refs.layoutScrollbarRef.update();
|
||||
}
|
||||
);
|
||||
// 监听 themeConfig 配置文件的变化,更新菜单 el-scrollbar 的高度
|
||||
watch(store.state.themeConfig.themeConfig, (val) => {
|
||||
state.currentRouteMeta = route.meta;
|
||||
const bool = state.currentRouteMeta.isLink && state.currentRouteMeta.isIframe;
|
||||
state.headerHeight = val.isTagsview ? (bool ? `85px` : `114px`) : '51px';
|
||||
if (val.isFixedHeaderChange !== val.isFixedHeader) {
|
||||
if (!proxy.$refs.layoutScrollbarRef) return false;
|
||||
proxy.$refs.layoutScrollbarRef.update();
|
||||
}
|
||||
});
|
||||
return {
|
||||
getThemeConfig,
|
||||
...toRefs(state),
|
||||
|
||||
@ -8,9 +8,9 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive } from 'vue';
|
||||
import { toRefs, reactive, defineComponent } from 'vue';
|
||||
import { onBeforeRouteUpdate } from 'vue-router';
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'layoutFooter',
|
||||
setup() {
|
||||
const state = reactive({
|
||||
@ -18,16 +18,18 @@ export default {
|
||||
});
|
||||
// 路由改变时,等主界面动画加载完毕再显示 footer
|
||||
onBeforeRouteUpdate(() => {
|
||||
state.isDelayFooter = false;
|
||||
setTimeout(() => {
|
||||
state.isDelayFooter = true;
|
||||
}, 800);
|
||||
state.isDelayFooter = false;
|
||||
setTimeout(() => {
|
||||
state.isDelayFooter = true;
|
||||
}, 800);
|
||||
}, 0);
|
||||
});
|
||||
return {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@ -38,7 +40,7 @@ export default {
|
||||
margin: auto;
|
||||
color: var(--el-text-color-secondary);
|
||||
text-align: center;
|
||||
animation: logoAnimation 0.3s ease-in-out;
|
||||
animation: error-num 1s ease-in-out;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,23 +1,21 @@
|
||||
<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'" />
|
||||
<component :is="getThemeConfig.layout" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, onBeforeMount, onUnmounted, getCurrentInstance } from 'vue';
|
||||
import { computed, onBeforeMount, onUnmounted, getCurrentInstance, defineComponent, defineAsyncComponent } from 'vue';
|
||||
import { useStore } from '/@/store/index';
|
||||
import { Local } from '/@/utils/storage';
|
||||
import Defaults from '/@/layout/main/defaults.vue';
|
||||
import Classic from '/@/layout/main/classic.vue';
|
||||
import Transverse from '/@/layout/main/transverse.vue';
|
||||
import Columns from '/@/layout/main/columns.vue';
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'layout',
|
||||
components: { Defaults, Classic, Transverse, Columns },
|
||||
components: {
|
||||
defaults: defineAsyncComponent(() => import('/@/layout/main/defaults.vue')),
|
||||
classic: defineAsyncComponent(() => import('/@/layout/main/classic.vue')),
|
||||
transverse: defineAsyncComponent(() => import('/@/layout/main/transverse.vue')),
|
||||
columns: defineAsyncComponent(() => import('/@/layout/main/columns.vue')),
|
||||
},
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const { proxy } = <any>getCurrentInstance();
|
||||
const store = useStore();
|
||||
// 获取布局配置信息
|
||||
const getThemeConfig = computed(() => {
|
||||
@ -53,5 +51,5 @@ export default {
|
||||
getThemeConfig,
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
<div class="layout-lock-screen-date-box-info">{{ time.mdq }}</div>
|
||||
</div>
|
||||
<div class="layout-lock-screen-date-top">
|
||||
<SvgIcon name="elementTop" />
|
||||
<SvgIcon name="ele-Top" />
|
||||
<div class="layout-lock-screen-date-top-text">上滑解锁</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -41,7 +41,7 @@
|
||||
<template #append>
|
||||
<el-button @click="onLockScreenSubmit">
|
||||
<el-icon>
|
||||
<elementRight />
|
||||
<ele-Right />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</template>
|
||||
@ -49,9 +49,9 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-lock-screen-login-icon">
|
||||
<SvgIcon name="elementMicrophone" />
|
||||
<SvgIcon name="elementClock" />
|
||||
<SvgIcon name="elementSwitchButton" />
|
||||
<SvgIcon name="ele-Microphone" />
|
||||
<SvgIcon name="ele-AlarmClock" />
|
||||
<SvgIcon name="ele-SwitchButton" />
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
@ -64,13 +64,33 @@ import { nextTick, onMounted, reactive, toRefs, ref, onUnmounted, getCurrentInst
|
||||
import { useStore } from '/@/store/index';
|
||||
import { formatDate } from '/@/utils/formatTime';
|
||||
import { Local } from '/@/utils/storage';
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface LockScreenState {
|
||||
transparency: number;
|
||||
downClientY: number;
|
||||
moveDifference: number;
|
||||
isShowLoockLogin: boolean;
|
||||
isFlags: boolean;
|
||||
querySelectorEl: HTMLElement | string;
|
||||
time: {
|
||||
hm: string;
|
||||
s: string;
|
||||
mdq: string;
|
||||
};
|
||||
setIntervalTime: number;
|
||||
isShowLockScreen: boolean;
|
||||
isShowLockScreenIntervalTime: number;
|
||||
lockScreenPassword: string;
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'layoutLockScreen',
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const { proxy } = <any>getCurrentInstance();
|
||||
const layoutLockScreenInputRef = ref();
|
||||
const store = useStore();
|
||||
const state: any = reactive({
|
||||
const state = reactive<LockScreenState>({
|
||||
transparency: 1,
|
||||
downClientY: 0,
|
||||
moveDifference: 0,
|
||||
@ -95,7 +115,7 @@ export default defineComponent({
|
||||
// 鼠标移动
|
||||
const onMove = (move: any) => {
|
||||
if (state.isFlags) {
|
||||
const el = state.querySelectorEl;
|
||||
const el = <HTMLElement>state.querySelectorEl;
|
||||
const opacitys = (state.transparency -= 1 / 200);
|
||||
if (move.touches) {
|
||||
state.moveDifference = move.touches[0].clientY - state.downClientY;
|
||||
@ -122,7 +142,7 @@ export default defineComponent({
|
||||
state.isFlags = false;
|
||||
state.transparency = 1;
|
||||
if (state.moveDifference >= -400) {
|
||||
state.querySelectorEl.setAttribute('style', `top:0px;opacity:1;transition:all 0.3s ease;`);
|
||||
(<HTMLElement>state.querySelectorEl).setAttribute('style', `top:0px;opacity:1;transition:all 0.3s ease;`);
|
||||
}
|
||||
};
|
||||
// 获取要拖拽的初始元素
|
||||
|
||||
@ -1,20 +1,21 @@
|
||||
<template>
|
||||
<div class="layout-logo" v-if="setShowLogo" @click="onThemeConfigChange">
|
||||
<img src="https://gitee.com/lyt-top/vue-next-admin-images/raw/master/logo/logo-mini.svg" class="layout-logo-medium-img" />
|
||||
<img :src="logoMini" class="layout-logo-medium-img" />
|
||||
<span>{{ getThemeConfig.globalTitle }}</span>
|
||||
</div>
|
||||
<div class="layout-logo-size" v-else @click="onThemeConfigChange">
|
||||
<img src="https://gitee.com/lyt-top/vue-next-admin-images/raw/master/logo/logo-mini.svg" class="layout-logo-size-img" />
|
||||
<img :src="logoMini" class="layout-logo-size-img" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, getCurrentInstance } from 'vue';
|
||||
import { computed, defineComponent } from 'vue';
|
||||
import { useStore } from '/@/store/index';
|
||||
export default {
|
||||
import logoMini from '/@/assets/logo-mini.svg';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'layoutLogo',
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const store = useStore();
|
||||
// 获取布局配置信息
|
||||
const getThemeConfig = computed(() => {
|
||||
@ -28,16 +29,16 @@ export default {
|
||||
// logo 点击实现菜单展开/收起
|
||||
const onThemeConfigChange = () => {
|
||||
if (store.state.themeConfig.themeConfig.layout === 'transverse') return false;
|
||||
proxy.mittBus.emit('onMenuClick');
|
||||
store.state.themeConfig.themeConfig.isCollapse = !store.state.themeConfig.themeConfig.isCollapse;
|
||||
};
|
||||
return {
|
||||
logoMini,
|
||||
setShowLogo,
|
||||
getThemeConfig,
|
||||
onThemeConfigChange,
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@ -48,7 +49,7 @@ export default {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: rgb(0 21 41 / 2%) 0px 1px 4px;
|
||||
color: var(--color-primary);
|
||||
color: var(--el-color-primary);
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
animation: logoAnimation 0.3s ease-in-out;
|
||||
|
||||
@ -13,13 +13,13 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { computed, defineComponent } from 'vue';
|
||||
import { useStore } from '/@/store/index';
|
||||
import Aside from '/@/layout/component/aside.vue';
|
||||
import Header from '/@/layout/component/header.vue';
|
||||
import Main from '/@/layout/component/main.vue';
|
||||
import TagsView from '/@/layout/navBars/tagsView/tagsView.vue';
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'layoutClassic',
|
||||
components: { Aside, Header, Main, TagsView },
|
||||
setup() {
|
||||
@ -32,5 +32,5 @@ export default {
|
||||
getThemeConfig,
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -16,13 +16,13 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { computed, defineComponent } from 'vue';
|
||||
import { useStore } from '/@/store/index';
|
||||
import Aside from '/@/layout/component/aside.vue';
|
||||
import Header from '/@/layout/component/header.vue';
|
||||
import Main from '/@/layout/component/main.vue';
|
||||
import ColumnsAside from '/@/layout/component/columnsAside.vue';
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'layoutColumns',
|
||||
components: { Aside, Header, Main, ColumnsAside },
|
||||
setup() {
|
||||
@ -34,5 +34,5 @@ export default {
|
||||
isFixedHeader,
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -13,17 +13,17 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, getCurrentInstance, watch } from 'vue';
|
||||
import { computed, getCurrentInstance, watch, defineComponent } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useStore } from '/@/store/index';
|
||||
import Aside from '/@/layout/component/aside.vue';
|
||||
import Header from '/@/layout/component/header.vue';
|
||||
import Main from '/@/layout/component/main.vue';
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'layoutDefaults',
|
||||
components: { Aside, Header, Main },
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const { proxy } = <any>getCurrentInstance();
|
||||
const store = useStore();
|
||||
const route = useRoute();
|
||||
const isFixedHeader = computed(() => {
|
||||
@ -40,5 +40,5 @@ export default {
|
||||
isFixedHeader,
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -2,7 +2,8 @@
|
||||
<div class="layout-navbars-breadcrumb" :style="{ display: isShowBreadcrumb }">
|
||||
<SvgIcon
|
||||
class="layout-navbars-breadcrumb-icon"
|
||||
:name="getThemeConfig.isCollapse ? 'elementExpand' : 'elementFold'"
|
||||
:name="getThemeConfig.isCollapse ? 'ele-Expand' : 'ele-Fold'"
|
||||
:size="16"
|
||||
@click="onThemeConfigChange"
|
||||
/>
|
||||
<el-breadcrumb class="layout-navbars-breadcrumb-hide">
|
||||
@ -21,17 +22,26 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive, computed, getCurrentInstance, onMounted } from 'vue';
|
||||
import { toRefs, reactive, computed, onMounted, defineComponent } from 'vue';
|
||||
import { onBeforeRouteUpdate, useRoute, useRouter } from 'vue-router';
|
||||
import { useStore } from '/@/store/index';
|
||||
export default {
|
||||
import { Local } from '/@/utils/storage';
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface BreadcrumbState {
|
||||
breadcrumbList: Array<any>;
|
||||
routeSplit: Array<string>;
|
||||
routeSplitFirst: string;
|
||||
routeSplitIndex: number;
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'layoutBreadcrumb',
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const store = useStore();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const state: any = reactive({
|
||||
const state = reactive<BreadcrumbState>({
|
||||
breadcrumbList: [],
|
||||
routeSplit: [],
|
||||
routeSplitFirst: '',
|
||||
@ -45,11 +55,8 @@ export default {
|
||||
const isShowBreadcrumb = computed(() => {
|
||||
initRouteSplit(route.path);
|
||||
const { layout, isBreadcrumb } = store.state.themeConfig.themeConfig;
|
||||
if (layout === 'classic' || layout === 'transverse') {
|
||||
return 'none';
|
||||
} else {
|
||||
return isBreadcrumb ? '' : 'none';
|
||||
}
|
||||
if (layout === 'classic' || layout === 'transverse') return 'none';
|
||||
else return isBreadcrumb ? '' : 'none';
|
||||
});
|
||||
// 面包屑点击时
|
||||
const onBreadcrumbClick = (v: any) => {
|
||||
@ -59,8 +66,13 @@ export default {
|
||||
};
|
||||
// 展开/收起左侧菜单点击
|
||||
const onThemeConfigChange = () => {
|
||||
proxy.mittBus.emit('onMenuClick');
|
||||
store.state.themeConfig.themeConfig.isCollapse = !store.state.themeConfig.themeConfig.isCollapse;
|
||||
setLocalThemeConfig();
|
||||
};
|
||||
// 存储布局配置
|
||||
const setLocalThemeConfig = () => {
|
||||
Local.remove('themeConfig');
|
||||
Local.set('themeConfig', getThemeConfig.value);
|
||||
};
|
||||
// 处理面包屑数据
|
||||
const getBreadcrumbList = (arr: Array<object>) => {
|
||||
@ -101,7 +113,7 @@ export default {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@ -115,11 +127,11 @@ export default {
|
||||
cursor: pointer;
|
||||
font-size: 18px;
|
||||
margin-right: 15px;
|
||||
color: var(--bg-topBarColor);
|
||||
color: var(--next-bg-topBarColor);
|
||||
}
|
||||
.layout-navbars-breadcrumb-span {
|
||||
opacity: 0.7;
|
||||
color: var(--bg-topBarColor);
|
||||
color: var(--next-bg-topBarColor);
|
||||
}
|
||||
.layout-navbars-breadcrumb-iconfont {
|
||||
font-size: 14px;
|
||||
@ -127,7 +139,14 @@ export default {
|
||||
}
|
||||
::v-deep(.el-breadcrumb__separator) {
|
||||
opacity: 0.7;
|
||||
color: var(--bg-topBarColor);
|
||||
color: var(--next-bg-topBarColor);
|
||||
}
|
||||
::v-deep(.el-breadcrumb__inner a, .el-breadcrumb__inner.is-link) {
|
||||
font-weight: unset !important;
|
||||
color: var(--next-bg-topBarColor);
|
||||
&:hover {
|
||||
color: var(--el-color-primary) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,19 +1,18 @@
|
||||
<template>
|
||||
<div class="layout-navbars-close-full" v-if="isTagsViewCurrenFull">
|
||||
<div class="layout-navbars-close-full-box" title="关闭全屏" @click="onCloseFullscreen">
|
||||
<SvgIcon name="elementClose" />
|
||||
<SvgIcon name="ele-Close" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive, computed } from 'vue';
|
||||
import { computed, defineComponent } from 'vue';
|
||||
import { useStore } from '/@/store/index';
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'layoutCloseFull',
|
||||
setup() {
|
||||
const store = useStore();
|
||||
const state: any = reactive({});
|
||||
// 获取卡片全屏信息
|
||||
const isTagsViewCurrenFull = computed(() => {
|
||||
return store.state.tagsViewRoutes.isTagsViewCurrenFull;
|
||||
@ -25,10 +24,9 @@ export default {
|
||||
return {
|
||||
isTagsViewCurrenFull,
|
||||
onCloseFullscreen,
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@ -56,7 +54,7 @@ export default {
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
transition: all 0.3s ease;
|
||||
i {
|
||||
color: var(--color-primary);
|
||||
color: var(--el-color-primary);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,27 +8,29 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, reactive, toRefs, onMounted, onUnmounted, getCurrentInstance } from 'vue';
|
||||
import { computed, reactive, toRefs, onMounted, onUnmounted, getCurrentInstance, defineComponent } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useStore } from '/@/store/index';
|
||||
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 {
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface IndexState {
|
||||
menuList: object[];
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'layoutBreadcrumbIndex',
|
||||
components: { Breadcrumb, User, Logo, Horizontal },
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const { proxy } = <any>getCurrentInstance();
|
||||
const store = useStore();
|
||||
const route = useRoute();
|
||||
const state: any = reactive({
|
||||
const state = reactive<IndexState>({
|
||||
menuList: [],
|
||||
});
|
||||
// 获取布局配置信息
|
||||
const getThemeConfig = computed(() => {
|
||||
return store.state.themeConfig.themeConfig;
|
||||
});
|
||||
// 设置 logo 显示/隐藏
|
||||
const setIsShowLogo = computed(() => {
|
||||
let { isShowLogo, layout } = store.state.themeConfig.themeConfig;
|
||||
@ -93,13 +95,12 @@ export default {
|
||||
proxy.mittBus.off('getBreadcrumbIndexSetFilterRoutes');
|
||||
});
|
||||
return {
|
||||
getThemeConfig,
|
||||
setIsShowLogo,
|
||||
isLayoutTransverse,
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@ -108,7 +109,7 @@ export default {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-right: 15px;
|
||||
background: var(--bg-topBar);
|
||||
border-bottom: 1px solid #f1f2f3;
|
||||
background: var(--next-bg-topBar);
|
||||
border-bottom: 1px solid var(--next-border-color-light);
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
>
|
||||
<template #prefix>
|
||||
<el-icon class="el-input__icon">
|
||||
<elementSearch />
|
||||
<ele-Search />
|
||||
</el-icon>
|
||||
</template>
|
||||
<template #default="{ item }">
|
||||
@ -26,13 +26,27 @@
|
||||
import { reactive, toRefs, defineComponent, ref, nextTick } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useStore } from '/@/store/index';
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface SearchState {
|
||||
isShowSearch: boolean;
|
||||
menuQuery: string;
|
||||
tagsViewList: object[];
|
||||
}
|
||||
interface Restaurant {
|
||||
path: string;
|
||||
meta: {
|
||||
title: string;
|
||||
};
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'layoutBreadcrumbSearch',
|
||||
setup() {
|
||||
const layoutMenuAutocompleteRef = ref();
|
||||
const store = useStore();
|
||||
const router = useRouter();
|
||||
const state: any = reactive({
|
||||
const state = reactive<SearchState>({
|
||||
isShowSearch: false,
|
||||
menuQuery: '',
|
||||
tagsViewList: [],
|
||||
@ -51,13 +65,13 @@ export default defineComponent({
|
||||
state.isShowSearch = false;
|
||||
};
|
||||
// 菜单搜索数据过滤
|
||||
const menuSearch = (queryString: any, cb: any) => {
|
||||
const menuSearch = (queryString: string, cb: Function) => {
|
||||
let results = queryString ? state.tagsViewList.filter(createFilter(queryString)) : state.tagsViewList;
|
||||
cb(results);
|
||||
};
|
||||
// 菜单搜索过滤
|
||||
const createFilter = (queryString: any) => {
|
||||
return (restaurant: any) => {
|
||||
const createFilter: any = (queryString: string) => {
|
||||
return (restaurant: Restaurant) => {
|
||||
return (
|
||||
restaurant.path.toLowerCase().indexOf(queryString.toLowerCase()) > -1 ||
|
||||
restaurant.meta.title.toLowerCase().indexOf(queryString.toLowerCase()) > -1
|
||||
|
||||
@ -1,102 +1,99 @@
|
||||
<template>
|
||||
<div class="layout-breadcrumb-seting">
|
||||
<el-drawer title="布局配置" v-model="getThemeConfig.isDrawer" direction="rtl" destroy-on-close size="240px" @close="onDrawerClose">
|
||||
<el-drawer title="布局配置" v-model="getThemeConfig.isDrawer" direction="rtl" destroy-on-close size="260px" @close="onDrawerClose">
|
||||
<el-scrollbar class="layout-breadcrumb-seting-bar">
|
||||
<!-- 全局主题 -->
|
||||
<el-divider content-position="left">全局主题</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('primary')"> </el-color-picker>
|
||||
<el-color-picker v-model="getThemeConfig.primary" size="default" @change="onColorPickerChange"> </el-color-picker>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">success</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">深色模式</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-color-picker v-model="getThemeConfig.success" size="small" @change="onColorPickerChange('success')"> </el-color-picker>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">info</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-color-picker v-model="getThemeConfig.info" size="small" @change="onColorPickerChange('info')"> </el-color-picker>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">warning</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-color-picker v-model="getThemeConfig.warning" size="small" @change="onColorPickerChange('warning')"> </el-color-picker>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">danger</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-color-picker v-model="getThemeConfig.danger" size="small" @change="onColorPickerChange('danger')"> </el-color-picker>
|
||||
<el-switch v-model="getThemeConfig.isIsDark" size="small" @change="onAddDarkChange"></el-switch>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 菜单 / 顶栏 -->
|
||||
<el-divider content-position="left">菜单 / 顶栏</el-divider>
|
||||
<!-- 顶栏设置 -->
|
||||
<el-divider content-position="left">顶栏设置</el-divider>
|
||||
<div class="layout-breadcrumb-seting-bar-flex">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">顶栏背景</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-color-picker v-model="getThemeConfig.topBar" size="small" @change="onBgColorPickerChange('topBar')"> </el-color-picker>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">菜单背景</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-color-picker v-model="getThemeConfig.menuBar" size="small" @change="onBgColorPickerChange('menuBar')"> </el-color-picker>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">分栏菜单背景</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-color-picker v-model="getThemeConfig.columnsMenuBar" size="small" @change="onBgColorPickerChange('columnsMenuBar')">
|
||||
</el-color-picker>
|
||||
<el-color-picker v-model="getThemeConfig.topBar" size="default" @change="onBgColorPickerChange('topBar')"> </el-color-picker>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">顶栏默认字体颜色</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-color-picker v-model="getThemeConfig.topBarColor" size="small" @change="onBgColorPickerChange('topBarColor')"> </el-color-picker>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">菜单默认字体颜色</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-color-picker v-model="getThemeConfig.menuBarColor" size="small" @change="onBgColorPickerChange('menuBarColor')"> </el-color-picker>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">分栏菜单默认字体颜色</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-color-picker v-model="getThemeConfig.columnsMenuBarColor" size="small" @change="onBgColorPickerChange('columnsMenuBarColor')">
|
||||
</el-color-picker>
|
||||
<el-color-picker v-model="getThemeConfig.topBarColor" size="default" @change="onBgColorPickerChange('topBarColor')"> </el-color-picker>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt10">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">顶栏背景渐变</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-switch v-model="getThemeConfig.isTopBarColorGradual" @change="onTopBarGradualChange"></el-switch>
|
||||
<el-switch v-model="getThemeConfig.isTopBarColorGradual" size="small" @change="onTopBarGradualChange"></el-switch>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 菜单设置 -->
|
||||
<el-divider content-position="left">菜单设置</el-divider>
|
||||
<div class="layout-breadcrumb-seting-bar-flex">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">菜单背景</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-color-picker v-model="getThemeConfig.menuBar" size="default" @change="onBgColorPickerChange('menuBar')"> </el-color-picker>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">菜单默认字体颜色</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-color-picker v-model="getThemeConfig.menuBarColor" size="default" @change="onBgColorPickerChange('menuBarColor')"> </el-color-picker>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt14">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">菜单背景渐变</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-switch v-model="getThemeConfig.isMenuBarColorGradual" @change="onMenuBarGradualChange"></el-switch>
|
||||
<el-switch v-model="getThemeConfig.isMenuBarColorGradual" size="small" @change="onMenuBarGradualChange"></el-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt14">
|
||||
|
||||
<!-- 分栏设置 -->
|
||||
<el-divider content-position="left" :style="{ opacity: getThemeConfig.layout !== 'columns' ? 0.5 : 1 }">分栏设置</el-divider>
|
||||
<div class="layout-breadcrumb-seting-bar-flex" :style="{ opacity: getThemeConfig.layout !== 'columns' ? 0.5 : 1 }">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">分栏菜单背景</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-color-picker
|
||||
v-model="getThemeConfig.columnsMenuBar"
|
||||
size="default"
|
||||
@change="onBgColorPickerChange('columnsMenuBar')"
|
||||
:disabled="getThemeConfig.layout !== 'columns'"
|
||||
>
|
||||
</el-color-picker>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex" :style="{ opacity: getThemeConfig.layout !== 'columns' ? 0.5 : 1 }">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">分栏菜单默认字体颜色</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-color-picker
|
||||
v-model="getThemeConfig.columnsMenuBarColor"
|
||||
size="default"
|
||||
@change="onBgColorPickerChange('columnsMenuBarColor')"
|
||||
:disabled="getThemeConfig.layout !== 'columns'"
|
||||
>
|
||||
</el-color-picker>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt14" :style="{ opacity: getThemeConfig.layout !== 'columns' ? 0.5 : 1 }">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">分栏菜单背景渐变</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-switch v-model="getThemeConfig.isColumnsMenuBarColorGradual" @change="onColumnsMenuBarGradualChange"></el-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt14">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">菜单字体背景高亮</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-switch v-model="getThemeConfig.isMenuBarColorHighlight" @change="onMenuBarHighlightChange"></el-switch>
|
||||
<el-switch
|
||||
v-model="getThemeConfig.isColumnsMenuBarColorGradual"
|
||||
size="small"
|
||||
@change="onColumnsMenuBarGradualChange"
|
||||
:disabled="getThemeConfig.layout !== 'columns'"
|
||||
></el-switch>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -105,32 +102,37 @@
|
||||
<div class="layout-breadcrumb-seting-bar-flex">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">菜单水平折叠</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-switch v-model="getThemeConfig.isCollapse" @change="onThemeConfigChange"></el-switch>
|
||||
<el-switch v-model="getThemeConfig.isCollapse" size="small" @change="onThemeConfigChange"></el-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">菜单手风琴</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-switch v-model="getThemeConfig.isUniqueOpened" @change="setLocalThemeConfig"></el-switch>
|
||||
<el-switch v-model="getThemeConfig.isUniqueOpened" size="small" @change="setLocalThemeConfig"></el-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">固定 Header</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-switch v-model="getThemeConfig.isFixedHeader" @change="onIsFixedHeaderChange"></el-switch>
|
||||
<el-switch v-model="getThemeConfig.isFixedHeader" size="small" @change="onIsFixedHeaderChange"></el-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt15" :style="{ opacity: getThemeConfig.layout !== 'classic' ? 0.5 : 1 }">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">经典布局分割菜单</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-switch v-model="getThemeConfig.isClassicSplitMenu" :disabled="getThemeConfig.layout !== 'classic'" @change="onClassicSplitMenuChange">
|
||||
<el-switch
|
||||
v-model="getThemeConfig.isClassicSplitMenu"
|
||||
:disabled="getThemeConfig.layout !== 'classic'"
|
||||
size="small"
|
||||
@change="onClassicSplitMenuChange"
|
||||
>
|
||||
</el-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">开启锁屏</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-switch v-model="getThemeConfig.isLockScreen" @change="setLocalThemeConfig"></el-switch>
|
||||
<el-switch v-model="getThemeConfig.isLockScreen" size="small" @change="setLocalThemeConfig"></el-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt11">
|
||||
@ -142,7 +144,7 @@
|
||||
:min="1"
|
||||
:max="9999"
|
||||
@change="setLocalThemeConfig"
|
||||
size="mini"
|
||||
size="default"
|
||||
style="width: 90px"
|
||||
>
|
||||
</el-input-number>
|
||||
@ -154,7 +156,7 @@
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">侧边栏 Logo</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-switch v-model="getThemeConfig.isShowLogo" @change="onIsShowLogoChange"></el-switch>
|
||||
<el-switch v-model="getThemeConfig.isShowLogo" size="small" @change="onIsShowLogoChange"></el-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@ -166,6 +168,7 @@
|
||||
<el-switch
|
||||
v-model="getThemeConfig.isBreadcrumb"
|
||||
:disabled="getThemeConfig.layout === 'classic' || getThemeConfig.layout === 'transverse'"
|
||||
size="small"
|
||||
@change="onIsBreadcrumbChange"
|
||||
></el-switch>
|
||||
</div>
|
||||
@ -173,73 +176,72 @@
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">开启 Breadcrumb 图标</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-switch v-model="getThemeConfig.isBreadcrumbIcon" @change="setLocalThemeConfig"></el-switch>
|
||||
<el-switch v-model="getThemeConfig.isBreadcrumbIcon" size="small" @change="setLocalThemeConfig"></el-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">开启 Tagsview</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-switch v-model="getThemeConfig.isTagsview" @change="setLocalThemeConfig"></el-switch>
|
||||
<el-switch v-model="getThemeConfig.isTagsview" size="small" @change="setLocalThemeConfig"></el-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">开启 Tagsview 图标</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-switch v-model="getThemeConfig.isTagsviewIcon" @change="setLocalThemeConfig"></el-switch>
|
||||
<el-switch v-model="getThemeConfig.isTagsviewIcon" size="small" @change="setLocalThemeConfig"></el-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">开启 TagsView 缓存</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-switch v-model="getThemeConfig.isCacheTagsView" @change="setLocalThemeConfig"></el-switch>
|
||||
<el-switch v-model="getThemeConfig.isCacheTagsView" size="small" @change="setLocalThemeConfig"></el-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt15" :style="{ opacity: isMobile ? 0.5 : 1 }">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">开启 TagsView 拖拽</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-switch v-model="getThemeConfig.isSortableTagsView" :disabled="isMobile ? true : false" @change="onSortableTagsViewChange"></el-switch>
|
||||
<el-switch
|
||||
v-model="getThemeConfig.isSortableTagsView"
|
||||
:disabled="isMobile ? true : false"
|
||||
size="small"
|
||||
@change="onSortableTagsViewChange"
|
||||
></el-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">开启 TagsView 共用</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-switch v-model="getThemeConfig.isShareTagsView" @change="onShareTagsViewChange"></el-switch>
|
||||
<el-switch v-model="getThemeConfig.isShareTagsView" size="small" @change="onShareTagsViewChange"></el-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">开启 Footer</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-switch v-model="getThemeConfig.isFooter" @change="setLocalThemeConfig"></el-switch>
|
||||
<el-switch v-model="getThemeConfig.isFooter" size="small" @change="setLocalThemeConfig"></el-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">灰色模式</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-switch v-model="getThemeConfig.isGrayscale" @change="onAddFilterChange('grayscale')"></el-switch>
|
||||
<el-switch v-model="getThemeConfig.isGrayscale" size="small" @change="onAddFilterChange('grayscale')"></el-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">色弱模式</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-switch v-model="getThemeConfig.isInvert" @change="onAddFilterChange('invert')"></el-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">{深色模式</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-switch v-model="getThemeConfig.isIsDark" @change="onAddDarkChange"></el-switch>
|
||||
<el-switch v-model="getThemeConfig.isInvert" size="small" @change="onAddFilterChange('invert')"></el-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">开启水印</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-switch v-model="getThemeConfig.isWartermark" @change="onWartermarkChange"></el-switch>
|
||||
<el-switch v-model="getThemeConfig.isWartermark" size="small" @change="onWartermarkChange"></el-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt14">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">水印文案</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-input v-model="getThemeConfig.wartermarkText" size="mini" style="width: 90px" @input="onWartermarkTextInput($event)"></el-input>
|
||||
<el-input v-model="getThemeConfig.wartermarkText" size="default" style="width: 90px" @input="onWartermarkTextInput($event)"></el-input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -248,37 +250,50 @@
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">Tagsview 风格</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-select v-model="getThemeConfig.tagsStyle" placeholder="请选择" size="mini" style="width: 90px" @change="setLocalThemeConfig">
|
||||
<el-select v-model="getThemeConfig.tagsStyle" placeholder="请选择" size="default" style="width: 90px" @change="setLocalThemeConfig">
|
||||
<el-option label="风格1" value="tags-style-one"></el-option>
|
||||
<el-option label="风格2" value="tags-style-two"></el-option>
|
||||
<el-option label="风格3" value="tags-style-three"></el-option>
|
||||
<el-option label="风格4" value="tags-style-four"></el-option>
|
||||
<el-option label="风格5" value="tags-style-five"></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">主页面切换动画</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-select v-model="getThemeConfig.animation" placeholder="请选择" size="mini" style="width: 90px" @change="setLocalThemeConfig">
|
||||
<el-select v-model="getThemeConfig.animation" placeholder="请选择" size="default" 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 mt15" :style="{ opacity: getThemeConfig.layout !== 'columns' ? 0.5 : 1 }">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">分栏高亮风格</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-select v-model="getThemeConfig.columnsAsideStyle" placeholder="请选择" size="mini" style="width: 90px" @change="setLocalThemeConfig">
|
||||
<el-select
|
||||
v-model="getThemeConfig.columnsAsideStyle"
|
||||
placeholder="请选择"
|
||||
size="default"
|
||||
style="width: 90px"
|
||||
:disabled="getThemeConfig.layout !== 'columns' ? true : false"
|
||||
@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 mb27">
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt15 mb27" :style="{ opacity: getThemeConfig.layout !== 'columns' ? 0.5 : 1 }">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">分栏布局风格</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-select v-model="getThemeConfig.columnsAsideLayout" placeholder="请选择" size="mini" style="width: 90px" @change="setLocalThemeConfig">
|
||||
<el-select
|
||||
v-model="getThemeConfig.columnsAsideLayout"
|
||||
placeholder="请选择"
|
||||
size="default"
|
||||
style="width: 90px"
|
||||
:disabled="getThemeConfig.layout !== 'columns' ? true : false"
|
||||
@change="setLocalThemeConfig"
|
||||
>
|
||||
<el-option label="水平" value="columns-horizontal"></el-option>
|
||||
<el-option label="垂直" value="columns-vertical"></el-option>
|
||||
</el-select>
|
||||
@ -355,15 +370,15 @@
|
||||
</div>
|
||||
<div class="copy-config">
|
||||
<el-alert title="点击下方按钮,复制布局配置去 `src/store/modules/themeConfig.ts` 中修改。" type="warning" :closable="false"> </el-alert>
|
||||
<el-button size="small" class="copy-config-btn" type="primary" ref="copyConfigBtnRef" @click="onCopyConfigClick">
|
||||
<el-icon>
|
||||
<elementCopyDocument />
|
||||
<el-button size="default" class="copy-config-btn" type="primary" ref="copyConfigBtnRef" @click="onCopyConfigClick">
|
||||
<el-icon class="mr5">
|
||||
<ele-CopyDocument />
|
||||
</el-icon>
|
||||
一键复制配置
|
||||
</el-button>
|
||||
<el-button size="small" class="copy-config-btn-reset" type="info" @click="onResetConfigClick">
|
||||
<el-icon>
|
||||
<elementRefreshRight />
|
||||
<el-button size="default" class="copy-config-btn-reset" type="info" @click="onResetConfigClick">
|
||||
<el-icon class="mr5">
|
||||
<ele-RefreshRight />
|
||||
</el-icon>
|
||||
一键恢复默认
|
||||
</el-button>
|
||||
@ -376,7 +391,7 @@
|
||||
<script lang="ts">
|
||||
import { nextTick, onUnmounted, onMounted, getCurrentInstance, defineComponent, computed, reactive, toRefs } from 'vue';
|
||||
import { useStore } from '/@/store/index';
|
||||
import { getLightColor } from '/@/utils/theme';
|
||||
import { getLightColor, getDarkColor } from '/@/utils/theme';
|
||||
import { verifyAndSpace } from '/@/utils/toolsValidate';
|
||||
import { Local } from '/@/utils/storage';
|
||||
import Watermark from '/@/utils/wartermark';
|
||||
@ -385,7 +400,7 @@ import other from '/@/utils/other';
|
||||
export default defineComponent({
|
||||
name: 'layoutBreadcrumbSeting',
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const { proxy } = <any>getCurrentInstance();
|
||||
const store = useStore();
|
||||
const { copyText } = commonFunction();
|
||||
const state = reactive({
|
||||
@ -396,20 +411,19 @@ export default defineComponent({
|
||||
return store.state.themeConfig.themeConfig;
|
||||
});
|
||||
// 1、全局主题
|
||||
const onColorPickerChange = (color: string) => {
|
||||
setPropertyFun(`--color-${color}`, getThemeConfig.value[color]);
|
||||
setDispatchThemeConfig();
|
||||
};
|
||||
// 1、全局主题设置函数
|
||||
const setPropertyFun = (color: string, targetVal: any) => {
|
||||
document.documentElement.style.setProperty(color, targetVal);
|
||||
const onColorPickerChange = () => {
|
||||
// 颜色加深
|
||||
document.documentElement.style.setProperty('--el-color-primary-dark-2', `${getDarkColor(getThemeConfig.value.primary, 0.1)}`);
|
||||
document.documentElement.style.setProperty('--el-color-primary', getThemeConfig.value.primary);
|
||||
// 颜色变浅
|
||||
for (let i = 1; i <= 9; i++) {
|
||||
document.documentElement.style.setProperty(`${color}-light-${i}`, getLightColor(targetVal, i / 10));
|
||||
document.documentElement.style.setProperty(`--el-color-primary-light-${i}`, `${getLightColor(getThemeConfig.value.primary, i / 10)}`);
|
||||
}
|
||||
setDispatchThemeConfig();
|
||||
};
|
||||
// 2、菜单 / 顶栏
|
||||
const onBgColorPickerChange = (bg: string) => {
|
||||
document.documentElement.style.setProperty(`--bg-${bg}`, getThemeConfig.value[bg]);
|
||||
document.documentElement.style.setProperty(`--next-bg-${bg}`, (<any>getThemeConfig.value)[bg]);
|
||||
onTopBarGradualChange();
|
||||
onMenuBarGradualChange();
|
||||
onColumnsMenuBarGradualChange();
|
||||
@ -429,35 +443,17 @@ export default defineComponent({
|
||||
};
|
||||
// 2、菜单 / 顶栏 --> 背景渐变函数
|
||||
const setGraduaFun = (el: string, bool: boolean, color: string) => {
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
let els = document.querySelector(el);
|
||||
if (!els) return false;
|
||||
if (bool) els.setAttribute('style', `background-image:linear-gradient(to bottom left , ${color}, ${getLightColor(color, 0.6)})`);
|
||||
else els.setAttribute('style', `background-image:${color}`);
|
||||
document.documentElement.style.setProperty('--el-menu-bg-color', document.documentElement.style.getPropertyValue('--next-bg-menuBar'));
|
||||
if (bool) els.setAttribute('style', `background:linear-gradient(to bottom left , ${color}, ${getLightColor(color, 0.6)}) !important;`);
|
||||
else els.setAttribute('style', ``);
|
||||
setLocalThemeConfig();
|
||||
});
|
||||
};
|
||||
// 2、菜单 / 顶栏 --> 菜单字体背景高亮
|
||||
const onMenuBarHighlightChange = () => {
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
let elsItems = document.querySelectorAll('.el-menu-item');
|
||||
let elActive = document.querySelector('.el-menu-item.is-active');
|
||||
if (!elActive) return false;
|
||||
if (getThemeConfig.value.isMenuBarColorHighlight) {
|
||||
elsItems.forEach((el: any) => el.setAttribute('id', ``));
|
||||
elActive.setAttribute('id', `add-is-active`);
|
||||
Local.set('menuBarHighlightId', elActive.getAttribute('id'));
|
||||
} else {
|
||||
elActive.setAttribute('id', ``);
|
||||
}
|
||||
setLocalThemeConfig();
|
||||
}, 0);
|
||||
});
|
||||
}, 200);
|
||||
};
|
||||
// 3、界面设置 --> 菜单水平折叠
|
||||
const onThemeConfigChange = () => {
|
||||
onMenuBarHighlightChange();
|
||||
setDispatchThemeConfig();
|
||||
};
|
||||
// 3、界面设置 --> 固定 Header
|
||||
@ -518,7 +514,7 @@ export default defineComponent({
|
||||
setLocalThemeConfig();
|
||||
};
|
||||
// 4、界面显示 --> 水印文案
|
||||
const onWartermarkTextInput = (val: string) => {
|
||||
const onWartermarkTextInput = (val: any) => {
|
||||
getThemeConfig.value.wartermarkText = verifyAndSpace(val);
|
||||
if (getThemeConfig.value.wartermarkText === '') return false;
|
||||
if (getThemeConfig.value.isWartermark) Watermark.set(getThemeConfig.value.wartermarkText);
|
||||
@ -531,7 +527,6 @@ export default defineComponent({
|
||||
getThemeConfig.value.layout = layout;
|
||||
getThemeConfig.value.isDrawer = false;
|
||||
initLayoutChangeFun();
|
||||
onMenuBarHighlightChange();
|
||||
};
|
||||
// 设置布局切换函数
|
||||
const initLayoutChangeFun = () => {
|
||||
@ -539,6 +534,8 @@ export default defineComponent({
|
||||
onBgColorPickerChange('menuBarColor');
|
||||
onBgColorPickerChange('topBar');
|
||||
onBgColorPickerChange('topBarColor');
|
||||
onBgColorPickerChange('columnsMenuBar');
|
||||
onBgColorPickerChange('columnsMenuBarColor');
|
||||
};
|
||||
// 关闭弹窗时,初始化变量。变量用于处理 proxy.$refs.layoutScrollbarRef.update()
|
||||
const onDrawerClose = () => {
|
||||
@ -578,43 +575,28 @@ export default defineComponent({
|
||||
Local.clear();
|
||||
window.location.reload();
|
||||
};
|
||||
// 修复防止退出登录再进入界面时,需要刷新样式才生效的问题,初始化布局样式等(登录的时候触发,目前方案)
|
||||
// 初始化菜单样式等
|
||||
const initSetStyle = () => {
|
||||
setTimeout(() => {
|
||||
// 2、菜单 / 顶栏 --> 顶栏背景渐变
|
||||
onTopBarGradualChange();
|
||||
// 2、菜单 / 顶栏 --> 菜单背景渐变
|
||||
onMenuBarGradualChange();
|
||||
// 2、菜单 / 顶栏 --> 分栏菜单背景渐变
|
||||
onColumnsMenuBarGradualChange();
|
||||
// 2、菜单 / 顶栏 --> 菜单字体背景高亮
|
||||
onMenuBarHighlightChange();
|
||||
}, 1300);
|
||||
// 2、菜单 / 顶栏 --> 顶栏背景渐变
|
||||
onTopBarGradualChange();
|
||||
// 2、菜单 / 顶栏 --> 菜单背景渐变
|
||||
onMenuBarGradualChange();
|
||||
// 2、菜单 / 顶栏 --> 分栏菜单背景渐变
|
||||
onColumnsMenuBarGradualChange();
|
||||
};
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
// 判断当前布局是否不相同,不相同则初始化当前布局的样式,防止监听窗口大小改变时,布局配置logo、菜单背景等部分布局失效问题
|
||||
if (!Local.get('frequency')) initLayoutChangeFun();
|
||||
Local.set('frequency', 1);
|
||||
// 修复防止退出登录再进入界面时,需要刷新样式才生效的问题,初始化布局样式等(登录的时候触发,目前方案)
|
||||
proxy.mittBus.on('onSignInClick', () => {
|
||||
initSetStyle();
|
||||
});
|
||||
// 监听菜单点击,菜单字体背景高亮
|
||||
proxy.mittBus.on('onMenuClick', () => {
|
||||
onMenuBarHighlightChange();
|
||||
});
|
||||
// 监听窗口大小改变,非默认布局,设置成默认布局(适配移动端)
|
||||
proxy.mittBus.on('layoutMobileResize', (res: any) => {
|
||||
getThemeConfig.value.layout = res.layout;
|
||||
getThemeConfig.value.isDrawer = false;
|
||||
initLayoutChangeFun();
|
||||
onMenuBarHighlightChange();
|
||||
state.isMobile = other.isMobile();
|
||||
});
|
||||
setTimeout(() => {
|
||||
// 修复防止退出登录再进入界面时,需要刷新样式才生效的问题,初始化布局样式等(登录的时候触发,目前方案)
|
||||
initSetStyle();
|
||||
// 灰色模式
|
||||
if (getThemeConfig.value.isGrayscale) onAddFilterChange('grayscale');
|
||||
// 色弱模式
|
||||
@ -623,13 +605,12 @@ export default defineComponent({
|
||||
if (getThemeConfig.value.isIsDark) onAddDarkChange();
|
||||
// 开启水印
|
||||
onWartermarkChange();
|
||||
// 初始化菜单样式等
|
||||
initSetStyle();
|
||||
}, 100);
|
||||
});
|
||||
});
|
||||
onUnmounted(() => {
|
||||
// 取消监听菜单点击,菜单字体背景高亮
|
||||
proxy.mittBus.off('onMenuClick');
|
||||
proxy.mittBus.off('onSignInClick');
|
||||
proxy.mittBus.off('layoutMobileResize');
|
||||
});
|
||||
return {
|
||||
@ -639,7 +620,6 @@ export default defineComponent({
|
||||
onTopBarGradualChange,
|
||||
onMenuBarGradualChange,
|
||||
onColumnsMenuBarGradualChange,
|
||||
onMenuBarHighlightChange,
|
||||
onThemeConfigChange,
|
||||
onIsFixedHeaderChange,
|
||||
onIsShowLogoChange,
|
||||
@ -673,9 +653,10 @@ export default defineComponent({
|
||||
.layout-breadcrumb-seting-bar-flex {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 5px;
|
||||
&-label {
|
||||
flex: 1;
|
||||
color: #666666;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
}
|
||||
.layout-drawer-content-flex {
|
||||
@ -694,16 +675,16 @@ export default defineComponent({
|
||||
.el-container {
|
||||
height: 100%;
|
||||
.el-aside-dark {
|
||||
background-color: #b3c0d1;
|
||||
background-color: var(--next-color-seting-header);
|
||||
}
|
||||
.el-aside {
|
||||
background-color: #d3dce6;
|
||||
background-color: var(--next-color-seting-aside);
|
||||
}
|
||||
.el-header {
|
||||
background-color: #b3c0d1;
|
||||
background-color: var(--next-color-seting-header);
|
||||
}
|
||||
.el-main {
|
||||
background-color: #e9eef3;
|
||||
background-color: var(--next-color-seting-main);
|
||||
}
|
||||
}
|
||||
.el-circular {
|
||||
@ -714,7 +695,7 @@ export default defineComponent({
|
||||
}
|
||||
.drawer-layout-active {
|
||||
border: 1px solid;
|
||||
border-color: var(--color-primary);
|
||||
border-color: var(--el-color-primary);
|
||||
}
|
||||
.layout-tips-warp,
|
||||
.layout-tips-warp-active {
|
||||
@ -724,7 +705,7 @@ export default defineComponent({
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
border: 1px solid;
|
||||
border-color: var(--color-primary-light-4);
|
||||
border-color: var(--el-color-primary-light-4);
|
||||
border-radius: 100%;
|
||||
padding: 4px;
|
||||
.layout-tips-box {
|
||||
@ -733,7 +714,7 @@ export default defineComponent({
|
||||
height: 30px;
|
||||
z-index: 9;
|
||||
border: 1px solid;
|
||||
border-color: var(--color-primary-light-4);
|
||||
border-color: var(--el-color-primary-light-4);
|
||||
border-radius: 100%;
|
||||
.layout-tips-txt {
|
||||
transition: inherit;
|
||||
@ -743,11 +724,11 @@ export default defineComponent({
|
||||
line-height: 1;
|
||||
letter-spacing: 2px;
|
||||
white-space: nowrap;
|
||||
color: var(--color-primary-light-4);
|
||||
color: var(--el-color-primary-light-4);
|
||||
text-align: center;
|
||||
transform: rotate(30deg);
|
||||
left: -1px;
|
||||
background-color: #e9eef3;
|
||||
background-color: var(--next-color-seting-main);
|
||||
width: 32px;
|
||||
height: 17px;
|
||||
line-height: 17px;
|
||||
@ -756,13 +737,13 @@ export default defineComponent({
|
||||
}
|
||||
.layout-tips-warp-active {
|
||||
border: 1px solid;
|
||||
border-color: var(--color-primary);
|
||||
border-color: var(--el-color-primary);
|
||||
.layout-tips-box {
|
||||
border: 1px solid;
|
||||
border-color: var(--color-primary);
|
||||
border-color: var(--el-color-primary);
|
||||
.layout-tips-txt {
|
||||
color: var(--color-primary) !important;
|
||||
background-color: #e9eef3 !important;
|
||||
color: var(--el-color-primary) !important;
|
||||
background-color: var(--next-color-seting-main) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -770,18 +751,18 @@ export default defineComponent({
|
||||
.el-circular {
|
||||
transition: all 0.3s ease-in-out;
|
||||
border: 1px solid;
|
||||
border-color: var(--color-primary);
|
||||
border-color: var(--el-color-primary);
|
||||
}
|
||||
.layout-tips-warp {
|
||||
transition: all 0.3s ease-in-out;
|
||||
border-color: var(--color-primary);
|
||||
border-color: var(--el-color-primary);
|
||||
.layout-tips-box {
|
||||
transition: inherit;
|
||||
border-color: var(--color-primary);
|
||||
border-color: var(--el-color-primary);
|
||||
.layout-tips-txt {
|
||||
transition: inherit;
|
||||
color: var(--color-primary) !important;
|
||||
background-color: #e9eef3 !important;
|
||||
color: var(--el-color-primary) !important;
|
||||
background-color: var(--next-color-seting-main) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,33 +6,30 @@
|
||||
</div>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="" :disabled="disabledSize === ''">默认</el-dropdown-item>
|
||||
<el-dropdown-item command="medium" :disabled="disabledSize === 'medium'">中等</el-dropdown-item>
|
||||
<el-dropdown-item command="small" :disabled="disabledSize === 'small'">小型</el-dropdown-item>
|
||||
<el-dropdown-item command="mini" :disabled="disabledSize === 'mini'">超小</el-dropdown-item>
|
||||
<el-dropdown-item command="medium" :disabled="disabledSize === 'large'">大型</el-dropdown-item>
|
||||
<el-dropdown-item command="small" :disabled="disabledSize === 'default'">默认</el-dropdown-item>
|
||||
<el-dropdown-item command="mini" :disabled="disabledSize === 'small'">小型</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<div class="layout-navbars-breadcrumb-user-icon" @click="onSearchClick">
|
||||
<el-icon title="菜单搜索">
|
||||
<elementSearch />
|
||||
<ele-Search />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="layout-navbars-breadcrumb-user-icon" @click="onLayoutSetingClick">
|
||||
<i class="icon-skin iconfont" title="布局配置"></i>
|
||||
</div>
|
||||
<div class="layout-navbars-breadcrumb-user-icon">
|
||||
<el-popover placement="bottom" trigger="click" v-model:visible="isShowUserNewsPopover" :width="300" popper-class="el-popover-pupop-user-news">
|
||||
<el-popover placement="bottom" trigger="click">
|
||||
<template #reference>
|
||||
<el-badge :is-dot="true" @click="isShowUserNewsPopover = !isShowUserNewsPopover">
|
||||
<el-badge :is-dot="true">
|
||||
<el-icon title="消息">
|
||||
<elementBell />
|
||||
<ele-Bell />
|
||||
</el-icon>
|
||||
</el-badge>
|
||||
</template>
|
||||
<transition name="el-zoom-in-top">
|
||||
<UserNews v-show="isShowUserNewsPopover" />
|
||||
</transition>
|
||||
<UserNews />
|
||||
</el-popover>
|
||||
</div>
|
||||
<div class="layout-navbars-breadcrumb-user-icon mr10" @click="onScreenfullClick">
|
||||
@ -41,9 +38,9 @@
|
||||
<el-dropdown :show-timeout="70" :hide-timeout="50" @command="onHandleCommandClick">
|
||||
<span class="layout-navbars-breadcrumb-user-link">
|
||||
<img :src="getUserInfos.photo" class="layout-navbars-breadcrumb-user-link-photo mr5" />
|
||||
{{ getUserInfos.userName === '' ? 'test' : getUserInfos.userName }}
|
||||
{{ getUserInfos.userName === '' ? 'common' : getUserInfos.userName }}
|
||||
<el-icon class="el-icon--right">
|
||||
<elementArrowDown />
|
||||
<ele-ArrowDown />
|
||||
</el-icon>
|
||||
</span>
|
||||
<template #dropdown>
|
||||
@ -61,7 +58,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { ref, getCurrentInstance, computed, reactive, toRefs, onMounted } from 'vue';
|
||||
import { ref, getCurrentInstance, computed, reactive, toRefs, onMounted, defineComponent } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import screenfull from 'screenfull';
|
||||
@ -70,22 +67,21 @@ import { useStore } from '/@/store/index';
|
||||
import { Session, Local } from '/@/utils/storage';
|
||||
import UserNews from '/@/layout/navBars/breadcrumb/userNews.vue';
|
||||
import Search from '/@/layout/navBars/breadcrumb/search.vue';
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'layoutBreadcrumbUser',
|
||||
components: { UserNews, Search },
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const { proxy } = <any>getCurrentInstance();
|
||||
const router = useRouter();
|
||||
const store = useStore();
|
||||
const searchRef = ref();
|
||||
const state = reactive({
|
||||
isScreenfull: false,
|
||||
isShowUserNewsPopover: false,
|
||||
disabledSize: '',
|
||||
disabledSize: 'large',
|
||||
});
|
||||
// 获取用户信息 vuex
|
||||
const getUserInfos = computed(() => {
|
||||
return store.state.userInfos.userInfos;
|
||||
return <any>store.state.userInfos.userInfos;
|
||||
});
|
||||
// 获取布局配置信息
|
||||
const getThemeConfig = computed(() => {
|
||||
@ -93,10 +89,11 @@ export default {
|
||||
});
|
||||
// 设置分割样式
|
||||
const layoutUserFlexNum = computed(() => {
|
||||
let { layout, isClassicSplitMenu } = getThemeConfig.value;
|
||||
let num = '';
|
||||
if (layout === 'defaults' || (layout === 'classic' && !isClassicSplitMenu) || layout === 'columns') num = 1;
|
||||
else num = null;
|
||||
let num: string | number = '';
|
||||
const { layout, isClassicSplitMenu } = getThemeConfig.value;
|
||||
const layoutArr: string[] = ['defaults', 'columns'];
|
||||
if (layoutArr.includes(layout) || (layout === 'classic' && !isClassicSplitMenu)) num = '1';
|
||||
else num = '';
|
||||
return num;
|
||||
});
|
||||
// 全屏点击时
|
||||
@ -126,6 +123,7 @@ export default {
|
||||
showCancelButton: true,
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
buttonSize: 'default',
|
||||
beforeClose: (action, instance, done) => {
|
||||
if (action === 'confirm') {
|
||||
instance.confirmButtonLoading = true;
|
||||
@ -141,13 +139,13 @@ export default {
|
||||
}
|
||||
},
|
||||
})
|
||||
.then(() => {
|
||||
.then(async () => {
|
||||
Session.clear(); // 清除缓存/token等
|
||||
resetRoute(); // 删除/重置路由
|
||||
router.push('/login');
|
||||
await resetRoute(); // 删除/重置路由
|
||||
ElMessage.success('安全退出成功!');
|
||||
setTimeout(() => {
|
||||
ElMessage.success('安全退出成功!');
|
||||
}, 300);
|
||||
window.location.href = ''; // 去登录页
|
||||
}, 500);
|
||||
})
|
||||
.catch(() => {});
|
||||
} else if (path === 'wareHouse') {
|
||||
@ -172,18 +170,15 @@ export default {
|
||||
// 初始化全局组件大小
|
||||
const initComponentSize = () => {
|
||||
switch (Local.get('themeConfig').globalComponentSize) {
|
||||
case '':
|
||||
state.disabledSize = '';
|
||||
case 'large':
|
||||
state.disabledSize = 'large';
|
||||
break;
|
||||
case 'medium':
|
||||
state.disabledSize = 'medium';
|
||||
case 'default':
|
||||
state.disabledSize = 'default';
|
||||
break;
|
||||
case 'small':
|
||||
state.disabledSize = 'small';
|
||||
break;
|
||||
case 'mini':
|
||||
state.disabledSize = 'mini';
|
||||
break;
|
||||
}
|
||||
};
|
||||
// 页面加载时
|
||||
@ -204,7 +199,7 @@ export default {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@ -226,13 +221,13 @@ export default {
|
||||
&-icon {
|
||||
padding: 0 10px;
|
||||
cursor: pointer;
|
||||
color: var(--bg-topBarColor);
|
||||
color: var(--next-bg-topBarColor);
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.04);
|
||||
background: var(--next-color-user-hover);
|
||||
i {
|
||||
display: inline-block;
|
||||
animation: logoAnimation 0.3s ease-in-out;
|
||||
@ -240,7 +235,7 @@ export default {
|
||||
}
|
||||
}
|
||||
::v-deep(.el-dropdown) {
|
||||
color: var(--bg-topBarColor);
|
||||
color: var(--next-bg-topBarColor);
|
||||
}
|
||||
::v-deep(.el-badge) {
|
||||
height: 40px;
|
||||
|
||||
@ -21,8 +21,8 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { reactive, toRefs } from 'vue';
|
||||
export default {
|
||||
import { reactive, toRefs, defineComponent } from 'vue';
|
||||
export default defineComponent({
|
||||
name: 'layoutBreadcrumbUserNews',
|
||||
setup() {
|
||||
const state = reactive({
|
||||
@ -53,21 +53,21 @@ export default {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.layout-navbars-breadcrumb-user-news {
|
||||
.head-box {
|
||||
display: flex;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
border-bottom: 1px solid var(--el-border-color-lighter);
|
||||
box-sizing: border-box;
|
||||
color: #333333;
|
||||
color: var(--el-text-color-primary);
|
||||
justify-content: space-between;
|
||||
height: 35px;
|
||||
align-items: center;
|
||||
.head-box-btn {
|
||||
color: var(--color-primary);
|
||||
color: var(--el-color-primary);
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
opacity: 0.8;
|
||||
@ -84,25 +84,25 @@ export default {
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
.content-box-msg {
|
||||
color: #999999;
|
||||
color: var(--el-text-color-secondary);
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.content-box-time {
|
||||
color: #999999;
|
||||
color: var(--el-text-color-secondary);
|
||||
}
|
||||
}
|
||||
}
|
||||
.foot-box {
|
||||
height: 35px;
|
||||
color: var(--color-primary);
|
||||
color: var(--el-color-primary);
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
opacity: 0.8;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-top: 1px solid #ebeef5;
|
||||
border-top: 1px solid var(--el-border-color-lighter);
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@ -6,11 +6,11 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { computed, defineComponent } from 'vue';
|
||||
import { useStore } from '/@/store/index';
|
||||
import BreadcrumbIndex from '/@/layout/navBars/breadcrumb/index.vue';
|
||||
import TagsView from '/@/layout/navBars/tagsView/tagsView.vue';
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'layoutNavBars',
|
||||
components: { BreadcrumbIndex, TagsView },
|
||||
setup() {
|
||||
@ -24,7 +24,7 @@ export default {
|
||||
setShowTagsView,
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@ -36,16 +36,22 @@ export default defineComponent({
|
||||
props: {
|
||||
dropdown: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {
|
||||
x: 0,
|
||||
y: 0,
|
||||
};
|
||||
},
|
||||
},
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const state = reactive({
|
||||
isShow: false,
|
||||
dropdownList: [
|
||||
{ contextMenuClickId: 0, txt: '刷新', affix: false, icon: 'elementRefreshRight' },
|
||||
{ contextMenuClickId: 1, txt: '关闭', affix: false, icon: 'elementClose' },
|
||||
{ contextMenuClickId: 2, txt: '关闭其它', affix: false, icon: 'elementCircleClose' },
|
||||
{ contextMenuClickId: 3, txt: '全部关闭', affix: false, icon: 'elementFolderDelete' },
|
||||
{ contextMenuClickId: 0, txt: '刷新', affix: false, icon: 'ele-RefreshRight' },
|
||||
{ contextMenuClickId: 1, txt: '关闭', affix: false, icon: 'ele-Close' },
|
||||
{ contextMenuClickId: 2, txt: '关闭其它', affix: false, icon: 'ele-CircleClose' },
|
||||
{ contextMenuClickId: 3, txt: '全部关闭', affix: false, icon: 'ele-FolderDelete' },
|
||||
{ contextMenuClickId: 4, txt: '当前页全屏', affix: false, icon: 'iconfont icon-fullscreen' },
|
||||
],
|
||||
item: {},
|
||||
|
||||
@ -16,20 +16,24 @@
|
||||
}
|
||||
"
|
||||
>
|
||||
<i class="iconfont icon-webicon318 layout-navbars-tagsview-ul-li-iconfont font14" v-if="isActive(v)"></i>
|
||||
<i class="layout-navbars-tagsview-ul-li-iconfont" :class="v.meta.icon" v-if="!isActive(v) && getThemeConfig.isTagsviewIcon"></i>
|
||||
<i class="iconfont icon-webicon318 layout-navbars-tagsview-ul-li-iconfont" v-if="isActive(v)"></i>
|
||||
<SvgIcon :name="v.meta.icon" v-if="!isActive(v) && getThemeConfig.isTagsviewIcon" class="pr5" />
|
||||
<span>{{ v.meta.title }}</span>
|
||||
<template v-if="isActive(v)">
|
||||
<SvgIcon name="elementRefreshRight" class="ml5" @click.stop="refreshCurrentTagsView($route.fullPath)" />
|
||||
<SvgIcon
|
||||
name="elementClose"
|
||||
name="ele-RefreshRight"
|
||||
class="ml5 layout-navbars-tagsview-ul-li-refresh"
|
||||
@click.stop="refreshCurrentTagsView($route.fullPath)"
|
||||
/>
|
||||
<SvgIcon
|
||||
name="ele-Close"
|
||||
class="layout-navbars-tagsview-ul-li-icon layout-icon-active"
|
||||
v-if="!v.meta.isAffix"
|
||||
@click.stop="closeCurrentTagsView(getThemeConfig.isShareTagsView ? v.path : v.url)"
|
||||
/>
|
||||
</template>
|
||||
<SvgIcon
|
||||
name="elementClose"
|
||||
name="ele-Close"
|
||||
class="layout-navbars-tagsview-ul-li-icon layout-icon-three"
|
||||
v-if="!v.meta.isAffix"
|
||||
@click.stop="closeCurrentTagsView(getThemeConfig.isShareTagsView ? v.path : v.url)"
|
||||
@ -42,7 +46,20 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive, onMounted, computed, ref, nextTick, onBeforeUpdate, onBeforeMount, onUnmounted, getCurrentInstance, watch } from 'vue';
|
||||
import {
|
||||
toRefs,
|
||||
reactive,
|
||||
onMounted,
|
||||
computed,
|
||||
ref,
|
||||
nextTick,
|
||||
onBeforeUpdate,
|
||||
onBeforeMount,
|
||||
onUnmounted,
|
||||
getCurrentInstance,
|
||||
watch,
|
||||
defineComponent,
|
||||
} from 'vue';
|
||||
import { useRoute, useRouter, onBeforeRouteUpdate } from 'vue-router';
|
||||
import Sortable from 'sortablejs';
|
||||
import { ElMessage } from 'element-plus';
|
||||
@ -51,19 +68,47 @@ import { Session } from '/@/utils/storage';
|
||||
import { isObjectValueEqual } from '/@/utils/arrayOperation';
|
||||
import other from '/@/utils/other';
|
||||
import Contextmenu from '/@/layout/navBars/tagsView/contextmenu.vue';
|
||||
export default {
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface TagsViewState {
|
||||
routeActive: string;
|
||||
routePath: string | unknown;
|
||||
dropdown: {
|
||||
x: string | number;
|
||||
y: string | number;
|
||||
};
|
||||
tagsRefsIndex: number;
|
||||
tagsViewList: any[];
|
||||
sortable: any;
|
||||
tagsViewRoutesList: any[];
|
||||
}
|
||||
interface RouteParams {
|
||||
path: string;
|
||||
url: string;
|
||||
}
|
||||
interface CurrentContextmenu {
|
||||
meta: {
|
||||
isDynamic: boolean;
|
||||
};
|
||||
params: any;
|
||||
query: any;
|
||||
path: string;
|
||||
contextMenuClickId: string | number;
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'layoutTagsView',
|
||||
components: { Contextmenu },
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const tagsRefs = ref([]);
|
||||
const { proxy } = <any>getCurrentInstance();
|
||||
const tagsRefs = ref<any[]>([]);
|
||||
const scrollbarRef = ref();
|
||||
const contextmenuRef = ref();
|
||||
const tagsUlRef = ref();
|
||||
const store = useStore();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const state: any = reactive({
|
||||
const state = reactive<TagsViewState>({
|
||||
routeActive: '',
|
||||
routePath: route.path,
|
||||
dropdown: { x: '', y: '' },
|
||||
@ -81,7 +126,7 @@ export default {
|
||||
return store.state.themeConfig.themeConfig;
|
||||
});
|
||||
// 设置 tagsView 高亮
|
||||
const isActive = (v) => {
|
||||
const isActive = (v: RouteParams) => {
|
||||
if (getThemeConfig.value.isShareTagsView) {
|
||||
return v.path === state.routePath;
|
||||
} else {
|
||||
@ -160,7 +205,7 @@ export default {
|
||||
// 防止拿取不到路由信息
|
||||
nextTick(async () => {
|
||||
// 修复:https://gitee.com/lyt-top/vue-next-admin/issues/I3YX6G
|
||||
let item = '';
|
||||
let item: any = '';
|
||||
if (to && to.meta.isDynamic) {
|
||||
// 动态路由(xxx/:id/:name"):参数不同,开启多个 tagsview
|
||||
if (!getThemeConfig.value.isShareTagsView) await solveAddTagsView(path, to);
|
||||
@ -250,7 +295,7 @@ export default {
|
||||
};
|
||||
// 当前项右键菜单点击,拿当前点击的路由路径对比 浏览器缓存中的 tagsView 路由数组,取当前点击项的详细路由信息
|
||||
// 防止 tagsView 非当前页演示时,操作异常
|
||||
const getCurrentRouteItem = (path: string, cParams: { [key: string]: any }) => {
|
||||
const getCurrentRouteItem = (path: string, cParams: any) => {
|
||||
const itemRoute = Session.get('tagsViewList') ? Session.get('tagsViewList') : state.tagsViewList;
|
||||
return itemRoute.find((v: any) => {
|
||||
if (
|
||||
@ -267,7 +312,7 @@ export default {
|
||||
});
|
||||
};
|
||||
// 当前项右键菜单点击
|
||||
const onCurrentContextmenuClick = async (item) => {
|
||||
const onCurrentContextmenuClick = async (item: CurrentContextmenu) => {
|
||||
const cParams = item.meta.isDynamic ? item.params : item.query;
|
||||
if (!getCurrentRouteItem(item.path, cParams)) return ElMessage({ type: 'warning', message: '请正确输入路径及完整参数(query、params)' });
|
||||
const { path, name, params, query, meta, url } = getCurrentRouteItem(item.path, cParams);
|
||||
@ -382,7 +427,7 @@ export default {
|
||||
});
|
||||
};
|
||||
// 获取 tagsView 的下标:用于处理 tagsView 点击时的横向滚动
|
||||
const getTagsRefsIndex = (path: string) => {
|
||||
const getTagsRefsIndex = (path: string | unknown) => {
|
||||
nextTick(async () => {
|
||||
// await 使用该写法,防止拿取不到 tagsViewList 列表数据不完整
|
||||
let tagsViewList = await state.tagsViewList;
|
||||
@ -399,7 +444,7 @@ export default {
|
||||
};
|
||||
// 设置 tagsView 可以进行拖拽
|
||||
const initSortable = async () => {
|
||||
const el = document.querySelector('.layout-navbars-tagsview-ul') as HTMLElement;
|
||||
const el = <HTMLElement>document.querySelector('.layout-navbars-tagsview-ul');
|
||||
if (!el) return false;
|
||||
state.sortable.el && state.sortable.destroy();
|
||||
state.sortable = Sortable.create(el, {
|
||||
@ -429,7 +474,7 @@ export default {
|
||||
// 拖动问题,https://gitee.com/lyt-top/vue-next-admin/issues/I3ZRRI
|
||||
window.addEventListener('resize', onSortableResize);
|
||||
// 监听非本页面调用 0 刷新当前,1 关闭当前,2 关闭其它,3 关闭全部 4 当前页全屏
|
||||
proxy.mittBus.on('onCurrentContextmenuClick', (data: object) => {
|
||||
proxy.mittBus.on('onCurrentContextmenuClick', (data: CurrentContextmenu) => {
|
||||
onCurrentContextmenuClick(data);
|
||||
});
|
||||
// 监听布局配置界面开启/关闭拖拽
|
||||
@ -486,7 +531,6 @@ export default {
|
||||
return {
|
||||
isActive,
|
||||
onContextmenu,
|
||||
getTagsViewRoutes,
|
||||
onTagsClick,
|
||||
tagsRefs,
|
||||
contextmenuRef,
|
||||
@ -501,13 +545,15 @@ export default {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.layout-navbars-tagsview {
|
||||
background-color: var(--el-color-white);
|
||||
border-bottom: 1px solid #f1f2f3;
|
||||
border-bottom: 1px solid var(--next-border-color-light);
|
||||
position: relative;
|
||||
z-index: 4;
|
||||
::v-deep(.el-scrollbar__wrap) {
|
||||
overflow-x: auto !important;
|
||||
}
|
||||
@ -536,9 +582,9 @@ export default {
|
||||
cursor: pointer;
|
||||
justify-content: space-between;
|
||||
&:hover {
|
||||
background-color: var(--color-primary-light-9);
|
||||
color: var(--color-primary);
|
||||
border-color: var(--color-primary-light-6);
|
||||
background-color: var(--el-color-primary-light-9);
|
||||
color: var(--el-color-primary);
|
||||
border-color: var(--el-color-primary-light-6);
|
||||
}
|
||||
&-iconfont {
|
||||
position: relative;
|
||||
@ -554,8 +600,8 @@ export default {
|
||||
line-height: 14px;
|
||||
right: -5px;
|
||||
&:hover {
|
||||
color: var(--color-whites);
|
||||
background-color: var(--color-primary-light-3);
|
||||
color: var(--el-color-white);
|
||||
background-color: var(--el-color-primary-light-3);
|
||||
}
|
||||
}
|
||||
.layout-icon-active {
|
||||
@ -566,64 +612,12 @@ export default {
|
||||
}
|
||||
}
|
||||
.is-active {
|
||||
color: var(--color-whites);
|
||||
background: var(--color-primary);
|
||||
border-color: var(--color-primary);
|
||||
color: var(--el-color-white);
|
||||
background: var(--el-color-primary);
|
||||
border-color: var(--el-color-primary);
|
||||
transition: border-color 3s ease;
|
||||
}
|
||||
}
|
||||
// 风格2
|
||||
.tags-style-two {
|
||||
.layout-navbars-tagsview-ul-li {
|
||||
height: 34px !important;
|
||||
line-height: 34px !important;
|
||||
border: none !important;
|
||||
.layout-navbars-tagsview-ul-li-iconfont {
|
||||
display: none;
|
||||
}
|
||||
.layout-icon-active {
|
||||
display: none;
|
||||
}
|
||||
.layout-icon-three {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.is-active {
|
||||
background: none !important;
|
||||
color: var(--color-primary) !important;
|
||||
border-bottom: 2px solid !important;
|
||||
border-color: var(--color-primary) !important;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
}
|
||||
// 风格3
|
||||
.tags-style-three {
|
||||
.layout-navbars-tagsview-ul-li {
|
||||
height: 34px !important;
|
||||
line-height: 34px !important;
|
||||
border-right: 1px solid #f6f6f6 !important;
|
||||
border-top: none !important;
|
||||
border-bottom: none !important;
|
||||
border-left: none !important;
|
||||
border-radius: 0 !important;
|
||||
margin-right: 0 !important;
|
||||
&:first-of-type {
|
||||
border-left: 1px solid #f6f6f6 !important;
|
||||
}
|
||||
.layout-icon-active {
|
||||
display: none;
|
||||
}
|
||||
.layout-icon-three {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.is-active {
|
||||
background: var(--el-color-white) !important;
|
||||
color: var(--color-primary) !important;
|
||||
border-top: 1px solid !important;
|
||||
border-top-color: var(--color-primary) !important;
|
||||
}
|
||||
}
|
||||
// 风格4
|
||||
.tags-style-four {
|
||||
.layout-navbars-tagsview-ul-li {
|
||||
@ -643,7 +637,41 @@ export default {
|
||||
}
|
||||
.is-active {
|
||||
background: none !important;
|
||||
color: var(--color-primary) !important;
|
||||
color: var(--el-color-primary) !important;
|
||||
}
|
||||
}
|
||||
// 风格5
|
||||
.tags-style-five {
|
||||
align-items: flex-end;
|
||||
.tags-style-five-svg {
|
||||
-webkit-mask-box-image: url("data:image/svg+xml,%3Csvg width='68' height='34' viewBox='0 0 68 34' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='m27,0c-7.99582,0 -11.95105,0.00205 -12,12l0,6c0,8.284 -0.48549,16.49691 -8.76949,16.49691l54.37857,-0.11145c-8.284,0 -8.60908,-8.10146 -8.60908,-16.38546l0,-6c0.11145,-12.08445 -4.38441,-12 -12,-12l-13,0z' fill='%23409eff'/%3E%3C/svg%3E")
|
||||
12 27 15;
|
||||
}
|
||||
.layout-navbars-tagsview-ul-li {
|
||||
padding: 0 5px;
|
||||
border-width: 15px 27px 15px;
|
||||
border-style: solid;
|
||||
border-color: transparent;
|
||||
margin: 0 -15px;
|
||||
.layout-icon-active,
|
||||
.layout-navbars-tagsview-ul-li-iconfont,
|
||||
.layout-navbars-tagsview-ul-li-refresh {
|
||||
display: none;
|
||||
}
|
||||
.layout-icon-three {
|
||||
display: block;
|
||||
}
|
||||
&:hover {
|
||||
@extend .tags-style-five-svg;
|
||||
background: var(--el-color-primary-light-9);
|
||||
color: unset;
|
||||
}
|
||||
}
|
||||
.is-active {
|
||||
@extend .tags-style-five-svg;
|
||||
background: var(--el-color-primary-light-9) !important;
|
||||
color: var(--el-color-primary) !important;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,18 +10,20 @@
|
||||
</template>
|
||||
<SubItem :chil="val.children" />
|
||||
</el-sub-menu>
|
||||
<el-menu-item :index="val.path" :key="val.path" v-else>
|
||||
<template #title v-if="!val.meta.isLink || (val.meta.isLink && val.meta.isIframe)">
|
||||
<SvgIcon :name="val.meta.icon" />
|
||||
{{ val.meta.title }}
|
||||
</template>
|
||||
<template #title v-else>
|
||||
<a :href="val.meta.isLink" target="_blank" rel="opener">
|
||||
<template v-else>
|
||||
<el-menu-item :index="val.path" :key="val.path">
|
||||
<template #title v-if="!val.meta.isLink || (val.meta.isLink && val.meta.isIframe)">
|
||||
<SvgIcon :name="val.meta.icon" />
|
||||
{{ val.meta.title }}
|
||||
</a>
|
||||
</template>
|
||||
</el-menu-item>
|
||||
</template>
|
||||
<template #title v-else>
|
||||
<a :href="val.meta.isLink" target="_blank" rel="opener">
|
||||
<SvgIcon :name="val.meta.icon" />
|
||||
{{ val.meta.title }}
|
||||
</a>
|
||||
</template>
|
||||
</el-menu-item>
|
||||
</template>
|
||||
</template>
|
||||
</el-menu>
|
||||
</el-scrollbar>
|
||||
@ -43,7 +45,7 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const { proxy } = <any>getCurrentInstance();
|
||||
const route = useRoute();
|
||||
const store = useStore();
|
||||
const state = reactive({
|
||||
@ -51,19 +53,19 @@ export default defineComponent({
|
||||
});
|
||||
// 获取父级菜单数据
|
||||
const menuLists = computed(() => {
|
||||
return props.menuList;
|
||||
return <any>props.menuList;
|
||||
});
|
||||
// 设置横向滚动条可以鼠标滚轮滚动
|
||||
const onElMenuHorizontalScroll = (e: any) => {
|
||||
const eventDelta = e.wheelDelta || -e.deltaY * 40;
|
||||
proxy.$refs.elMenuHorizontalScrollRef.$refs.wrap.scrollLeft = proxy.$refs.elMenuHorizontalScrollRef.$refs.wrap.scrollLeft + eventDelta / 4;
|
||||
proxy.$refs.elMenuHorizontalScrollRef.$refs.wrap$.scrollLeft = proxy.$refs.elMenuHorizontalScrollRef.$refs.wrap.scrollLeft + eventDelta / 4;
|
||||
};
|
||||
// 初始化数据,页面刷新时,滚动条滚动到对应位置
|
||||
const initElMenuOffsetLeft = () => {
|
||||
nextTick(() => {
|
||||
let els: any = document.querySelector('.el-menu.el-menu--horizontal li.is-active');
|
||||
if (!els) return false;
|
||||
proxy.$refs.elMenuHorizontalScrollRef.$refs.wrap.scrollLeft = els.offsetLeft;
|
||||
proxy.$refs.elMenuHorizontalScrollRef.$refs.wrap$.scrollLeft = els.offsetLeft;
|
||||
});
|
||||
};
|
||||
// 路由过滤递归函数
|
||||
@ -91,10 +93,10 @@ export default defineComponent({
|
||||
return currentData;
|
||||
};
|
||||
// 设置页面当前路由高亮
|
||||
const setCurrentRouterHighlight = (currentRoute) => {
|
||||
const setCurrentRouterHighlight = (currentRoute: any) => {
|
||||
const { path, meta } = currentRoute;
|
||||
if (store.state.themeConfig.themeConfig.layout === 'classic') {
|
||||
state.defaultActive = `/${path.split('/')[1]}`;
|
||||
(<any>state.defaultActive) = `/${path.split('/')[1]}`;
|
||||
} else {
|
||||
const pathSplit = meta.isDynamic ? meta.isDynamicPath.split('/') : path.split('/');
|
||||
if (pathSplit.length >= 4 && meta.isHide) state.defaultActive = pathSplit.splice(0, 3).join('/');
|
||||
@ -113,7 +115,6 @@ export default defineComponent({
|
||||
onBeforeRouteUpdate((to) => {
|
||||
// 修复:https://gitee.com/lyt-top/vue-next-admin/issues/I3YX6G
|
||||
setCurrentRouterHighlight(to);
|
||||
proxy.mittBus.emit('onMenuClick');
|
||||
// 修复经典布局开启切割菜单时,点击tagsView后左侧导航菜单数据不变的问题
|
||||
let { layout, isClassicSplitMenu } = store.state.themeConfig.themeConfig;
|
||||
if (layout === 'classic' && isClassicSplitMenu) {
|
||||
|
||||
@ -7,18 +7,20 @@
|
||||
</template>
|
||||
<sub-item :chil="val.children" />
|
||||
</el-sub-menu>
|
||||
<el-menu-item :index="val.path" :key="val.path" v-else>
|
||||
<template v-if="!val.meta.isLink || (val.meta.isLink && val.meta.isIframe)">
|
||||
<SvgIcon :name="val.meta.icon" />
|
||||
<span>{{ val.meta.title }}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<a :href="val.meta.isLink" target="_blank" rel="opener">
|
||||
<template v-else>
|
||||
<el-menu-item :index="val.path" :key="val.path">
|
||||
<template v-if="!val.meta.isLink || (val.meta.isLink && val.meta.isIframe)">
|
||||
<SvgIcon :name="val.meta.icon" />
|
||||
{{ val.meta.title }}
|
||||
</a>
|
||||
</template>
|
||||
</el-menu-item>
|
||||
<span>{{ val.meta.title }}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<a :href="val.meta.isLink" target="_blank" rel="opener">
|
||||
<SvgIcon :name="val.meta.icon" />
|
||||
{{ val.meta.title }}
|
||||
</a>
|
||||
</template>
|
||||
</el-menu-item>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
@ -35,7 +37,7 @@ export default defineComponent({
|
||||
setup(props) {
|
||||
// 获取父级菜单数据
|
||||
const chils = computed(() => {
|
||||
return props.chil;
|
||||
return <any>props.chil;
|
||||
});
|
||||
return {
|
||||
chils,
|
||||
|
||||
@ -15,21 +15,23 @@
|
||||
</template>
|
||||
<SubItem :chil="val.children" />
|
||||
</el-sub-menu>
|
||||
<el-menu-item :index="val.path" :key="val.path" v-else>
|
||||
<SvgIcon :name="val.meta.icon" />
|
||||
<template #title v-if="!val.meta.isLink || (val.meta.isLink && val.meta.isIframe)">
|
||||
<span>{{ val.meta.title }}</span>
|
||||
</template>
|
||||
<template #title v-else>
|
||||
<a :href="val.meta.isLink" target="_blank" rel="opener">{{ val.meta.title }}</a></template
|
||||
>
|
||||
</el-menu-item>
|
||||
<template v-else>
|
||||
<el-menu-item :index="val.path" :key="val.path">
|
||||
<SvgIcon :name="val.meta.icon" />
|
||||
<template #title v-if="!val.meta.isLink || (val.meta.isLink && val.meta.isIframe)">
|
||||
<span>{{ val.meta.title }}</span>
|
||||
</template>
|
||||
<template #title v-else>
|
||||
<a :href="val.meta.isLink" target="_blank" rel="opener" class="w100">{{ val.meta.title }}</a>
|
||||
</template>
|
||||
</el-menu-item>
|
||||
</template>
|
||||
</template>
|
||||
</el-menu>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive, computed, defineComponent, getCurrentInstance, onMounted, watch } from 'vue';
|
||||
import { toRefs, reactive, computed, defineComponent, onMounted, watch } from 'vue';
|
||||
import { useRoute, onBeforeRouteUpdate } from 'vue-router';
|
||||
import { useStore } from '/@/store/index';
|
||||
import SubItem from '/@/layout/navMenu/subItem.vue';
|
||||
@ -43,7 +45,6 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const store = useStore();
|
||||
const route = useRoute();
|
||||
const state = reactive({
|
||||
@ -53,14 +54,14 @@ export default defineComponent({
|
||||
});
|
||||
// 获取父级菜单数据
|
||||
const menuLists = computed(() => {
|
||||
return props.menuList;
|
||||
return <any>props.menuList;
|
||||
});
|
||||
// 获取布局配置信息
|
||||
const getThemeConfig = computed(() => {
|
||||
return store.state.themeConfig.themeConfig;
|
||||
});
|
||||
// 菜单高亮(详情时,父级高亮)
|
||||
const setParentHighlight = (currentRoute) => {
|
||||
const setParentHighlight = (currentRoute: any) => {
|
||||
const { path, meta } = currentRoute;
|
||||
const pathSplit = meta.isDynamic ? meta.isDynamicPath.split('/') : path.split('/');
|
||||
if (pathSplit.length >= 4 && meta.isHide) return pathSplit.splice(0, 3).join('/');
|
||||
@ -84,7 +85,6 @@ export default defineComponent({
|
||||
onBeforeRouteUpdate((to) => {
|
||||
// 修复:https://gitee.com/lyt-top/vue-next-admin/issues/I3YX6G
|
||||
state.defaultActive = setParentHighlight(to);
|
||||
proxy.mittBus.emit('onMenuClick');
|
||||
const clientWidth = document.body.clientWidth;
|
||||
if (clientWidth < 1000) getThemeConfig.value.isCollapse = false;
|
||||
});
|
||||
|
||||
@ -19,7 +19,7 @@ export default defineComponent({
|
||||
});
|
||||
// 初始化页面加载 loading
|
||||
const initIframeLoad = () => {
|
||||
state.iframeUrl = route.meta.isLink;
|
||||
state.iframeUrl = <any>route.meta.isLink;
|
||||
nextTick(() => {
|
||||
state.iframeLoading = true;
|
||||
const iframe = document.getElementById('iframe');
|
||||
|
||||
@ -1,22 +1,38 @@
|
||||
<template>
|
||||
<div class="layout-view-bg-white flex layout-view-link" :style="{ height: `calc(100vh - ${setLinkHeight}` }">
|
||||
<a :href="currentRouteMeta.isLink" target="_blank" rel="opener" class="flex-margin"
|
||||
>{{ currentRouteMeta.title }}:{{ currentRouteMeta.isLink }}</a
|
||||
>
|
||||
<a :href="currentRouteMeta.isLink" target="_blank" rel="opener" class="flex-margin">
|
||||
{{ currentRouteMeta.title }}:{{ currentRouteMeta.isLink }}
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, toRefs, reactive, computed, watch } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useRoute, RouteMeta } from 'vue-router';
|
||||
import { useStore } from '/@/store/index';
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface LinkViewState {
|
||||
currentRouteMeta: {
|
||||
isLink: string;
|
||||
title: string;
|
||||
};
|
||||
}
|
||||
interface LinkViewRouteMeta extends RouteMeta {
|
||||
isLink: string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'layoutLinkView',
|
||||
setup() {
|
||||
const route = useRoute();
|
||||
const store = useStore();
|
||||
const state = reactive({
|
||||
currentRouteMeta: {},
|
||||
const state = reactive<LinkViewState>({
|
||||
currentRouteMeta: {
|
||||
isLink: '',
|
||||
title: '',
|
||||
},
|
||||
});
|
||||
// 设置 link 的高度
|
||||
const setLinkHeight = computed(() => {
|
||||
@ -28,7 +44,7 @@ export default defineComponent({
|
||||
watch(
|
||||
() => route.path,
|
||||
() => {
|
||||
state.currentRouteMeta = route.meta;
|
||||
state.currentRouteMeta = <LinkViewRouteMeta>route.meta;
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
|
||||
@ -2,8 +2,8 @@
|
||||
<div class="h100">
|
||||
<router-view v-slot="{ Component }">
|
||||
<transition :name="setTransitionName" mode="out-in">
|
||||
<keep-alive :include="keepAliveNameList">
|
||||
<component :is="Component" :key="refreshRouterViewKey" class="w100" />
|
||||
<keep-alive :include="keepAliveNameList"
|
||||
><component :is="Component" :key="refreshRouterViewKey" class="w100" :style="{ minHeight }" />
|
||||
</keep-alive>
|
||||
</transition>
|
||||
</router-view>
|
||||
@ -14,16 +14,28 @@
|
||||
import { computed, defineComponent, toRefs, reactive, getCurrentInstance, onBeforeMount, onUnmounted, nextTick, watch } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useStore } from '/@/store/index';
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface ParentViewState {
|
||||
refreshRouterViewKey: null | string;
|
||||
keepAliveNameList: string[];
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'layoutParentView',
|
||||
props: {
|
||||
minHeight: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const { proxy } = <any>getCurrentInstance();
|
||||
const route = useRoute();
|
||||
const store = useStore();
|
||||
const state: any = reactive({
|
||||
const state = reactive<ParentViewState>({
|
||||
refreshRouterViewKey: null,
|
||||
keepAliveNameList: [],
|
||||
keepAliveNameNewList: [],
|
||||
});
|
||||
// 设置主界面切换动画
|
||||
const setTransitionName = computed(() => {
|
||||
|
||||
@ -6,7 +6,6 @@ import { directive } from '/@/utils/directive';
|
||||
import other from '/@/utils/other';
|
||||
|
||||
import ElementPlus from 'element-plus';
|
||||
import zhCn from 'element-plus/es/locale/lang/zh-cn';
|
||||
import 'element-plus/dist/index.css';
|
||||
import '/@/theme/index.scss';
|
||||
import mitt from 'mitt';
|
||||
@ -16,6 +15,6 @@ const app = createApp(App);
|
||||
directive(app);
|
||||
other.elSvg(app);
|
||||
|
||||
app.use(router).use(store, key).use(ElementPlus, { size: other.globalComponentSize, locale: zhCn }).mount('#app');
|
||||
app.use(router).use(store, key).use(ElementPlus).mount('#app');
|
||||
|
||||
app.config.globalProperties.mittBus = mitt();
|
||||
|
||||
@ -3,7 +3,9 @@ import { Session } from '/@/utils/storage';
|
||||
import { NextLoading } from '/@/utils/loading';
|
||||
import { setAddRoute, setFilterMenuAndCacheTagsViewRoutes } from '/@/router/index';
|
||||
import { dynamicRoutes } from '/@/router/route';
|
||||
import { getMenuAdmin, getMenuTest } from '/@/api/menu/index';
|
||||
import { useMenuApi } from '/@/api/menu/index';
|
||||
|
||||
const menuApi = useMenuApi();
|
||||
|
||||
const layouModules: any = import.meta.glob('../layout/routerView/*.{vue,tsx}');
|
||||
const viewsModules: any = import.meta.glob('../views/**/*.{vue,tsx}');
|
||||
@ -50,9 +52,9 @@ export function getBackEndControlRoutes() {
|
||||
// 模拟 admin 与 test
|
||||
const auth = store.state.userInfos.userInfos.roles[0];
|
||||
// 管理员 admin
|
||||
if (auth === 'admin') return getMenuAdmin();
|
||||
if (auth === 'admin') return menuApi.getMenuAdmin();
|
||||
// 其它用户 test
|
||||
else return getMenuTest();
|
||||
else return menuApi.getMenuTest();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -163,8 +163,8 @@ export function setFilterRouteEnd() {
|
||||
* @description 此处循环为 dynamicRoutes(/@/router/route)第一个顶级 children 的路由一维数组,非多级嵌套
|
||||
* @link 参考:https://next.router.vuejs.org/zh/api/#addroute
|
||||
*/
|
||||
export function setAddRoute() {
|
||||
setFilterRouteEnd().forEach((route: RouteRecordRaw) => {
|
||||
export async function setAddRoute() {
|
||||
await setFilterRouteEnd().forEach((route: RouteRecordRaw) => {
|
||||
const routeName: any = route.name;
|
||||
if (!router.hasRoute(routeName)) router.addRoute(route);
|
||||
});
|
||||
@ -176,8 +176,8 @@ export function setAddRoute() {
|
||||
* @description 此处循环为 dynamicRoutes(/@/router/route)第一个顶级 children 的路由一维数组,非多级嵌套
|
||||
* @link 参考:https://next.router.vuejs.org/zh/api/#push
|
||||
*/
|
||||
export function resetRoute() {
|
||||
setFilterRouteEnd().forEach((route: RouteRecordRaw) => {
|
||||
export async function resetRoute() {
|
||||
await setFilterRouteEnd().forEach((route: RouteRecordRaw) => {
|
||||
const routeName: any = route.name;
|
||||
router.hasRoute(routeName) && router.removeRoute(routeName);
|
||||
});
|
||||
|
||||
@ -88,7 +88,7 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
|
||||
isAffix: false,
|
||||
isIframe: false,
|
||||
roles: ['admin'],
|
||||
icon: 'elementColdDrink',
|
||||
icon: 'ele-ColdDrink',
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -118,7 +118,7 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
|
||||
isAffix: false,
|
||||
isIframe: false,
|
||||
roles: ['admin'],
|
||||
icon: 'elementOfficeBuilding',
|
||||
icon: 'ele-OfficeBuilding',
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -133,7 +133,7 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
|
||||
isAffix: false,
|
||||
isIframe: false,
|
||||
roles: ['admin'],
|
||||
icon: 'elementSetUp',
|
||||
icon: 'ele-SetUp',
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@ -5,20 +5,15 @@ export interface ThemeConfigState {
|
||||
themeConfig: {
|
||||
isDrawer: boolean;
|
||||
primary: string;
|
||||
success: string;
|
||||
info: string;
|
||||
warning: string;
|
||||
danger: string;
|
||||
topBar: string;
|
||||
menuBar: string;
|
||||
columnsMenuBar: string;
|
||||
topBarColor: string;
|
||||
menuBarColor: string;
|
||||
columnsMenuBarColor: string;
|
||||
isTopBarColorGradual: boolean;
|
||||
menuBar: string;
|
||||
menuBarColor: string;
|
||||
isMenuBarColorGradual: boolean;
|
||||
columnsMenuBar: string;
|
||||
columnsMenuBarColor: string;
|
||||
isColumnsMenuBarColorGradual: boolean;
|
||||
isMenuBarColorHighlight: boolean;
|
||||
isCollapse: boolean;
|
||||
isUniqueOpened: boolean;
|
||||
isFixedHeader: boolean;
|
||||
@ -55,30 +50,36 @@ export interface ThemeConfigState {
|
||||
|
||||
// 路由列表
|
||||
export interface RoutesListState {
|
||||
routesList: Array<object>;
|
||||
routesList: object[];
|
||||
isColumnsMenuHover: Boolean;
|
||||
isColumnsNavHover: Boolean;
|
||||
}
|
||||
|
||||
// 路由缓存列表
|
||||
export interface KeepAliveNamesState {
|
||||
keepAliveNames: Array<string>;
|
||||
keepAliveNames: string[];
|
||||
}
|
||||
|
||||
// TagsView 路由列表
|
||||
export interface TagsViewRoutesState {
|
||||
tagsViewRoutes: Array<object>;
|
||||
tagsViewRoutes: object[];
|
||||
isTagsViewCurrenFull: Boolean;
|
||||
}
|
||||
|
||||
// 用户信息
|
||||
export interface UserInfosState {
|
||||
userInfos: object;
|
||||
userInfos: {
|
||||
authBtnList: string[];
|
||||
photo: string;
|
||||
roles: string[];
|
||||
time: number;
|
||||
userName: string;
|
||||
};
|
||||
}
|
||||
|
||||
// 后端返回原始路由(未处理时)
|
||||
export interface RequestOldRoutesState {
|
||||
requestOldRoutes: Array<object>;
|
||||
requestOldRoutes: object[];
|
||||
}
|
||||
|
||||
// 主接口(顶级类型声明)
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { Module } from 'vuex';
|
||||
// 此处加上 `.ts` 后缀报错,具体原因不详
|
||||
import { KeepAliveNamesState, RootStateTypes } from '/@/store/interface/index';
|
||||
|
||||
const keepAliveNamesModule: Module<KeepAliveNamesState, RootStateTypes> = {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { Module } from 'vuex';
|
||||
// 此处加上 `.ts` 后缀报错,具体原因不详
|
||||
import { RequestOldRoutesState, RootStateTypes } from '/@/store/interface/index';
|
||||
|
||||
const requestOldRoutesModule: Module<RequestOldRoutesState, RootStateTypes> = {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { Module } from 'vuex';
|
||||
// 此处加上 `.ts` 后缀报错,具体原因不详
|
||||
import { RoutesListState, RootStateTypes } from '/@/store/interface/index';
|
||||
|
||||
const routesListModule: Module<RoutesListState, RootStateTypes> = {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { Module } from 'vuex';
|
||||
// 此处加上 `.ts` 后缀报错,具体原因不详
|
||||
import { TagsViewRoutesState, RootStateTypes } from '/@/store/interface/index';
|
||||
import { Session } from '/@/utils/storage';
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { Module } from 'vuex';
|
||||
// 此处加上 `.ts` 后缀报错,具体原因不详
|
||||
import { ThemeConfigState, RootStateTypes } from '/@/store/interface/index';
|
||||
|
||||
/**
|
||||
@ -17,16 +16,8 @@ const themeConfigModule: Module<ThemeConfigState, RootStateTypes> = {
|
||||
/**
|
||||
* 全局主题
|
||||
*/
|
||||
// 默认 primary 颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
|
||||
// 默认 primary 主题颜色
|
||||
primary: '#409eff',
|
||||
// 默认 success 颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
|
||||
success: '#67c23a',
|
||||
// 默认 info 颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
|
||||
info: '#909399',
|
||||
// 默认 warning 颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
|
||||
warning: '#e6a23c',
|
||||
// 默认 danger 颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
|
||||
danger: '#f56c6c',
|
||||
|
||||
/**
|
||||
* 菜单 / 顶栏
|
||||
@ -34,26 +25,24 @@ const themeConfigModule: Module<ThemeConfigState, RootStateTypes> = {
|
||||
* 切换布局需手动设置样式,设置的样式自动同步各布局,
|
||||
* 代码位置:/@/layout/navBars/breadcrumb/setings.vue
|
||||
*/
|
||||
// 默认顶栏导航背景颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
|
||||
// 默认顶栏导航背景颜色
|
||||
topBar: '#ffffff',
|
||||
// 默认菜单导航背景颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
|
||||
menuBar: '#545c64',
|
||||
// 默认分栏菜单背景颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
|
||||
columnsMenuBar: '#545c64',
|
||||
// 默认顶栏导航字体颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
|
||||
// 默认顶栏导航字体颜色
|
||||
topBarColor: '#606266',
|
||||
// 默认菜单导航字体颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
|
||||
menuBarColor: '#eaeaea',
|
||||
// 默认分栏菜单字体颜色,请注意:需要同时修改 `/@/theme/common/var.scss` 对应的值
|
||||
columnsMenuBarColor: '#e6e6e6',
|
||||
// 是否开启顶栏背景颜色渐变
|
||||
isTopBarColorGradual: false,
|
||||
// 默认菜单导航背景颜色
|
||||
menuBar: '#545c64',
|
||||
// 默认菜单导航字体颜色
|
||||
menuBarColor: '#eaeaea',
|
||||
// 是否开启菜单背景颜色渐变
|
||||
isMenuBarColorGradual: false,
|
||||
// 默认分栏菜单背景颜色
|
||||
columnsMenuBar: '#545c64',
|
||||
// 默认分栏菜单字体颜色
|
||||
columnsMenuBarColor: '#e6e6e6',
|
||||
// 是否开启分栏菜单背景颜色渐变
|
||||
isColumnsMenuBarColorGradual: false,
|
||||
// 是否开启菜单字体背景高亮
|
||||
isMenuBarColorHighlight: false,
|
||||
|
||||
/**
|
||||
* 界面设置
|
||||
@ -110,9 +99,9 @@ const themeConfigModule: Module<ThemeConfigState, RootStateTypes> = {
|
||||
/**
|
||||
* 其它设置
|
||||
*/
|
||||
// Tagsview 风格:可选值"<tags-style-one|tags-style-two|tags-style-three|tags-style-four>",默认 tags-style-one
|
||||
// Tagsview 风格:可选值"<tags-style-one|tags-style-four|tags-style-five>",默认 tags-style-five
|
||||
// 定义的值与 `/src/layout/navBars/tagsView/tagsView.vue` 中的 class 同名
|
||||
tagsStyle: 'tags-style-one',
|
||||
tagsStyle: 'tags-style-five',
|
||||
// 主页面切换动画:可选值"<slide-right|slide-left|opacitys>",默认 slide-right
|
||||
animation: 'slide-right',
|
||||
// 分栏高亮风格:可选值"<columns-round|columns-card>",默认 columns-round
|
||||
@ -140,9 +129,9 @@ const themeConfigModule: Module<ThemeConfigState, RootStateTypes> = {
|
||||
// 网站主标题(菜单导航、浏览器当前网页标题)
|
||||
globalTitle: 'vue-next-admin',
|
||||
// 网站副标题(登录页顶部文字)
|
||||
globalViceTitle: 'SMALL@小柒',
|
||||
// 默认全局组件大小,可选值"<|medium|small|mini>",默认 ''
|
||||
globalComponentSize: '',
|
||||
globalViceTitle: 'vueNextAdmin',
|
||||
// 默认全局组件大小,可选值"<large|'default'|small>",默认 'large'
|
||||
globalComponentSize: 'large',
|
||||
},
|
||||
},
|
||||
mutations: {
|
||||
|
||||
@ -1,22 +1,27 @@
|
||||
import { Module } from 'vuex';
|
||||
import { Session } from '/@/utils/storage';
|
||||
// 此处加上 `.ts` 后缀报错,具体原因不详
|
||||
import { UserInfosState, RootStateTypes } from '/@/store/interface/index';
|
||||
|
||||
const userInfosModule: Module<UserInfosState, RootStateTypes> = {
|
||||
namespaced: true,
|
||||
state: {
|
||||
userInfos: {},
|
||||
userInfos: {
|
||||
authBtnList: [],
|
||||
photo: '',
|
||||
roles: [],
|
||||
time: 0,
|
||||
userName: '',
|
||||
},
|
||||
},
|
||||
mutations: {
|
||||
// 设置用户信息
|
||||
getUserInfos(state: any, data: object) {
|
||||
getUserInfos(state, data: any) {
|
||||
state.userInfos = data;
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
// 设置用户信息
|
||||
async setUserInfos({ commit }, data: object) {
|
||||
async setUserInfos({ commit }, data: UserInfosState) {
|
||||
if (data) {
|
||||
commit('getUserInfos', data);
|
||||
} else {
|
||||
|
||||
@ -7,6 +7,19 @@
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
:root {
|
||||
--next-bg-main-color: #f8f8f8;
|
||||
--next-bg-color: #f5f5ff;
|
||||
--next-border-color-light: #f1f2f3;
|
||||
--next-color-primary-lighter: #ecf5ff;
|
||||
--next-color-dark-hover: #0000001a;
|
||||
--next-color-menu-hover: rgba(0, 0, 0, 0.1);
|
||||
--next-color-user-hover: rgba(0, 0, 0, 0.04);
|
||||
--next-color-seting-main: #e9eef3;
|
||||
--next-color-seting-aside: #d3dce6;
|
||||
--next-color-seting-header: #b3c0d1;
|
||||
}
|
||||
|
||||
html,
|
||||
body,
|
||||
#app {
|
||||
@ -18,7 +31,7 @@ body,
|
||||
font-weight: 400;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
background-color: #f8f8f8;
|
||||
background-color: var(--next-bg-main-color);
|
||||
font-size: 14px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
@ -30,7 +43,7 @@ body,
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.layout-aside {
|
||||
background: var(--bg-menuBar);
|
||||
background: var(--next-bg-menuBar);
|
||||
box-shadow: 2px 0 6px rgb(0 21 41 / 1%);
|
||||
height: inherit;
|
||||
position: relative;
|
||||
@ -49,7 +62,7 @@ body,
|
||||
padding: 0 !important;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
background-color: #f8f8f8;
|
||||
background-color: var(--next-bg-main-color);
|
||||
}
|
||||
.el-scrollbar {
|
||||
width: 100%;
|
||||
@ -63,7 +76,7 @@ body,
|
||||
border: 1px solid var(--el-border-color-light, #ebeef5);
|
||||
}
|
||||
.layout-el-aside-br-color {
|
||||
border-right: 1px solid rgb(238, 238, 238);
|
||||
border-right: 1px solid var(--el-border-color-light, #ebeef5);
|
||||
}
|
||||
// pc端左侧导航样式
|
||||
.layout-aside-pc-220 {
|
||||
@ -88,11 +101,11 @@ body,
|
||||
}
|
||||
.layout-aside-mobile-close {
|
||||
left: -220px;
|
||||
transition: all 0.3s cubic-bezier(1, -0.04, 0, 1.32);
|
||||
transition: all 0.3s cubic-bezier(0.39, 0.58, 0.57, 1);
|
||||
}
|
||||
.layout-aside-mobile-open {
|
||||
left: 0;
|
||||
transition: all 0.3s cubic-bezier(0.53, -0.26, 0.42, 1.18);
|
||||
transition: all 0.3s cubic-bezier(0.22, 0.61, 0.36, 1);
|
||||
}
|
||||
.layout-aside-mobile-mode {
|
||||
position: fixed;
|
||||
@ -103,6 +116,7 @@ body,
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
z-index: 9999998;
|
||||
animation: error-img 0.3s;
|
||||
}
|
||||
.layout-scrollbar {
|
||||
@extend .el-scrollbar;
|
||||
@ -133,7 +147,7 @@ body,
|
||||
------------------------------- */
|
||||
#nprogress {
|
||||
.bar {
|
||||
background: var(--color-primary) !important;
|
||||
background: var(--el-color-primary) !important;
|
||||
z-index: 9999999 !important;
|
||||
}
|
||||
}
|
||||
@ -145,6 +159,7 @@ body,
|
||||
}
|
||||
.flex-auto {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
.flex-center {
|
||||
@extend .flex;
|
||||
@ -209,19 +224,19 @@ body,
|
||||
/* 颜色值
|
||||
------------------------------- */
|
||||
.color-primary {
|
||||
color: var(--color-primary);
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
.color-success {
|
||||
color: var(--color-success);
|
||||
color: var(--el-color-success);
|
||||
}
|
||||
.color-warning {
|
||||
color: var(--color-warning);
|
||||
color: var(--el-color-warning);
|
||||
}
|
||||
.color-danger {
|
||||
color: var(--color-danger);
|
||||
color: var(--el-color-danger);
|
||||
}
|
||||
.color-info {
|
||||
color: var(--color-info);
|
||||
color: var(--el-color-info);
|
||||
}
|
||||
|
||||
/* 字体大小全局样式
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
@import 'common/transition.scss';
|
||||
@import 'common/var.scss';
|
||||
@ -38,7 +38,7 @@
|
||||
------------------------------- */
|
||||
.breadcrumb-enter-active,
|
||||
.breadcrumb-leave-active {
|
||||
transition: all 0.3s;
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
.breadcrumb-enter-from,
|
||||
.breadcrumb-leave-active {
|
||||
@ -47,6 +47,7 @@
|
||||
}
|
||||
.breadcrumb-leave-active {
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
/* logo 过渡动画
|
||||
@ -83,3 +84,11 @@
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes error-img-two {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,127 +0,0 @@
|
||||
/**
|
||||
* scss 怎么动态创建变量
|
||||
* 本来想用 @function,@for 好像不可以动态创建
|
||||
* 2020.12.19 lyt 记录
|
||||
**/
|
||||
|
||||
/* 定义初始颜色
|
||||
------------------------------- */
|
||||
$--color-primary: #409eff !default;
|
||||
$--color-whites: #ffffff !default;
|
||||
$--color-primary-light-1: mix($--color-whites, $--color-primary, 10%) !default;
|
||||
$--color-primary-light-2: mix($--color-whites, $--color-primary, 20%) !default;
|
||||
$--color-primary-light-3: mix($--color-whites, $--color-primary, 30%) !default;
|
||||
$--color-primary-light-4: mix($--color-whites, $--color-primary, 40%) !default;
|
||||
$--color-primary-light-5: mix($--color-whites, $--color-primary, 50%) !default;
|
||||
$--color-primary-light-6: mix($--color-whites, $--color-primary, 60%) !default;
|
||||
$--color-primary-light-7: mix($--color-whites, $--color-primary, 70%) !default;
|
||||
$--color-primary-light-8: mix($--color-whites, $--color-primary, 80%) !default;
|
||||
$--color-primary-light-9: mix($--color-whites, $--color-primary, 90%) !default;
|
||||
$--color-success: #67c23a !default;
|
||||
$--color-success-light-1: mix($--color-whites, $--color-success, 10%) !default;
|
||||
$--color-success-light-2: mix($--color-whites, $--color-success, 20%) !default;
|
||||
$--color-success-light-3: mix($--color-whites, $--color-success, 30%) !default;
|
||||
$--color-success-light-4: mix($--color-whites, $--color-success, 40%) !default;
|
||||
$--color-success-light-5: mix($--color-whites, $--color-success, 50%) !default;
|
||||
$--color-success-light-6: mix($--color-whites, $--color-success, 60%) !default;
|
||||
$--color-success-light-7: mix($--color-whites, $--color-success, 70%) !default;
|
||||
$--color-success-light-8: mix($--color-whites, $--color-success, 80%) !default;
|
||||
$--color-success-light-9: mix($--color-whites, $--color-success, 90%) !default;
|
||||
$--color-info: #909399 !default;
|
||||
$--color-info-light-1: mix($--color-whites, $--color-info, 10%) !default;
|
||||
$--color-info-light-2: mix($--color-whites, $--color-info, 20%) !default;
|
||||
$--color-info-light-3: mix($--color-whites, $--color-info, 30%) !default;
|
||||
$--color-info-light-4: mix($--color-whites, $--color-info, 40%) !default;
|
||||
$--color-info-light-5: mix($--color-whites, $--color-info, 50%) !default;
|
||||
$--color-info-light-6: mix($--color-whites, $--color-info, 60%) !default;
|
||||
$--color-info-light-7: mix($--color-whites, $--color-info, 70%) !default;
|
||||
$--color-info-light-8: mix($--color-whites, $--color-info, 80%) !default;
|
||||
$--color-info-light-9: mix($--color-whites, $--color-info, 90%) !default;
|
||||
$--color-warning: #e6a23c !default;
|
||||
$--color-warning-light-1: mix($--color-whites, $--color-warning, 10%) !default;
|
||||
$--color-warning-light-2: mix($--color-whites, $--color-warning, 20%) !default;
|
||||
$--color-warning-light-3: mix($--color-whites, $--color-warning, 30%) !default;
|
||||
$--color-warning-light-4: mix($--color-whites, $--color-warning, 40%) !default;
|
||||
$--color-warning-light-5: mix($--color-whites, $--color-warning, 50%) !default;
|
||||
$--color-warning-light-6: mix($--color-whites, $--color-warning, 60%) !default;
|
||||
$--color-warning-light-7: mix($--color-whites, $--color-warning, 70%) !default;
|
||||
$--color-warning-light-8: mix($--color-whites, $--color-warning, 80%) !default;
|
||||
$--color-warning-light-9: mix($--color-whites, $--color-warning, 90%) !default;
|
||||
$--color-danger: #f56c6c !default;
|
||||
$--color-danger-light-1: mix($--color-whites, $--color-danger, 10%) !default;
|
||||
$--color-danger-light-2: mix($--color-whites, $--color-danger, 20%) !default;
|
||||
$--color-danger-light-3: mix($--color-whites, $--color-danger, 30%) !default;
|
||||
$--color-danger-light-4: mix($--color-whites, $--color-danger, 40%) !default;
|
||||
$--color-danger-light-5: mix($--color-whites, $--color-danger, 50%) !default;
|
||||
$--color-danger-light-6: mix($--color-whites, $--color-danger, 60%) !default;
|
||||
$--color-danger-light-7: mix($--color-whites, $--color-danger, 70%) !default;
|
||||
$--color-danger-light-8: mix($--color-whites, $--color-danger, 80%) !default;
|
||||
$--color-danger-light-9: mix($--color-whites, $--color-danger, 90%) !default;
|
||||
$--bg-topBar: #ffffff;
|
||||
$--bg-menuBar: #545c64;
|
||||
$--bg-columnsMenuBar: #545c64;
|
||||
$--bg-topBarColor: #606266;
|
||||
$--bg-menuBarColor: #eaeaea;
|
||||
$--bg-columnsMenuBarColor: #e6e6e6;
|
||||
|
||||
/* 赋值给:root
|
||||
------------------------------- */
|
||||
:root {
|
||||
--color-primary: #{$--color-primary};
|
||||
--color-whites: #{$--color-whites};
|
||||
--color-primary-light-1: #{$--color-primary-light-1};
|
||||
--color-primary-light-2: #{$--color-primary-light-2};
|
||||
--color-primary-light-3: #{$--color-primary-light-3};
|
||||
--color-primary-light-4: #{$--color-primary-light-4};
|
||||
--color-primary-light-5: #{$--color-primary-light-5};
|
||||
--color-primary-light-6: #{$--color-primary-light-6};
|
||||
--color-primary-light-7: #{$--color-primary-light-7};
|
||||
--color-primary-light-8: #{$--color-primary-light-8};
|
||||
--color-primary-light-9: #{$--color-primary-light-9};
|
||||
--color-success: #{$--color-success};
|
||||
--color-success-light-1: #{$--color-success-light-1};
|
||||
--color-success-light-2: #{$--color-success-light-2};
|
||||
--color-success-light-3: #{$--color-success-light-3};
|
||||
--color-success-light-4: #{$--color-success-light-4};
|
||||
--color-success-light-5: #{$--color-success-light-5};
|
||||
--color-success-light-6: #{$--color-success-light-6};
|
||||
--color-success-light-7: #{$--color-success-light-7};
|
||||
--color-success-light-8: #{$--color-success-light-8};
|
||||
--color-success-light-9: #{$--color-success-light-9};
|
||||
--color-info: #{$--color-info};
|
||||
--color-info-light-1: #{$--color-info-light-1};
|
||||
--color-info-light-2: #{$--color-info-light-2};
|
||||
--color-info-light-3: #{$--color-info-light-3};
|
||||
--color-info-light-4: #{$--color-info-light-4};
|
||||
--color-info-light-5: #{$--color-info-light-5};
|
||||
--color-info-light-6: #{$--color-info-light-6};
|
||||
--color-info-light-7: #{$--color-info-light-7};
|
||||
--color-info-light-8: #{$--color-info-light-8};
|
||||
--color-info-light-9: #{$--color-info-light-9};
|
||||
--color-warning: #{$--color-warning};
|
||||
--color-warning-light-1: #{$--color-warning-light-1};
|
||||
--color-warning-light-2: #{$--color-warning-light-2};
|
||||
--color-warning-light-3: #{$--color-warning-light-3};
|
||||
--color-warning-light-4: #{$--color-warning-light-4};
|
||||
--color-warning-light-5: #{$--color-warning-light-5};
|
||||
--color-warning-light-6: #{$--color-warning-light-6};
|
||||
--color-warning-light-7: #{$--color-warning-light-7};
|
||||
--color-warning-light-8: #{$--color-warning-light-8};
|
||||
--color-warning-light-9: #{$--color-warning-light-9};
|
||||
--color-danger: #{$--color-danger};
|
||||
--color-danger-light-1: #{$--color-danger-light-1};
|
||||
--color-danger-light-2: #{$--color-danger-light-2};
|
||||
--color-danger-light-3: #{$--color-danger-light-3};
|
||||
--color-danger-light-4: #{$--color-danger-light-4};
|
||||
--color-danger-light-5: #{$--color-danger-light-5};
|
||||
--color-danger-light-6: #{$--color-danger-light-6};
|
||||
--color-danger-light-7: #{$--color-danger-light-7};
|
||||
--color-danger-light-8: #{$--color-danger-light-8};
|
||||
--color-danger-light-9: #{$--color-danger-light-9};
|
||||
--bg-topBar: #{$--bg-topBar};
|
||||
--bg-menuBar: #{$--bg-menuBar};
|
||||
--bg-columnsMenuBar: #{$--bg-columnsMenuBar};
|
||||
--bg-topBarColor: #{$--bg-topBarColor};
|
||||
--bg-menuBarColor: #{$--bg-menuBarColor};
|
||||
--bg-columnsMenuBarColor: #{$--bg-columnsMenuBarColor};
|
||||
}
|
||||
@ -1,57 +1,219 @@
|
||||
/* 深色模式样式
|
||||
------------------------------- */
|
||||
[data-theme='dark'] {
|
||||
// 全局
|
||||
filter: invert(0.9) hue-rotate(180deg);
|
||||
img,
|
||||
.layout-lock-screen-img,
|
||||
.visualizing-demo2,
|
||||
.w-e-panel-tab-content {
|
||||
filter: invert(1) hue-rotate(180deg);
|
||||
}
|
||||
.error img {
|
||||
filter: unset;
|
||||
}
|
||||
// 变量(自定义时,只需修改这里的值)
|
||||
--next-bg-main: #1f1f1f;
|
||||
--next-color-white: #ffffff;
|
||||
--next-color-disabled: #191919;
|
||||
--next-color-bar: #dadada;
|
||||
--next-color-primary: #303030;
|
||||
--next-border-color: #424242;
|
||||
--next-border-black: #333333;
|
||||
--next-border-columns: #2a2a2a;
|
||||
--next-color-seting: #505050;
|
||||
--next-text-color-regular: #9b9da1;
|
||||
--next-text-color-placeholder: #7a7a7a;
|
||||
--next-color-hover: #3c3c3c;
|
||||
--next-color-hover-rgba: rgba(0, 0, 0, 0.3);
|
||||
|
||||
// root
|
||||
--next-bg-main-color: var(--next-bg-main) !important;
|
||||
--next-bg-topBar: var(--next-color-disabled) !important;
|
||||
--next-bg-topBarColor: var(--next-color-bar) !important;
|
||||
--next-bg-menuBar: var(--next-color-disabled) !important;
|
||||
--next-bg-menuBarColor: var(--next-color-bar) !important;
|
||||
--next-bg-columnsMenuBar: var(--next-color-disabled) !important;
|
||||
--next-bg-columnsMenuBarColor: var(--next-color-bar) !important;
|
||||
--next-border-color-light: var(--next-border-black) !important;
|
||||
--next-color-primary-lighter: var(--next-color-primary) !important;
|
||||
--next-bg-color: var(--next-color-primary) !important;
|
||||
--next-color-dark-hover: var(--next-color-hover) !important;
|
||||
--next-color-menu-hover: var(--next-color-hover-rgba) !important;
|
||||
--next-color-user-hover: var(--next-color-hover-rgba) !important;
|
||||
--next-color-seting-main: var(--next-color-seting) !important;
|
||||
--next-color-seting-aside: var(--next-color-hover) !important;
|
||||
--next-color-seting-header: var(--next-color-primary) !important;
|
||||
|
||||
// element plus
|
||||
.el-radio-button__original-radio:checked + .el-radio-button__inner,
|
||||
.el-image-viewer__close,
|
||||
.el-image-viewer__actions__inner,
|
||||
.el-image-viewer__next,
|
||||
.el-image-viewer__prev {
|
||||
color: #000000 !important;
|
||||
}
|
||||
.el-overlay {
|
||||
background-color: rgba(0, 0, 0, 0.05) !important;
|
||||
}
|
||||
.el-drawer {
|
||||
box-shadow: 0 8px 10px -5px rgb(0 0 0 / 1%), 0 16px 24px 2px rgb(0 0 0 / 2%), 0 6px 30px 5px rgb(0 0 0 / 1%);
|
||||
}
|
||||
--el-color-white: var(--next-color-disabled) !important;
|
||||
--el-text-color-primary: var(--next-color-bar) !important;
|
||||
--el-border-color-base: var(--next-border-black) !important;
|
||||
--el-border-color-light: var(--next-border-black) !important;
|
||||
--el-text-color-regular: var(--next-text-color-regular) !important;
|
||||
--el-bg-color: var(--next-color-hover-rgba) !important;
|
||||
--el-color-success-lighter: var(--next-color-primary) !important;
|
||||
--el-color-warning-lighter: var(--next-color-primary) !important;
|
||||
--el-color-danger-lighter: var(--next-color-primary) !important;
|
||||
--el-color-primary-lighter: var(--next-color-primary) !important;
|
||||
--el-color-primary-light-9: var(--next-color-hover) !important;
|
||||
--el-text-color-disabled-base: var(--el-color-primary) !important;
|
||||
--el-border-color-lighter: var(--next-border-black) !important;
|
||||
--el-text-color-placeholder: var(--next-text-color-placeholder) !important;
|
||||
--el-disabled-bg-color: var(--next-color-disabled) !important;
|
||||
--el-fill-base: var(--next-color-white) !important;
|
||||
|
||||
// 数据可视化演示
|
||||
.visualizing-container-head {
|
||||
background: linear-gradient(to bottom, rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0.02)) !important;
|
||||
.visualizing-container-head-left-text-box {
|
||||
color: #000000 !important;
|
||||
// button
|
||||
.el-button {
|
||||
&:hover {
|
||||
border-color: var(--next-border-color) !important;
|
||||
}
|
||||
}
|
||||
.visualizing-container-content-left {
|
||||
background: linear-gradient(to right, rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.01)) !important;
|
||||
}
|
||||
.visualizing-container-content-center {
|
||||
background: linear-gradient(to top, rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.01)) !important;
|
||||
}
|
||||
.visualizing-container-content-right {
|
||||
background: linear-gradient(to left, rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.01)) !important;
|
||||
}
|
||||
.cropper-modal {
|
||||
background-color: #ffffff;
|
||||
.el-button--primary,
|
||||
.el-button--info,
|
||||
.el-button--danger,
|
||||
.el-button--success,
|
||||
.el-button--warning {
|
||||
--el-button-text-color: var(--next-color-white) !important;
|
||||
--el-button-hover-text-color: var(--next-color-white) !important;
|
||||
--el-button-disabled-text-color: var(--next-color-white) !important;
|
||||
&:hover {
|
||||
border-color: var(--el-button-hover-border-color, var(--el-button-hover-bg-color)) !important;
|
||||
}
|
||||
}
|
||||
|
||||
// 其它菜单等
|
||||
--bg-menuBar: #ffffff !important;
|
||||
--bg-menuBarColor: #303133 !important;
|
||||
--bg-columnsMenuBar: #ffffff !important;
|
||||
--bg-columnsMenuBarColor: #303133 !important;
|
||||
--color-whites: #000000 !important;
|
||||
// drawer
|
||||
.el-divider__text {
|
||||
background-color: var(--el-color-white) !important;
|
||||
}
|
||||
.el-drawer {
|
||||
border-left: 1px solid var(--next-border-color-light) !important;
|
||||
}
|
||||
|
||||
// tabs
|
||||
.el-tabs--border-card {
|
||||
background-color: var(--el-color-white) !important;
|
||||
}
|
||||
.el-tabs--border-card > .el-tabs__header .el-tabs__item.is-active {
|
||||
background: var(--next-color-primary-lighter);
|
||||
}
|
||||
|
||||
// alert / notice-bar
|
||||
.home-card-item {
|
||||
border: 1px solid var(--next-border-color-light) !important;
|
||||
}
|
||||
.el-alert,
|
||||
.notice-bar {
|
||||
border: 1px solid var(--next-border-color) !important;
|
||||
background-color: var(--next-color-disabled) !important;
|
||||
}
|
||||
|
||||
// menu
|
||||
.layout-aside {
|
||||
border-right: 1px solid var(--next-border-color-light) !important;
|
||||
}
|
||||
|
||||
// colorPicker
|
||||
.el-color-picker__mask {
|
||||
background: unset !important;
|
||||
}
|
||||
.el-color-picker__trigger {
|
||||
border: 1px solid var(--next-border-color-light) !important;
|
||||
}
|
||||
|
||||
// popper / dropdown
|
||||
.el-popper {
|
||||
border: 1px solid var(--next-border-color) !important;
|
||||
color: var(--el-text-color-primary) !important;
|
||||
.el-popper__arrow:before {
|
||||
background: var(--el-color-white) !important;
|
||||
border: 1px solid var(--next-border-color);
|
||||
}
|
||||
a {
|
||||
color: var(--el-text-color-primary) !important;
|
||||
}
|
||||
}
|
||||
.el-popper,
|
||||
.el-dropdown-menu {
|
||||
background: var(--el-color-white) !important;
|
||||
}
|
||||
.el-dropdown-menu__item:hover:not(.is-disabled) {
|
||||
background: var(--el-bg-color) !important;
|
||||
}
|
||||
.el-dropdown-menu__item.is-disabled {
|
||||
font-weight: 700 !important;
|
||||
}
|
||||
|
||||
// input
|
||||
.el-input-group__append,
|
||||
.el-input-group__prepend {
|
||||
border: var(--el-input-border) !important;
|
||||
border-right: none !important;
|
||||
background: var(--next-color-disabled) !important;
|
||||
border-left: 0 !important;
|
||||
}
|
||||
.el-input-number__decrease,
|
||||
.el-input-number__increase {
|
||||
background: var(--next-color-disabled) !important;
|
||||
}
|
||||
|
||||
// tag
|
||||
.el-select .el-select__tags .el-tag {
|
||||
background-color: var(--next-bg-color) !important;
|
||||
}
|
||||
|
||||
// pagination
|
||||
.el-pagination.is-background .el-pager li:not(.disabled).active {
|
||||
color: var(--next-color-white) !important;
|
||||
}
|
||||
.el-pagination.is-background .btn-next,
|
||||
.el-pagination.is-background .btn-prev,
|
||||
.el-pagination.is-background .el-pager li {
|
||||
background-color: var(--next-bg-color);
|
||||
}
|
||||
|
||||
// radio
|
||||
.el-radio-button:not(.is-active) .el-radio-button__inner {
|
||||
border: 1px solid var(--next-border-color-light) !important;
|
||||
border-left: 0 !important;
|
||||
}
|
||||
.el-radio-button.is-active .el-radio-button__inner {
|
||||
color: var(--next-color-white) !important;
|
||||
}
|
||||
|
||||
// countup
|
||||
.countup-card-item-flex {
|
||||
color: var(--el-text-color-primary) !important;
|
||||
}
|
||||
|
||||
// editor
|
||||
.editor-container {
|
||||
.w-e-toolbar {
|
||||
background: var(--el-color-white) !important;
|
||||
border: 1px solid var(--next-border-color-light) !important;
|
||||
.w-e-menu:hover {
|
||||
background: var(--next-color-user-hover) !important;
|
||||
i {
|
||||
color: var(--el-text-color-primary) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
.w-e-text-container {
|
||||
border: 1px solid var(--next-border-color-light) !important;
|
||||
border-top: none !important;
|
||||
.w-e-text {
|
||||
background: var(--el-color-white) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// date-picker
|
||||
.el-picker-panel {
|
||||
background: var(--el-color-white) !important;
|
||||
}
|
||||
|
||||
// dialog
|
||||
.el-dialog {
|
||||
border: 1px solid var(--el-border-color-lighter);
|
||||
.el-dialog__header {
|
||||
color: var(--el-text-color-primary) !important;
|
||||
}
|
||||
}
|
||||
|
||||
// columns
|
||||
.layout-columns-aside ul .layout-columns-active {
|
||||
color: var(--next-color-white) !important;
|
||||
}
|
||||
.layout-columns-aside {
|
||||
border-right: 1px solid var(--next-border-columns);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -13,12 +13,12 @@
|
||||
span {
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: var(--color-primary);
|
||||
color: var(--el-color-primary);
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
.span-active {
|
||||
color: var(--color-primary);
|
||||
color: var(--el-color-primary);
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
@ -47,21 +47,21 @@
|
||||
}
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background-color: var(--color-primary-light-9);
|
||||
border: 1px solid var(--color-primary-light-6);
|
||||
background-color: var(--el-color-primary-light-9);
|
||||
border: 1px solid var(--el-color-primary-light-6);
|
||||
.icon-selector-warp-item-value {
|
||||
i {
|
||||
color: var(--color-primary);
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.icon-selector-active {
|
||||
background-color: var(--color-primary-light-9);
|
||||
border: 1px solid var(--color-primary-light-6);
|
||||
background-color: var(--el-color-primary-light-9);
|
||||
border: 1px solid var(--el-color-primary-light-6);
|
||||
.icon-selector-warp-item-value {
|
||||
i {
|
||||
color: var(--color-primary);
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
@import './app.scss';
|
||||
@import './base.scss';
|
||||
@import 'common/transition.scss';
|
||||
@import './other.scss';
|
||||
@import './element.scss';
|
||||
@import './iconSelector.scss';
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
.loading-next .loading-next-box-warp .loading-next-box-item {
|
||||
width: 33.333333%;
|
||||
height: 33.333333%;
|
||||
background: var(--color-primary);
|
||||
background: var(--el-color-primary);
|
||||
float: left;
|
||||
animation: loading-next-animation 1.2s infinite ease;
|
||||
border-radius: 1px;
|
||||
|
||||
25
src/theme/media/date.scss
Normal file
25
src/theme/media/date.scss
Normal file
@ -0,0 +1,25 @@
|
||||
@import './index.scss';
|
||||
|
||||
/* 页面宽度小于768px
|
||||
------------------------------- */
|
||||
@media screen and (max-width: $sm) {
|
||||
// 时间选择器适配
|
||||
.el-date-range-picker {
|
||||
width: 100vw;
|
||||
.el-picker-panel__body {
|
||||
min-width: 100%;
|
||||
.el-date-range-picker__content {
|
||||
.el-date-range-picker__header div {
|
||||
margin-left: 22px;
|
||||
margin-right: 0px;
|
||||
}
|
||||
& + .el-date-range-picker__content {
|
||||
.el-date-range-picker__header div {
|
||||
margin-left: 0px;
|
||||
margin-right: 22px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3,8 +3,21 @@
|
||||
/* 页面宽度小于768px
|
||||
------------------------------- */
|
||||
@media screen and (max-width: $sm) {
|
||||
.home-warning-media,
|
||||
.home-dynamic-media {
|
||||
.home-media,
|
||||
.home-media-sm {
|
||||
margin-top: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 页面宽度小于1200px
|
||||
------------------------------- */
|
||||
@media screen and (max-width: $lg) {
|
||||
.home-media-lg {
|
||||
margin-top: 15px;
|
||||
}
|
||||
.home-monitor {
|
||||
.flex-warp-item {
|
||||
width: 33.33% !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,37 +1,15 @@
|
||||
/* 栅格布局(媒体查询变量)
|
||||
* $xs <768px 响应式栅格
|
||||
* https://developer.mozilla.org/zh-CN/docs/Learn/CSS/CSS_layout/Media_queries
|
||||
* $us ≥376px 响应式栅格
|
||||
* $xs ≥576px 响应式栅格
|
||||
* $sm ≥768px 响应式栅格
|
||||
* $md ≥992px 响应式栅格
|
||||
* $lg ≥1200px 响应式栅格
|
||||
* $xl ≥1920px 响应式栅格
|
||||
------------------------------- */
|
||||
$us: 376px;
|
||||
$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) {
|
||||
}
|
||||
|
||||
@ -1,12 +1,41 @@
|
||||
@import './index.scss';
|
||||
|
||||
/* 页面宽度小于992px
|
||||
------------------------------- */
|
||||
@media screen and (max-width: $lg) {
|
||||
.login-container {
|
||||
.login-icon-group {
|
||||
&::before {
|
||||
content: '';
|
||||
height: 70% !important;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
&::after {
|
||||
content: '';
|
||||
width: 100px !important;
|
||||
height: 200px !important;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 页面宽度小于992px
|
||||
------------------------------- */
|
||||
@media screen and (max-width: $md) {
|
||||
.login-content {
|
||||
right: unset !important;
|
||||
left: 50% !important;
|
||||
transform: translate(-50%, -50%) translate3d(0, 0, 0) !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* 页面宽度小于576px
|
||||
------------------------------- */
|
||||
@media screen and (max-width: $xs) {
|
||||
.login-container {
|
||||
background: none !important;
|
||||
.login-logo {
|
||||
display: none;
|
||||
.login-icon-group {
|
||||
display: none !important;
|
||||
}
|
||||
.login-content {
|
||||
width: 100% !important;
|
||||
@ -16,9 +45,6 @@
|
||||
box-shadow: unset !important;
|
||||
border: none !important;
|
||||
}
|
||||
.login-copyright {
|
||||
display: none !important;
|
||||
}
|
||||
.el-form-item {
|
||||
display: flex !important;
|
||||
}
|
||||
@ -27,7 +53,7 @@
|
||||
|
||||
/* 页面宽度小于375px
|
||||
------------------------------- */
|
||||
@media screen and (max-width: 376px) {
|
||||
@media screen and (max-width: $us) {
|
||||
.login-container {
|
||||
.login-content-title {
|
||||
font-size: 18px !important;
|
||||
|
||||
@ -10,3 +10,4 @@
|
||||
@import './pagination.scss';
|
||||
@import './dialog.scss';
|
||||
@import './cityLinkage.scss';
|
||||
@import './date.scss';
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
height: 3px !important;
|
||||
}
|
||||
::-webkit-scrollbar-track-piece {
|
||||
background-color: #f8f8f8;
|
||||
background-color: var(--next-bg-main-color);
|
||||
}
|
||||
// 滚动条的设置
|
||||
::-webkit-scrollbar-thumb {
|
||||
@ -40,7 +40,7 @@
|
||||
height: 7px;
|
||||
}
|
||||
::-webkit-scrollbar-track-piece {
|
||||
background-color: #f8f8f8;
|
||||
background-color: var(--next-bg-main-color);
|
||||
}
|
||||
// 滚动条的设置
|
||||
::-webkit-scrollbar-thumb {
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
/* Button 按钮
|
||||
------------------------------- */
|
||||
@mixin Button($main, $c1, $c2) {
|
||||
color: set-color($main);
|
||||
background: set-color($c1);
|
||||
border-color: set-color($c2);
|
||||
}
|
||||
|
||||
/* Radio 单选框、Checkbox 多选框
|
||||
------------------------------- */
|
||||
@mixin RadioCheckbox($name) {
|
||||
background-color: set-color($name);
|
||||
border-color: set-color($name);
|
||||
}
|
||||
|
||||
/* Tag 标签
|
||||
------------------------------- */
|
||||
@mixin Tag($main, $c1, $c2) {
|
||||
color: set-color($main);
|
||||
background-color: set-color($c1);
|
||||
border-color: set-color($c2);
|
||||
}
|
||||
@mixin TagDark($main, $c1) {
|
||||
color: set-color($main);
|
||||
background-color: set-color($c1);
|
||||
}
|
||||
|
||||
/* Alert 警告
|
||||
------------------------------- */
|
||||
@mixin Alert($main, $c1, $c2) {
|
||||
color: set-color($main);
|
||||
background: set-color($c1);
|
||||
border: 1px solid set-color($c2);
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
/* 颜色调用函数
|
||||
------------------------------- */
|
||||
@function set-color($key) {
|
||||
@return var(--color-#{$key});
|
||||
}
|
||||
@ -4,7 +4,7 @@
|
||||
* @param old 源数据
|
||||
* @returns 两数组相同返回 `true`,反之则反
|
||||
*/
|
||||
export function judementSameArr(news: Array<string>, old: Array<string>): boolean {
|
||||
export function judementSameArr(news: unknown[] | string[], old: string[]): boolean {
|
||||
let count = 0;
|
||||
const leng = old.length;
|
||||
for (let i in old) {
|
||||
|
||||
@ -5,25 +5,21 @@ import { formatDate } from '/@/utils/formatTime';
|
||||
|
||||
export default function () {
|
||||
const { toClipboard } = useClipboard();
|
||||
|
||||
// 百分比格式化
|
||||
//百分比格式化
|
||||
const percentFormat = (row: any, column: number, cellValue: any) => {
|
||||
return cellValue ? `${cellValue}%` : '-';
|
||||
};
|
||||
|
||||
// 列表日期时间格式化
|
||||
//列表日期时间格式化
|
||||
const dateFormatYMD = (row: any, column: number, cellValue: any) => {
|
||||
if (!cellValue) return '-';
|
||||
return formatDate(new Date(cellValue), 'YYYY-mm-dd');
|
||||
};
|
||||
|
||||
// 列表日期时间格式化
|
||||
//列表日期时间格式化
|
||||
const dateFormatYMDHMS = (row: any, column: number, cellValue: any) => {
|
||||
if (!cellValue) return '-';
|
||||
return formatDate(new Date(cellValue), 'YYYY-mm-dd HH:MM:SS');
|
||||
};
|
||||
|
||||
// 列表日期时间格式化
|
||||
//列表日期时间格式化
|
||||
const dateFormatHMS = (row: any, column: number, cellValue: any) => {
|
||||
if (!cellValue) return '-';
|
||||
let time = 0;
|
||||
@ -31,34 +27,30 @@ export default function () {
|
||||
if (typeof cellValue === 'number') time = cellValue;
|
||||
return formatDate(new Date(time * 1000), 'HH:MM:SS');
|
||||
};
|
||||
|
||||
// 小数格式化
|
||||
const scaleFormat = (value: any = 0, scale: number = 4) => {
|
||||
return Number.parseFloat(value).toFixed(scale);
|
||||
};
|
||||
|
||||
// 小数格式化
|
||||
const scale2Format = (value: any = 0) => {
|
||||
return Number.parseFloat(value).toFixed(2);
|
||||
};
|
||||
|
||||
// 点击复制文本
|
||||
const copyText = (text: string) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
// 复制
|
||||
//复制
|
||||
toClipboard(text);
|
||||
// 下面可以设置复制成功的提示框等操作
|
||||
//下面可以设置复制成功的提示框等操作
|
||||
ElMessage.success('复制成功!');
|
||||
resolve(text);
|
||||
} catch (e) {
|
||||
// 复制失败
|
||||
ElMessage.error('复制失败');
|
||||
//复制失败
|
||||
ElMessage.error('复制失败!');
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
percentFormat,
|
||||
dateFormatYMD,
|
||||
|
||||
@ -28,14 +28,14 @@ const getAlicdnIconfont = () => {
|
||||
});
|
||||
};
|
||||
|
||||
// 初始化获取 css 样式,获取 element plus 自带 svg 图标,增加了 element 前缀,使用时:elementAim
|
||||
// 初始化获取 css 样式,获取 element plus 自带 svg 图标,增加了 ele- 前缀,使用时:ele-Aim
|
||||
const getElementPlusIconfont = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
nextTick(() => {
|
||||
const icons = svg as any;
|
||||
const sheetsIconList = [];
|
||||
for (const i in icons) {
|
||||
sheetsIconList.push(`element${icons[i].name}`);
|
||||
sheetsIconList.push(`ele-${icons[i].name}`);
|
||||
}
|
||||
if (sheetsIconList.length > 0) resolve(sheetsIconList);
|
||||
else reject('未获取到值,请刷新重试');
|
||||
|
||||
@ -1,25 +1,16 @@
|
||||
import { nextTick } from 'vue';
|
||||
import loadingCss from '/@/theme/loading.scss';
|
||||
import '/@/theme/loading.scss';
|
||||
|
||||
/**
|
||||
* 页面全局 Loading
|
||||
* @method setCss 载入 css
|
||||
* @method start 创建 loading
|
||||
* @method done 移除 loading
|
||||
*/
|
||||
export const NextLoading = {
|
||||
// 载入 css
|
||||
setCss: () => {
|
||||
let link = document.createElement('link');
|
||||
link.rel = 'stylesheet';
|
||||
link.href = loadingCss;
|
||||
link.crossOrigin = 'anonymous';
|
||||
document.getElementsByTagName('head')[0].appendChild(link);
|
||||
},
|
||||
// 创建 loading
|
||||
start: () => {
|
||||
const bodys: Element = document.body;
|
||||
const div = document.createElement('div');
|
||||
const div = <HTMLElement>document.createElement('div');
|
||||
div.setAttribute('class', 'loading-next');
|
||||
const htmls = `
|
||||
<div class="loading-next-box">
|
||||
@ -43,11 +34,9 @@ export const NextLoading = {
|
||||
// 移除 loading
|
||||
done: () => {
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
window.nextLoading = false;
|
||||
const el = document.querySelector('.loading-next');
|
||||
el && el.parentNode?.removeChild(el);
|
||||
}, 1000);
|
||||
window.nextLoading = false;
|
||||
const el = <HTMLElement>document.querySelector('.loading-next');
|
||||
el?.parentNode?.removeChild(el);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
@ -14,14 +14,14 @@ import SvgIcon from '/@/components/svgIcon/index.vue';
|
||||
export function elSvg(app: App) {
|
||||
const icons = svg as any;
|
||||
for (const i in icons) {
|
||||
app.component(`element${icons[i].name}`, icons[i]);
|
||||
app.component(`ele-${icons[i].name}`, icons[i]);
|
||||
}
|
||||
app.component('SvgIcon', SvgIcon);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置浏览器标题
|
||||
* @method other.useTitle();
|
||||
* 设置浏览器标题国际化
|
||||
* @method const title = useTitle(); ==> title()
|
||||
*/
|
||||
export function useTitle() {
|
||||
nextTick(() => {
|
||||
@ -99,6 +99,27 @@ export function isMobile() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断数组对象中所有属性是否为空,为空则删除当前行对象
|
||||
* @description @感谢大黄
|
||||
* @param list 数组对象
|
||||
* @returns 删除空值后的数组对象
|
||||
*/
|
||||
export function handleEmpty(list: any) {
|
||||
const arr = [];
|
||||
for (const i in list) {
|
||||
const d = [];
|
||||
for (const j in list[i]) {
|
||||
d.push(list[i][j]);
|
||||
}
|
||||
const leng = d.filter((item) => item === '').length;
|
||||
if (leng !== d.length) {
|
||||
arr.push(list[i]);
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一批量导出
|
||||
* @method elSvg 导出全局注册 element plus svg 图标
|
||||
@ -107,6 +128,7 @@ export function isMobile() {
|
||||
* @method globalComponentSize element plus 全局组件大小
|
||||
* @method deepClone 对象深克隆
|
||||
* @method isMobile 判断是否是移动端
|
||||
* @method handleEmpty 判断数组对象中所有属性是否为空,为空则删除当前行对象
|
||||
*/
|
||||
const other = {
|
||||
elSvg: (app: App) => {
|
||||
@ -125,6 +147,9 @@ const other = {
|
||||
isMobile: () => {
|
||||
return isMobile();
|
||||
},
|
||||
handleEmpty: (list: any) => {
|
||||
return handleEmpty(list);
|
||||
},
|
||||
};
|
||||
|
||||
// 统一批量导出
|
||||
|
||||
@ -14,7 +14,7 @@ service.interceptors.request.use(
|
||||
(config) => {
|
||||
// 在发送请求之前做些什么 token
|
||||
if (Session.get('token')) {
|
||||
config.headers.common['Authorization'] = `${Session.get('token')}`;
|
||||
(<any>config.headers).common['Authorization'] = `${Session.get('token')}`;
|
||||
}
|
||||
return config;
|
||||
},
|
||||
|
||||
@ -36,7 +36,7 @@ export function rgbToHex(r: any, g: any, b: any) {
|
||||
* @param level 加深的程度,限0-1之间
|
||||
* @returns 返回处理后的颜色值
|
||||
*/
|
||||
export function getDarkColor(color: any, level: number) {
|
||||
export function getDarkColor(color: string, level: number) {
|
||||
let reg = /^\#?[0-9A-Fa-f]{6}$/;
|
||||
if (!reg.test(color)) return ElMessage.warning('输入错误的hex颜色值');
|
||||
let rgb = hexToRgb(color);
|
||||
@ -50,7 +50,7 @@ export function getDarkColor(color: any, level: number) {
|
||||
* @param level 加深的程度,限0-1之间
|
||||
* @returns 返回处理后的颜色值
|
||||
*/
|
||||
export function getLightColor(color: any, level: number) {
|
||||
export function getLightColor(color: string, level: number) {
|
||||
let reg = /^\#?[0-9A-Fa-f]{6}$/;
|
||||
if (!reg.test(color)) return ElMessage.warning('输入错误的hex颜色值');
|
||||
let rgb = hexToRgb(color);
|
||||
|
||||
@ -1,31 +0,0 @@
|
||||
import dotenv from 'dotenv';
|
||||
|
||||
// 定义接口类型声明
|
||||
export interface ViteEnv {
|
||||
VITE_PORT: number;
|
||||
VITE_OPEN: boolean;
|
||||
VITE_PUBLIC_PATH: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* vite 打包相关
|
||||
* @link 参考:https://cn.vitejs.dev/guide/env-and-mode.html
|
||||
* @returns 返回 `VITE_xxx` 环境变量和模式信息
|
||||
*/
|
||||
export function loadEnv(): ViteEnv {
|
||||
const env = process.env.NODE_ENV;
|
||||
const ret: any = {};
|
||||
const envList = [`.env.${env}.local`, `.env.${env}`, '.env.local', '.env'];
|
||||
envList.forEach((e) => {
|
||||
dotenv.config({ path: e });
|
||||
});
|
||||
for (const envName of Object.keys(process.env)) {
|
||||
let realName = (process.env as any)[envName].replace(/\\n/g, '\n');
|
||||
realName = realName === 'true' ? true : realName === 'false' ? false : realName;
|
||||
if (envName === 'VITE_PORT') realName = Number(realName);
|
||||
if (envName === 'VITE_OPEN') realName = Boolean(realName);
|
||||
ret[envName] = realName;
|
||||
process.env[envName] = realName;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
// 页面添加水印效果
|
||||
const setWatermark = (str: string) => {
|
||||
const id = '1.23452384164.123412416';
|
||||
if (document.getElementById(id) !== null) document.body.removeChild(document.getElementById(id) as any);
|
||||
if (document.getElementById(id) !== null) document.body.removeChild(<HTMLElement>document.getElementById(id));
|
||||
const can = document.createElement('canvas');
|
||||
can.width = 200;
|
||||
can.height = 130;
|
||||
@ -39,7 +39,7 @@ const watermark = {
|
||||
// 删除水印
|
||||
del: () => {
|
||||
let id = '1.23452384164.123412416';
|
||||
if (document.getElementById(id) !== null) document.body.removeChild(document.getElementById(id) as any);
|
||||
if (document.getElementById(id) !== null) document.body.removeChild(<HTMLElement>document.getElementById(id));
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@ -19,9 +19,10 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { Session } from '/@/utils/storage';
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: '401',
|
||||
setup() {
|
||||
const router = useRouter();
|
||||
@ -33,7 +34,7 @@ export default {
|
||||
onSetAuth,
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@ -19,8 +19,9 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: '404',
|
||||
setup() {
|
||||
const router = useRouter();
|
||||
@ -31,7 +32,7 @@ export default {
|
||||
onGoHome,
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -1,89 +0,0 @@
|
||||
/**
|
||||
* 最顶部 card
|
||||
* @returns 返回模拟数据
|
||||
*/
|
||||
export const topCardItemList = [
|
||||
{
|
||||
title: '今日访问人数',
|
||||
titleNum: '123',
|
||||
tip: '在场人数',
|
||||
tipNum: '911',
|
||||
color: '#F95959',
|
||||
iconColor: '#F86C6B',
|
||||
icon: 'iconfont icon-jinridaiban',
|
||||
},
|
||||
{
|
||||
title: '实验室总数',
|
||||
titleNum: '123',
|
||||
tip: '使用中',
|
||||
tipNum: '611',
|
||||
color: '#8595F4',
|
||||
iconColor: '#92A1F4',
|
||||
icon: 'iconfont icon-AIshiyanshi',
|
||||
},
|
||||
{
|
||||
title: '申请人数(月)',
|
||||
titleNum: '123',
|
||||
tip: '通过人数',
|
||||
tipNum: '911',
|
||||
color: '#FEBB50',
|
||||
iconColor: '#FDC566',
|
||||
icon: 'iconfont icon-shenqingkaiban',
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* 环境监测
|
||||
* @returns 返回模拟数据
|
||||
*/
|
||||
export const environmentList = [
|
||||
{
|
||||
icon: 'iconfont icon-yangan',
|
||||
label: '烟感',
|
||||
value: '2.1%OBS/M',
|
||||
iconColor: '#F72B3F',
|
||||
},
|
||||
{
|
||||
icon: 'iconfont icon-wendu',
|
||||
label: '温度',
|
||||
value: '30℃',
|
||||
iconColor: '#91BFF8',
|
||||
},
|
||||
{
|
||||
icon: 'iconfont icon-shidu',
|
||||
label: '湿度',
|
||||
value: '57%RH',
|
||||
iconColor: '#88D565',
|
||||
},
|
||||
{
|
||||
icon: 'iconfont icon-zaosheng',
|
||||
label: '噪声',
|
||||
value: '57DB',
|
||||
iconColor: '#FBD4A0',
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* 动态信息
|
||||
* @returns 返回模拟数据
|
||||
*/
|
||||
export const activitiesList = [
|
||||
{
|
||||
time1: '今天',
|
||||
time2: '12:20:30',
|
||||
title: '更名',
|
||||
label: '正式更名为 vue-next-admin',
|
||||
},
|
||||
{
|
||||
time1: '02-17',
|
||||
time2: '12:20:30',
|
||||
title: '页面',
|
||||
label: '完成对首页的开发',
|
||||
},
|
||||
{
|
||||
time1: '02-14',
|
||||
time2: '12:20:30',
|
||||
title: '页面',
|
||||
label: '新增个人中心',
|
||||
},
|
||||
];
|
||||
@ -1,16 +1,16 @@
|
||||
<template>
|
||||
<el-form class="login-content-form">
|
||||
<el-form-item>
|
||||
<el-input type="text" placeholder="用户名 admin 或不输均为 test" v-model="ruleForm.userName" clearable autocomplete="off">
|
||||
<el-form size="large" class="login-content-form">
|
||||
<el-form-item class="login-animation1">
|
||||
<el-input type="text" placeholder="用户名 admin 或不输均为 common" v-model="ruleForm.userName" clearable autocomplete="off">
|
||||
<template #prefix>
|
||||
<el-icon class="el-input__icon"><elementUser /></el-icon>
|
||||
<el-icon class="el-input__icon"><ele-User /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-form-item class="login-animation2">
|
||||
<el-input :type="isShowPassword ? 'text' : 'password'" placeholder="密码:123456" v-model="ruleForm.password" autocomplete="off">
|
||||
<template #prefix>
|
||||
<el-icon class="el-input__icon"><elementUnlock /></el-icon>
|
||||
<el-icon class="el-input__icon"><ele-Unlock /></el-icon>
|
||||
</template>
|
||||
<template #suffix>
|
||||
<i
|
||||
@ -22,23 +22,20 @@
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-row :gutter="15">
|
||||
<el-col :span="16">
|
||||
<el-input type="text" maxlength="4" placeholder="请输入验证码" v-model="ruleForm.code" clearable autocomplete="off">
|
||||
<template #prefix>
|
||||
<el-icon class="el-input__icon"><elementPosition /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="login-content-code">
|
||||
<span class="login-content-code-img">1234</span>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item class="login-animation3">
|
||||
<el-col :span="15">
|
||||
<el-input type="text" maxlength="4" placeholder="请输入验证码" v-model="ruleForm.code" clearable autocomplete="off">
|
||||
<template #prefix>
|
||||
<el-icon class="el-input__icon"><ele-Position /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-col>
|
||||
<el-col :span="1"></el-col>
|
||||
<el-col :span="8">
|
||||
<el-button class="login-content-code">1234</el-button>
|
||||
</el-col>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-form-item class="login-animation4">
|
||||
<el-button type="primary" class="login-content-submit" round @click="onSignIn" :loading="loading.signIn">
|
||||
<span>登 录</span>
|
||||
</el-button>
|
||||
@ -47,7 +44,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive, defineComponent, computed, getCurrentInstance } from 'vue';
|
||||
import { toRefs, reactive, defineComponent, computed } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { initFrontEndControlRoutes } from '/@/router/frontEnd';
|
||||
@ -56,9 +53,8 @@ import { useStore } from '/@/store/index';
|
||||
import { Session } from '/@/utils/storage';
|
||||
import { formatAxis } from '/@/utils/formatTime';
|
||||
export default defineComponent({
|
||||
name: 'login',
|
||||
name: 'loginAccount',
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const store = useStore();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
@ -88,7 +84,7 @@ export default defineComponent({
|
||||
// admin 按钮权限标识
|
||||
let adminAuthBtnList: Array<string> = ['btn.add', 'btn.del', 'btn.edit', 'btn.link'];
|
||||
// test 页面权限标识,对应路由 meta.roles,用于控制路由的显示/隐藏
|
||||
let testAuthPageList: Array<string> = ['common'];
|
||||
let testRoles: Array<string> = ['common'];
|
||||
// test 按钮权限标识
|
||||
let testAuthBtnList: Array<string> = ['btn.add', 'btn.link'];
|
||||
// 不同用户模拟不同的用户权限
|
||||
@ -96,7 +92,7 @@ export default defineComponent({
|
||||
defaultRoles = adminRoles;
|
||||
defaultAuthBtnList = adminAuthBtnList;
|
||||
} else {
|
||||
defaultRoles = testAuthPageList;
|
||||
defaultRoles = testRoles;
|
||||
defaultAuthBtnList = testAuthBtnList;
|
||||
}
|
||||
// 用户信息模拟数据
|
||||
@ -137,23 +133,19 @@ export default defineComponent({
|
||||
// 如果是复制粘贴的路径,非首页/登录页,那么登录成功后重定向到对应的路径中
|
||||
if (route.query?.redirect) {
|
||||
router.push({
|
||||
path: route.query?.redirect,
|
||||
query: Object.keys(route.query?.params).length > 0 ? JSON.parse(route.query?.params) : '',
|
||||
path: <string>route.query?.redirect,
|
||||
query: Object.keys(<string>route.query?.params).length > 0 ? JSON.parse(<string>route.query?.params) : '',
|
||||
});
|
||||
} else {
|
||||
router.push('/');
|
||||
}
|
||||
// 登录成功提示
|
||||
setTimeout(() => {
|
||||
// 关闭 loading
|
||||
state.loading.signIn = true;
|
||||
ElMessage.success(`${currentTimeInfo},欢迎回来!`);
|
||||
// 修复防止退出登录再进入界面时,需要刷新样式才生效的问题,初始化布局样式等(登录的时候触发,目前方案)
|
||||
proxy.mittBus.emit('onSignInClick');
|
||||
}, 300);
|
||||
// 关闭 loading
|
||||
state.loading.signIn = true;
|
||||
const signInText = '欢迎回来!';
|
||||
ElMessage.success(`${currentTimeInfo},${signInText}`);
|
||||
};
|
||||
return {
|
||||
currentTime,
|
||||
onSignIn,
|
||||
...toRefs(state),
|
||||
};
|
||||
@ -164,39 +156,28 @@ export default defineComponent({
|
||||
<style scoped lang="scss">
|
||||
.login-content-form {
|
||||
margin-top: 20px;
|
||||
@for $i from 1 through 4 {
|
||||
.login-animation#{$i} {
|
||||
opacity: 0;
|
||||
animation-name: error-num;
|
||||
animation-duration: 0.5s;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: calc($i/10) + s;
|
||||
}
|
||||
}
|
||||
.login-content-password {
|
||||
display: inline-block;
|
||||
width: 25px;
|
||||
width: 20px;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: #909399;
|
||||
}
|
||||
}
|
||||
.login-content-code {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
.login-content-code-img {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
background-color: #ffffff;
|
||||
border: 1px solid rgb(220, 223, 230);
|
||||
color: #333;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 5px;
|
||||
text-indent: 5px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
transition: all ease 0.2s;
|
||||
border-radius: 4px;
|
||||
user-select: none;
|
||||
&:hover {
|
||||
border-color: #c0c4cc;
|
||||
transition: all ease 0.2s;
|
||||
}
|
||||
}
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
font-weight: bold;
|
||||
letter-spacing: 5px;
|
||||
}
|
||||
.login-content-submit {
|
||||
width: 100%;
|
||||
|
||||
@ -1,45 +1,55 @@
|
||||
<template>
|
||||
<el-form class="login-content-form">
|
||||
<el-form-item>
|
||||
<el-form size="large" class="login-content-form">
|
||||
<el-form-item class="login-animation1">
|
||||
<el-input type="text" placeholder="请输入手机号" v-model="ruleForm.userName" clearable autocomplete="off">
|
||||
<template #prefix>
|
||||
<i class="iconfont icon-dianhua el-input__icon"></i>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-row :gutter="15">
|
||||
<el-col :span="16">
|
||||
<el-input type="text" maxlength="4" placeholder="请输入验证码" v-model="ruleForm.code" clearable autocomplete="off">
|
||||
<template #prefix>
|
||||
<el-icon class="el-input__icon"><elementPosition /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-button class="login-content-code">获取验证码</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item class="login-animation2">
|
||||
<el-col :span="15">
|
||||
<el-input type="text" maxlength="4" placeholder="请输入验证码" v-model="ruleForm.code" clearable autocomplete="off">
|
||||
<template #prefix>
|
||||
<el-icon class="el-input__icon"><ele-Position /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-col>
|
||||
<el-col :span="1"></el-col>
|
||||
<el-col :span="8">
|
||||
<el-button class="login-content-code">获取验证码</el-button>
|
||||
</el-col>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" class="login-content-submit" round>
|
||||
<el-form-item class="login-animation3">
|
||||
<el-button round type="primary" class="login-content-submit">
|
||||
<span>登 录</span>
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
<div class="font12 mt30 login-animation4 login-msg">
|
||||
* 温馨提示:建议使用谷歌、Microsoft Edge,版本 79.0.1072.62 及以上浏览器,360浏览器请使用极速模式
|
||||
</div>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive, defineComponent } from 'vue';
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface LoginMobileState {
|
||||
userName: any;
|
||||
code: string | number | undefined;
|
||||
}
|
||||
|
||||
// 定义对象与类型
|
||||
const ruleForm: LoginMobileState = {
|
||||
userName: '',
|
||||
code: '',
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
name: 'login',
|
||||
name: 'loginMobile',
|
||||
setup() {
|
||||
const state = reactive({
|
||||
ruleForm: {
|
||||
userName: '',
|
||||
code: '',
|
||||
},
|
||||
});
|
||||
const state = reactive({ ruleForm });
|
||||
return {
|
||||
...toRefs(state),
|
||||
};
|
||||
@ -50,6 +60,15 @@ export default defineComponent({
|
||||
<style scoped lang="scss">
|
||||
.login-content-form {
|
||||
margin-top: 20px;
|
||||
@for $i from 1 through 4 {
|
||||
.login-animation#{$i} {
|
||||
opacity: 0;
|
||||
animation-name: error-num;
|
||||
animation-duration: 0.5s;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: calc($i/10) + s;
|
||||
}
|
||||
}
|
||||
.login-content-code {
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
@ -60,5 +79,8 @@ export default defineComponent({
|
||||
font-weight: 300;
|
||||
margin-top: 15px;
|
||||
}
|
||||
.login-msg {
|
||||
color: var(--el-text-color-placeholder);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,21 +1,21 @@
|
||||
<template>
|
||||
<div class="login-scan-container">
|
||||
<div class="login-scan-qrcode" ref="qrcodeRef"></div>
|
||||
<div ref="qrcodeRef"></div>
|
||||
<div class="font12 mt20 login-msg">打开手机扫一扫,快速登录/注册</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive, defineComponent, onMounted, getCurrentInstance } from 'vue';
|
||||
import { ref, defineComponent, onMounted } from 'vue';
|
||||
import QRCode from 'qrcodejs2-fixes';
|
||||
export default defineComponent({
|
||||
name: 'login11',
|
||||
name: 'loginScan',
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const state = reactive({});
|
||||
const qrcodeRef = ref<HTMLElement | null>(null);
|
||||
// 初始化生成二维码
|
||||
const initQrcode = () => {
|
||||
proxy.$refs.qrcodeRef.innerHTML = '';
|
||||
new QRCode(proxy.$refs.qrcodeRef, {
|
||||
(qrcodeRef.value as HTMLElement).innerHTML = '';
|
||||
new QRCode(qrcodeRef.value, {
|
||||
text: `https://qm.qq.com/cgi-bin/qm/qr?k=RdUY97Vx0T0vZ_1OOu-X1yFNkWgDwbjC&jump_from=webapi`,
|
||||
width: 260,
|
||||
height: 260,
|
||||
@ -27,20 +27,32 @@ export default defineComponent({
|
||||
onMounted(() => {
|
||||
initQrcode();
|
||||
});
|
||||
return {
|
||||
...toRefs(state),
|
||||
};
|
||||
return { qrcodeRef };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.login-scan-animation {
|
||||
opacity: 0;
|
||||
animation-name: error-num;
|
||||
animation-duration: 0.5s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
.login-scan-container {
|
||||
.login-scan-qrcode {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -40%);
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
@extend .login-scan-animation;
|
||||
animation-delay: 0.1s;
|
||||
::v-deep(img) {
|
||||
margin: auto;
|
||||
}
|
||||
.login-msg {
|
||||
color: var(--el-text-color-placeholder);
|
||||
@extend .login-scan-animation;
|
||||
animation-delay: 0.2s;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,114 +1,148 @@
|
||||
<template>
|
||||
<div class="login-container">
|
||||
<div class="login-logo">
|
||||
<span>{{ getThemeConfig.globalViceTitle }}</span>
|
||||
<div class="login-icon-group">
|
||||
<div class="login-icon-group-title">
|
||||
<img :src="logoMini" />
|
||||
<div class="login-icon-group-title-text font25">{{ getThemeConfig.globalViceTitle }}</div>
|
||||
</div>
|
||||
<img :src="loginIconTwo" class="login-icon-group-icon" />
|
||||
</div>
|
||||
<div class="login-content" :class="{ 'login-content-mobile': tabsActiveName === 'mobile' }">
|
||||
<div class="login-content">
|
||||
<div class="login-content-main">
|
||||
<h4 class="login-content-title">{{ getThemeConfig.globalTitle }}后台模板</h4>
|
||||
<h4 class="login-content-title ml15">{{ getThemeConfig.globalTitle }}后台模板</h4>
|
||||
<div v-if="!isScan">
|
||||
<el-tabs v-model="tabsActiveName" @tab-click="onTabsClick">
|
||||
<el-tab-pane label="账号密码登录" name="account" :disabled="tabsActiveName === 'account'">
|
||||
<transition name="el-zoom-in-center">
|
||||
<Account v-show="isTabPaneShow" />
|
||||
</transition>
|
||||
<el-tabs v-model="tabsActiveName">
|
||||
<el-tab-pane label="账号密码登录" name="account">
|
||||
<Account />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="手机号登录" name="mobile" :disabled="tabsActiveName === 'mobile'">
|
||||
<transition name="el-zoom-in-center">
|
||||
<Mobile v-show="!isTabPaneShow" />
|
||||
</transition>
|
||||
<el-tab-pane label="手机号登录" name="mobile">
|
||||
<Mobile />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<div class="mt10">
|
||||
<el-button type="text" size="small">第三方登录</el-button>
|
||||
<el-button type="text" size="small">友情链接</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<Scan v-else />
|
||||
<Scan v-if="isScan" />
|
||||
<div class="login-content-main-sacn" @click="isScan = !isScan">
|
||||
<i class="iconfont" :class="isScan ? 'icon-diannao1' : 'icon-barcode-qr'"></i>
|
||||
<div class="login-content-main-sacn-delta"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="login-copyright">
|
||||
<div class="mb5 login-copyright-company">版权所有:深圳市xxx软件科技有限公司</div>
|
||||
<div class="login-copyright-msg">Copyright: Shenzhen XXX Software Technology 粤ICP备05010000号</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive, computed } from 'vue';
|
||||
import { toRefs, reactive, computed, defineComponent } from 'vue';
|
||||
import Account from '/@/views/login/component/account.vue';
|
||||
import Mobile from '/@/views/login/component/mobile.vue';
|
||||
import Scan from '/@/views/login/component/scan.vue';
|
||||
import { useStore } from '/@/store/index';
|
||||
export default {
|
||||
name: 'login',
|
||||
|
||||
import logoMini from '/@/assets/logo-mini.svg';
|
||||
import loginIconTwo from '/@/assets/login-icon-two.svg';
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface LoginState {
|
||||
tabsActiveName: string;
|
||||
isScan: boolean;
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'loginIndex',
|
||||
components: { Account, Mobile, Scan },
|
||||
setup() {
|
||||
const store = useStore();
|
||||
const state = reactive({
|
||||
const state = reactive<LoginState>({
|
||||
tabsActiveName: 'account',
|
||||
isTabPaneShow: true,
|
||||
isScan: false,
|
||||
});
|
||||
// 获取布局配置信息
|
||||
const getThemeConfig = computed(() => {
|
||||
return store.state.themeConfig.themeConfig;
|
||||
});
|
||||
// 切换密码、手机登录
|
||||
const onTabsClick = () => {
|
||||
state.isTabPaneShow = !state.isTabPaneShow;
|
||||
};
|
||||
return {
|
||||
onTabsClick,
|
||||
logoMini,
|
||||
loginIconTwo,
|
||||
getThemeConfig,
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.login-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: url('https://gitee.com/lyt-top/vue-next-admin-images/raw/master/login/bg-login.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
.login-logo {
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
left: 50%;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 20px;
|
||||
color: var(--color-primary);
|
||||
letter-spacing: 2px;
|
||||
width: 90%;
|
||||
transform: translateX(-50%);
|
||||
position: relative;
|
||||
background: var(--el-color-white);
|
||||
.login-icon-group {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
.login-icon-group-title {
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
left: 80px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
img {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
&-text {
|
||||
padding-left: 15px;
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 60%;
|
||||
overflow: hidden;
|
||||
height: 80%;
|
||||
-webkit-mask-box-image: url("data:image/svg+xml,%3Csvg width='1200' height='770' xmlns='http://www.w3.org/2000/svg' fill='none'%3E%3Cg%3E%3Cpath id='svg_1' d='M58.4 47.77C104.6 59.51 135.26 67.37 162.11 78.04C188.97 88.72 226.33 102.69 265.92 123.55C305.51 144.4 366.96 167.09 441.43 121.52C515.9 75.95 546.48 61.01 577.69 46.27C608.9 31.53 625.86 23.69 680.26 12.28C734.65 0.87 837.29 10.7 867.29 21.8C897.29 32.9 935.51 51.9 962.21 95.45C988.9 139.01 972.91 177.36 951.37 221.39C929.83 265.43 883.49 306 890.44 337.33C897.4 368.66 974.73 412.18 974.73 411.47C974.73 412.18 1066.36 457.62 1106.36 491.06C1146.36 524.5 1178.8 563.36 1184.03 579.63C1189.26 595.9 1200.4 622.49 1181.55 676.88C1162.71 731.26 1127.16 764.32 1115.31 778.64C1103.45 792.96 5.34 783.61 4.32 784.63C3.3 785.65 -172.34 2.38 1.13 35.04L58.4 47.77L58.4 47.77Z' fill='%23409eff'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");
|
||||
background: var(--el-color-primary-light-5);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
&::after {
|
||||
content: '';
|
||||
width: 150px;
|
||||
height: 300px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
-webkit-mask-box-image: url("data:image/svg+xml,%3Csvg width='150' height='300' xmlns='http://www.w3.org/2000/svg' fill='none'%3E%3Cg%3E%3Cpath id='svg_1' d='M-0.56 -0.28C41.94 36.17 67.73 18.94 93.33 33.96C118.93 48.98 107.58 73.56 101.94 89.76C96.29 105.96 50.09 217.83 47.87 231.18C45.64 244.52 46.02 255.2 64.4 270.05C82.79 284.91 121.99 292.31 111.98 289.81C101.97 287.32 153.96 301.48 151.83 299.9C149.69 298.32 149.98 -1.36 149.71 -1.18C149.98 -1.36 -43.06 -36.74 -0.56 -0.28L-0.56 -0.28Z' fill='%23409eff'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");
|
||||
background: var(--el-color-primary-light-5);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
&-icon {
|
||||
width: 60%;
|
||||
height: 70%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
.login-content {
|
||||
width: 500px;
|
||||
padding: 20px;
|
||||
position: absolute;
|
||||
right: 200px;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%) translate3d(0, 0, 0);
|
||||
background-color: rgba(255, 255, 255, 0.99);
|
||||
border: 5px solid var(--color-primary-light-8);
|
||||
border-radius: 4px;
|
||||
transition: height 0.2s linear;
|
||||
height: 480px;
|
||||
transform: translateY(-50%) translate3d(0, 0, 0);
|
||||
background-color: var(--el-color-white);
|
||||
border: 5px solid var(--el-color-primary-light-8);
|
||||
border-radius: 5px;
|
||||
overflow: hidden;
|
||||
z-index: 1;
|
||||
height: 460px;
|
||||
.login-content-main {
|
||||
margin: 0 auto;
|
||||
width: 80%;
|
||||
.login-content-title {
|
||||
color: #333;
|
||||
color: var(--el-text-color-primary);
|
||||
font-weight: 500;
|
||||
font-size: 22px;
|
||||
text-align: center;
|
||||
@ -129,6 +163,7 @@ export default {
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
transition: all ease 0.3s;
|
||||
color: var(--el-text-color-primary);
|
||||
&-delta {
|
||||
position: absolute;
|
||||
width: 35px;
|
||||
@ -142,7 +177,7 @@ export default {
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
transition: all ease 0.3s;
|
||||
color: var(--color-primary);
|
||||
color: var(--el-color-primary) !important;
|
||||
}
|
||||
i {
|
||||
width: 47px;
|
||||
@ -155,24 +190,5 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
.login-content-mobile {
|
||||
height: 418px;
|
||||
}
|
||||
.login-copyright {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
bottom: 30px;
|
||||
text-align: center;
|
||||
color: var(--color-whites);
|
||||
font-size: 12px;
|
||||
opacity: 0.8;
|
||||
.login-copyright-company {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.login-copyright-msg {
|
||||
@extend .login-copyright-company;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="system-add-dept-container">
|
||||
<el-dialog title="新增部门" v-model="isShowDialog" width="769px">
|
||||
<el-form :model="ruleForm" size="small" label-width="90px">
|
||||
<el-form :model="ruleForm" size="default" label-width="90px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-form-item label="上级部门">
|
||||
@ -59,8 +59,8 @@
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel" size="small">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" size="small">新 增</el-button>
|
||||
<el-button @click="onCancel" size="default">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" size="default">新 增</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
@ -68,11 +68,37 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { reactive, toRefs, onMounted } from 'vue';
|
||||
export default {
|
||||
import { reactive, toRefs, onMounted, defineComponent } from 'vue';
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface TableDataRow {
|
||||
deptName: string;
|
||||
createTime: string;
|
||||
status: boolean;
|
||||
sort: number;
|
||||
describe: string;
|
||||
id: number;
|
||||
children?: TableDataRow[];
|
||||
}
|
||||
interface DeptSate {
|
||||
isShowDialog: boolean;
|
||||
ruleForm: {
|
||||
deptLevel: Array<string>;
|
||||
deptName: string;
|
||||
person: string;
|
||||
phone: string | number;
|
||||
email: string;
|
||||
sort: number;
|
||||
status: boolean;
|
||||
describe: string;
|
||||
};
|
||||
deptData: Array<TableDataRow>;
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'systemAddDept',
|
||||
setup() {
|
||||
const state = reactive({
|
||||
const state = reactive<DeptSate>({
|
||||
isShowDialog: false,
|
||||
ruleForm: {
|
||||
deptLevel: [], // 上级部门
|
||||
@ -108,7 +134,7 @@ export default {
|
||||
deptName: 'vueNextAdmin',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '顶级部门',
|
||||
id: Math.random(),
|
||||
children: [
|
||||
@ -116,7 +142,7 @@ export default {
|
||||
deptName: 'IT外包服务',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '总部',
|
||||
id: Math.random(),
|
||||
},
|
||||
@ -124,7 +150,7 @@ export default {
|
||||
deptName: '资本控股',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '分部',
|
||||
id: Math.random(),
|
||||
},
|
||||
@ -143,5 +169,5 @@ export default {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="system-edit-dept-container">
|
||||
<el-dialog title="修改部门" v-model="isShowDialog" width="769px">
|
||||
<el-form :model="ruleForm" size="small" label-width="90px">
|
||||
<el-form :model="ruleForm" size="default" label-width="90px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-form-item label="上级部门">
|
||||
@ -59,8 +59,8 @@
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel" size="small">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" size="small">修 改</el-button>
|
||||
<el-button @click="onCancel" size="default">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" size="default">修 改</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
@ -68,11 +68,38 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { reactive, toRefs, onMounted } from 'vue';
|
||||
export default {
|
||||
import { reactive, toRefs, onMounted, defineComponent } from 'vue';
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface TableDataRow {
|
||||
deptName: string;
|
||||
createTime: string;
|
||||
status: boolean;
|
||||
sort: number;
|
||||
describe: string;
|
||||
id: number;
|
||||
children?: TableDataRow[];
|
||||
}
|
||||
interface RuleFormState {
|
||||
deptLevel: Array<string>;
|
||||
deptName: string;
|
||||
person: string;
|
||||
phone: string | number;
|
||||
email: string;
|
||||
sort: number;
|
||||
status: boolean;
|
||||
describe: string;
|
||||
}
|
||||
interface DeptSate {
|
||||
isShowDialog: boolean;
|
||||
ruleForm: RuleFormState;
|
||||
deptData: Array<TableDataRow>;
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'systemEditDept',
|
||||
setup() {
|
||||
const state = reactive({
|
||||
const state = reactive<DeptSate>({
|
||||
isShowDialog: false,
|
||||
ruleForm: {
|
||||
deptLevel: [], // 上级部门
|
||||
@ -87,7 +114,7 @@ export default {
|
||||
deptData: [], // 部门数据
|
||||
});
|
||||
// 打开弹窗
|
||||
const openDialog = (row: Object) => {
|
||||
const openDialog = (row: RuleFormState) => {
|
||||
row.deptLevel = ['vueNextAdmin'];
|
||||
row.person = 'lyt';
|
||||
row.phone = '12345678910';
|
||||
@ -113,7 +140,7 @@ export default {
|
||||
deptName: 'vueNextAdmin',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '顶级部门',
|
||||
id: Math.random(),
|
||||
children: [
|
||||
@ -121,7 +148,7 @@ export default {
|
||||
deptName: 'IT外包服务',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '总部',
|
||||
id: Math.random(),
|
||||
},
|
||||
@ -129,7 +156,7 @@ export default {
|
||||
deptName: '资本控股',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '分部',
|
||||
id: Math.random(),
|
||||
},
|
||||
@ -148,5 +175,5 @@ export default {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -2,16 +2,16 @@
|
||||
<div class="system-dept-container">
|
||||
<el-card shadow="hover">
|
||||
<div class="system-dept-search mb15">
|
||||
<el-input size="small" placeholder="请输入部门名称" style="max-width: 180px"> </el-input>
|
||||
<el-button size="small" type="primary" class="ml10">
|
||||
<el-input size="default" placeholder="请输入部门名称" style="max-width: 180px"> </el-input>
|
||||
<el-button size="default" type="primary" class="ml10">
|
||||
<el-icon>
|
||||
<elementSearch />
|
||||
<ele-Search />
|
||||
</el-icon>
|
||||
查询
|
||||
</el-button>
|
||||
<el-button size="small" type="success" class="ml10" @click="onOpenAddDept">
|
||||
<el-button size="default" type="success" class="ml10" @click="onOpenAddDept">
|
||||
<el-icon>
|
||||
<elementFolderAdd />
|
||||
<ele-FolderAdd />
|
||||
</el-icon>
|
||||
新增部门
|
||||
</el-button>
|
||||
@ -39,9 +39,9 @@
|
||||
<el-table-column prop="createTime" label="创建时间" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="操作" show-overflow-tooltip width="140">
|
||||
<template #default="scope">
|
||||
<el-button size="mini" type="text" @click="onOpenAddDept(scope.row)">新增</el-button>
|
||||
<el-button size="mini" type="text" @click="onOpenEditDept(scope.row)">修改</el-button>
|
||||
<el-button size="mini" type="text" @click="onTabelRowDel(scope.row)">删除</el-button>
|
||||
<el-button size="small" type="text" @click="onOpenAddDept">新增</el-button>
|
||||
<el-button size="small" type="text" @click="onOpenEditDept(scope.row)">修改</el-button>
|
||||
<el-button size="small" type="text" @click="onTabelRowDel(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@ -52,17 +52,40 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { ref, toRefs, reactive, onMounted } from 'vue';
|
||||
import { ref, toRefs, reactive, onMounted, defineComponent } from 'vue';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import AddDept from '/@/views/system/dept/component/addDept.vue';
|
||||
import EditDept from '/@/views/system/dept/component/editDept.vue';
|
||||
export default {
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface TableDataRow {
|
||||
deptName: string;
|
||||
createTime: string;
|
||||
status: boolean;
|
||||
sort: number;
|
||||
describe: string;
|
||||
id: number;
|
||||
children?: TableDataRow[];
|
||||
}
|
||||
interface TableDataState {
|
||||
tableData: {
|
||||
data: Array<TableDataRow>;
|
||||
total: number;
|
||||
loading: boolean;
|
||||
param: {
|
||||
pageNum: number;
|
||||
pageSize: number;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'systemDept',
|
||||
components: { AddDept, EditDept },
|
||||
setup() {
|
||||
const addDeptRef = ref();
|
||||
const editDeptRef = ref();
|
||||
const state = reactive({
|
||||
const state = reactive<TableDataState>({
|
||||
tableData: {
|
||||
data: [],
|
||||
total: 0,
|
||||
@ -79,7 +102,7 @@ export default {
|
||||
deptName: 'vueNextAdmin',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '顶级部门',
|
||||
id: Math.random(),
|
||||
children: [
|
||||
@ -87,7 +110,7 @@ export default {
|
||||
deptName: 'IT外包服务',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '总部',
|
||||
id: Math.random(),
|
||||
},
|
||||
@ -95,7 +118,7 @@ export default {
|
||||
deptName: '资本控股',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '分部',
|
||||
id: Math.random(),
|
||||
},
|
||||
@ -108,11 +131,11 @@ export default {
|
||||
addDeptRef.value.openDialog();
|
||||
};
|
||||
// 打开编辑菜单弹窗
|
||||
const onOpenEditDept = (row: object) => {
|
||||
const onOpenEditDept = (row: TableDataRow) => {
|
||||
editDeptRef.value.openDialog(row);
|
||||
};
|
||||
// 删除当前行
|
||||
const onTabelRowDel = (row: object) => {
|
||||
const onTabelRowDel = (row: TableDataRow) => {
|
||||
ElMessageBox.confirm(`此操作将永久删除部门:${row.deptName}, 是否继续?`, '提示', {
|
||||
confirmButtonText: '删除',
|
||||
cancelButtonText: '取消',
|
||||
@ -136,5 +159,5 @@ export default {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="system-add-dic-container">
|
||||
<el-dialog title="新增字典" v-model="isShowDialog" width="769px">
|
||||
<el-alert title="半成品,交互过于复杂,请自行扩展!" type="warning" :closable="false" class="mb20"> </el-alert>
|
||||
<el-form :model="ruleForm" size="small" label-width="90px">
|
||||
<el-form :model="ruleForm" size="default" label-width="90px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="字典名称">
|
||||
@ -24,14 +24,14 @@
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item :prop="`list[${k}].label`">
|
||||
<template #label>
|
||||
<el-button type="primary" circle size="mini" @click="onAddRow" v-if="k === 0">
|
||||
<el-button type="primary" circle size="small" @click="onAddRow" v-if="k === 0">
|
||||
<el-icon>
|
||||
<elementPlus />
|
||||
<ele-Plus />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
<el-button type="danger" circle size="mini" @click="onDelRow(k)" v-else>
|
||||
<el-button type="danger" circle size="small" @click="onDelRow(k)" v-else>
|
||||
<el-icon>
|
||||
<elementDelete />
|
||||
<ele-Delete />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
<span class="ml10">字段</span>
|
||||
@ -55,8 +55,8 @@
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel" size="small">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" size="small">新 增</el-button>
|
||||
<el-button @click="onCancel" size="default">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" size="default">新 增</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
@ -64,8 +64,8 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { reactive, toRefs } from 'vue';
|
||||
export default {
|
||||
import { reactive, toRefs, defineComponent } from 'vue';
|
||||
export default defineComponent({
|
||||
name: 'systemAddDic',
|
||||
setup() {
|
||||
const state = reactive({
|
||||
@ -111,7 +111,7 @@ export default {
|
||||
});
|
||||
};
|
||||
// 删除行
|
||||
const onDelRow = (k) => {
|
||||
const onDelRow = (k: number) => {
|
||||
state.ruleForm.list.splice(k, 1);
|
||||
};
|
||||
return {
|
||||
@ -124,5 +124,5 @@ export default {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="system-edit-dic-container">
|
||||
<el-dialog title="修改字典" v-model="isShowDialog" width="769px">
|
||||
<el-alert title="半成品,交互过于复杂,请自行扩展!" type="warning" :closable="false" class="mb20"> </el-alert>
|
||||
<el-form :model="ruleForm" size="small" label-width="90px">
|
||||
<el-form :model="ruleForm" size="default" label-width="90px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="字典名称">
|
||||
@ -24,14 +24,14 @@
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item :prop="`list[${k}].label`">
|
||||
<template #label>
|
||||
<el-button type="primary" circle size="mini" @click="onAddRow" v-if="k === 0">
|
||||
<el-button type="primary" circle size="small" @click="onAddRow" v-if="k === 0">
|
||||
<el-icon>
|
||||
<elementPlus />
|
||||
<ele-Plus />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
<el-button type="danger" circle size="mini" @click="onDelRow(k)" v-else>
|
||||
<el-button type="danger" circle size="small" @click="onDelRow(k)" v-else>
|
||||
<el-icon>
|
||||
<elementDelete />
|
||||
<ele-Delete />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
<span class="ml10">字段</span>
|
||||
@ -55,8 +55,8 @@
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel" size="small">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" size="small">修 改</el-button>
|
||||
<el-button @click="onCancel" size="default">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" size="default">修 改</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
@ -64,11 +64,31 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { reactive, toRefs } from 'vue';
|
||||
export default {
|
||||
import { reactive, toRefs, defineComponent } from 'vue';
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface RuleFormList {
|
||||
id: number;
|
||||
label: string;
|
||||
value: string;
|
||||
}
|
||||
interface RuleFormState {
|
||||
dicName: string;
|
||||
fieldName: string;
|
||||
status: boolean;
|
||||
list: RuleFormList[];
|
||||
describe: string;
|
||||
fieldNameList: Array<any>;
|
||||
}
|
||||
interface DicState {
|
||||
isShowDialog: boolean;
|
||||
ruleForm: RuleFormState;
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'systemEditDic',
|
||||
setup() {
|
||||
const state = reactive({
|
||||
const state = reactive<DicState>({
|
||||
isShowDialog: false,
|
||||
ruleForm: {
|
||||
dicName: '', // 字典名称
|
||||
@ -87,7 +107,7 @@ export default {
|
||||
},
|
||||
});
|
||||
// 打开弹窗
|
||||
const openDialog = (row: Object) => {
|
||||
const openDialog = (row: RuleFormState) => {
|
||||
if (row.fieldName === 'SYS_UERINFO') {
|
||||
row.list = [
|
||||
{ id: Math.random(), label: 'sex', value: '1' },
|
||||
@ -125,7 +145,7 @@ export default {
|
||||
});
|
||||
};
|
||||
// 删除行
|
||||
const onDelRow = (k) => {
|
||||
const onDelRow = (k: number) => {
|
||||
state.ruleForm.list.splice(k, 1);
|
||||
};
|
||||
return {
|
||||
@ -138,5 +158,5 @@ export default {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -2,16 +2,16 @@
|
||||
<div class="system-dic-container">
|
||||
<el-card shadow="hover">
|
||||
<div class="system-user-search mb15">
|
||||
<el-input size="small" placeholder="请输入字典名称" style="max-width: 180px"> </el-input>
|
||||
<el-button size="small" type="primary" class="ml10">
|
||||
<el-input size="default" placeholder="请输入字典名称" style="max-width: 180px"> </el-input>
|
||||
<el-button size="default" type="primary" class="ml10">
|
||||
<el-icon>
|
||||
<elementSearch />
|
||||
<ele-Search />
|
||||
</el-icon>
|
||||
查询
|
||||
</el-button>
|
||||
<el-button size="small" type="success" class="ml10" @click="onOpenAddDic">
|
||||
<el-button size="default" type="success" class="ml10" @click="onOpenAddDic">
|
||||
<el-icon>
|
||||
<elementFolderAdd />
|
||||
<ele-FolderAdd />
|
||||
</el-icon>
|
||||
新增字典
|
||||
</el-button>
|
||||
@ -30,8 +30,8 @@
|
||||
<el-table-column prop="createTime" label="创建时间" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="操作" width="100">
|
||||
<template #default="scope">
|
||||
<el-button size="mini" type="text" @click="onOpenEditDic(scope.row)">修改</el-button>
|
||||
<el-button size="mini" type="text" @click="onRowDel(scope.row)">删除</el-button>
|
||||
<el-button size="small" type="text" @click="onOpenEditDic(scope.row)">修改</el-button>
|
||||
<el-button size="small" type="text" @click="onRowDel(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@ -55,17 +55,38 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive, onMounted, ref } from 'vue';
|
||||
import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import AddDic from '/@/views/system/dic/component/addDic.vue';
|
||||
import EditDic from '/@/views/system/dic/component/editDic.vue';
|
||||
export default {
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface TableDataRow {
|
||||
dicName: string;
|
||||
fieldName: string;
|
||||
describe: string;
|
||||
status: boolean;
|
||||
createTime: string;
|
||||
}
|
||||
interface TableDataState {
|
||||
tableData: {
|
||||
data: Array<TableDataRow>;
|
||||
total: number;
|
||||
loading: boolean;
|
||||
param: {
|
||||
pageNum: number;
|
||||
pageSize: number;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'systemDic',
|
||||
components: { AddDic, EditDic },
|
||||
setup() {
|
||||
const addDicRef = ref();
|
||||
const editDicRef = ref();
|
||||
const state: any = reactive({
|
||||
const state = reactive<TableDataState>({
|
||||
tableData: {
|
||||
data: [],
|
||||
total: 0,
|
||||
@ -78,7 +99,7 @@ export default {
|
||||
});
|
||||
// 初始化表格数据
|
||||
const initTableData = () => {
|
||||
const data: Array<object> = [];
|
||||
const data: Array<TableDataRow> = [];
|
||||
for (let i = 0; i < 2; i++) {
|
||||
data.push({
|
||||
dicName: i === 0 ? '角色标识' : '用户性别',
|
||||
@ -96,11 +117,11 @@ export default {
|
||||
addDicRef.value.openDialog();
|
||||
};
|
||||
// 打开修改字典弹窗
|
||||
const onOpenEditDic = (row: Object) => {
|
||||
const onOpenEditDic = (row: TableDataRow) => {
|
||||
editDicRef.value.openDialog(row);
|
||||
};
|
||||
// 删除字典
|
||||
const onRowDel = (row: Object) => {
|
||||
const onRowDel = (row: TableDataRow) => {
|
||||
ElMessageBox.confirm(`此操作将永久删除字典名称:“${row.dicName}”,是否继续?`, '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
@ -134,10 +155,5 @@ export default {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.system-dic-container {
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="system-add-menu-container">
|
||||
<el-dialog title="新增菜单" v-model="isShowDialog" width="769px">
|
||||
<el-form :model="ruleForm" size="small" label-width="80px">
|
||||
<el-form :model="ruleForm" size="default" label-width="80px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-form-item label="上级菜单">
|
||||
@ -61,12 +61,7 @@
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="链接地址">
|
||||
<el-input
|
||||
v-model="ruleForm.meta.isLink"
|
||||
placeholder="外链/内嵌时链接地址(http:xxx.com)"
|
||||
clearable
|
||||
:disabled="ruleForm.isLink === '' || !ruleForm.isLink"
|
||||
>
|
||||
<el-input v-model="ruleForm.meta.isLink" placeholder="外链/内嵌时链接地址(http:xxx.com)" clearable :disabled="!ruleForm.isLink">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@ -137,8 +132,8 @@
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel" size="small">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" size="small">新 增</el-button>
|
||||
<el-button @click="onCancel" size="default">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" size="default">新 增</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
@ -146,11 +141,11 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { reactive, toRefs, onMounted } from 'vue';
|
||||
import { reactive, toRefs, onMounted, defineComponent } from 'vue';
|
||||
import { useStore } from '/@/store/index';
|
||||
import IconSelector from '/@/components/iconSelector/index.vue';
|
||||
// import { setBackEndControlRefreshRoutes } from "/@/router/backEnd";
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'systemAddMenu',
|
||||
components: { IconSelector },
|
||||
setup() {
|
||||
@ -182,9 +177,9 @@ export default {
|
||||
menuData: [], // 上级菜单数据
|
||||
});
|
||||
// 获取 vuex 中的路由
|
||||
const getMenuData = (routes) => {
|
||||
const arr = [];
|
||||
routes.map((val) => {
|
||||
const getMenuData = (routes: any) => {
|
||||
const arr: any = [];
|
||||
routes.map((val: any) => {
|
||||
val['title'] = val.meta.title;
|
||||
val['id'] = Math.random();
|
||||
arr.push({ ...val });
|
||||
@ -202,11 +197,8 @@ export default {
|
||||
};
|
||||
// 是否内嵌下拉改变
|
||||
const onSelectIframeChange = () => {
|
||||
if (state.ruleForm.meta.isIframe) {
|
||||
state.ruleForm.isLink = true;
|
||||
} else {
|
||||
state.ruleForm.isLink = '';
|
||||
}
|
||||
if (state.ruleForm.meta.isIframe) state.ruleForm.isLink = true;
|
||||
else state.ruleForm.isLink = false;
|
||||
};
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
@ -230,5 +222,5 @@ export default {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="system-edit-menu-container">
|
||||
<el-dialog title="修改菜单" v-model="isShowDialog" width="769px">
|
||||
<el-form :model="ruleForm" size="small" label-width="80px">
|
||||
<el-form :model="ruleForm" size="default" label-width="80px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-form-item label="上级菜单">
|
||||
@ -61,12 +61,7 @@
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="链接地址">
|
||||
<el-input
|
||||
v-model="ruleForm.meta.isLink"
|
||||
placeholder="外链/内嵌时链接地址(http:xxx.com)"
|
||||
clearable
|
||||
:disabled="ruleForm.isLink === '' || !ruleForm.isLink"
|
||||
>
|
||||
<el-input v-model="ruleForm.meta.isLink" placeholder="外链/内嵌时链接地址(http:xxx.com)" clearable :disabled="!ruleForm.isLink">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@ -137,8 +132,8 @@
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel" size="small">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" size="small">修 改</el-button>
|
||||
<el-button @click="onCancel" size="default">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" size="default">修 改</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
@ -146,11 +141,11 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { reactive, toRefs, onMounted } from 'vue';
|
||||
import { reactive, toRefs, onMounted, defineComponent } from 'vue';
|
||||
import { useStore } from '/@/store/index';
|
||||
import IconSelector from '/@/components/iconSelector/index.vue';
|
||||
// import { setBackEndControlRefreshRoutes } from "/@/router/backEnd";
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'systemEditMenu',
|
||||
components: { IconSelector },
|
||||
setup() {
|
||||
@ -182,9 +177,9 @@ export default {
|
||||
menuData: [], // 上级菜单数据
|
||||
});
|
||||
// 获取 vuex 中的路由
|
||||
const getMenuData = (routes) => {
|
||||
const arr = [];
|
||||
routes.map((val) => {
|
||||
const getMenuData = (routes: any) => {
|
||||
const arr: any = [];
|
||||
routes.map((val: any) => {
|
||||
val['title'] = val.meta.title;
|
||||
val['id'] = Math.random();
|
||||
arr.push({ ...val });
|
||||
@ -193,7 +188,7 @@ export default {
|
||||
return arr;
|
||||
};
|
||||
// 打开弹窗
|
||||
const openDialog = (row: Object) => {
|
||||
const openDialog = (row: any) => {
|
||||
row.menuType = 'menu';
|
||||
row.menuSort = Math.random();
|
||||
state.ruleForm = row;
|
||||
@ -205,11 +200,8 @@ export default {
|
||||
};
|
||||
// 是否内嵌下拉改变
|
||||
const onSelectIframeChange = () => {
|
||||
if (state.ruleForm.meta.isIframe) {
|
||||
state.ruleForm.isLink = true;
|
||||
} else {
|
||||
state.ruleForm.isLink = '';
|
||||
}
|
||||
if (state.ruleForm.meta.isIframe) state.ruleForm.isLink = true;
|
||||
else state.ruleForm.isLink = false;
|
||||
};
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
@ -233,5 +225,5 @@ export default {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -2,16 +2,16 @@
|
||||
<div class="system-menu-container">
|
||||
<el-card shadow="hover">
|
||||
<div class="system-menu-search mb15">
|
||||
<el-input size="small" placeholder="请输入菜单名称" style="max-width: 180px"> </el-input>
|
||||
<el-button size="small" type="primary" class="ml10">
|
||||
<el-input size="default" placeholder="请输入菜单名称" style="max-width: 180px"> </el-input>
|
||||
<el-button size="default" type="primary" class="ml10">
|
||||
<el-icon>
|
||||
<elementSearch />
|
||||
<ele-Search />
|
||||
</el-icon>
|
||||
查询
|
||||
</el-button>
|
||||
<el-button size="small" type="success" class="ml10" @click="onOpenAddMenu">
|
||||
<el-button size="default" type="success" class="ml10" @click="onOpenAddMenu">
|
||||
<el-icon>
|
||||
<elementFolderAdd />
|
||||
<ele-FolderAdd />
|
||||
</el-icon>
|
||||
新增菜单
|
||||
</el-button>
|
||||
@ -46,9 +46,9 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" show-overflow-tooltip width="140">
|
||||
<template #default="scope">
|
||||
<el-button size="mini" type="text" @click="onOpenAddMenu(scope.row)">新增</el-button>
|
||||
<el-button size="mini" type="text" @click="onOpenEditMenu(scope.row)">修改</el-button>
|
||||
<el-button size="mini" type="text" @click="onTabelRowDel(scope.row)">删除</el-button>
|
||||
<el-button size="small" type="text" @click="onOpenAddMenu">新增</el-button>
|
||||
<el-button size="small" type="text" @click="onOpenEditMenu(scope.row)">修改</el-button>
|
||||
<el-button size="small" type="text" @click="onTabelRowDel(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@ -59,12 +59,13 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { ref, toRefs, reactive, computed } from 'vue';
|
||||
import { ref, toRefs, reactive, computed, defineComponent } from 'vue';
|
||||
import { RouteRecordRaw } from 'vue-router';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import { useStore } from '/@/store/index';
|
||||
import AddMenu from '/@/views/system/menu/component/addMenu.vue';
|
||||
import EditMenu from '/@/views/system/menu/component/editMenu.vue';
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'systemMenu',
|
||||
components: { AddMenu, EditMenu },
|
||||
setup() {
|
||||
@ -81,11 +82,11 @@ export default {
|
||||
addMenuRef.value.openDialog();
|
||||
};
|
||||
// 打开编辑菜单弹窗
|
||||
const onOpenEditMenu = (row: object) => {
|
||||
const onOpenEditMenu = (row: RouteRecordRaw) => {
|
||||
editMenuRef.value.openDialog(row);
|
||||
};
|
||||
// 删除当前行
|
||||
const onTabelRowDel = (row: object) => {
|
||||
const onTabelRowDel = (row: RouteRecordRaw) => {
|
||||
ElMessageBox.confirm(`此操作将永久删除路由:${row.path}, 是否继续?`, '提示', {
|
||||
confirmButtonText: '删除',
|
||||
cancelButtonText: '取消',
|
||||
@ -106,5 +107,5 @@ export default {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="system-add-role-container">
|
||||
<el-dialog title="新增角色" v-model="isShowDialog" width="769px">
|
||||
<el-form :model="ruleForm" size="small" label-width="90px">
|
||||
<el-form :model="ruleForm" size="default" label-width="90px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="角色名称">
|
||||
@ -42,8 +42,8 @@
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel" size="small">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" size="small">新 增</el-button>
|
||||
<el-button @click="onCancel" size="default">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" size="default">新 增</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
@ -51,11 +51,34 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { reactive, toRefs } from 'vue';
|
||||
export default {
|
||||
import { reactive, toRefs, defineComponent } from 'vue';
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface MenuDataTree {
|
||||
id: number;
|
||||
label: string;
|
||||
children?: MenuDataTree[];
|
||||
}
|
||||
interface RoleState {
|
||||
isShowDialog: boolean;
|
||||
ruleForm: {
|
||||
roleName: string;
|
||||
roleSign: string;
|
||||
sort: number;
|
||||
status: boolean;
|
||||
describe: string;
|
||||
};
|
||||
menuData: Array<MenuDataTree>;
|
||||
menuProps: {
|
||||
children: string;
|
||||
label: string;
|
||||
};
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'systemAddRole',
|
||||
setup() {
|
||||
const state = reactive({
|
||||
const state = reactive<RoleState>({
|
||||
isShowDialog: false,
|
||||
ruleForm: {
|
||||
roleName: '', // 角色名称
|
||||
@ -202,7 +225,7 @@ export default {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="system-edit-role-container">
|
||||
<el-dialog title="修改角色" v-model="isShowDialog" width="769px">
|
||||
<el-form :model="ruleForm" size="small" label-width="90px">
|
||||
<el-form :model="ruleForm" size="default" label-width="90px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="角色名称">
|
||||
@ -42,8 +42,8 @@
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel" size="small">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" size="small">修 改</el-button>
|
||||
<el-button @click="onCancel" size="default">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" size="default">修 改</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
@ -51,11 +51,35 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { reactive, toRefs } from 'vue';
|
||||
export default {
|
||||
import { reactive, toRefs, defineComponent } from 'vue';
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface MenuDataTree {
|
||||
id: number;
|
||||
label: string;
|
||||
children?: MenuDataTree[];
|
||||
}
|
||||
interface DialogRow {
|
||||
roleName: string;
|
||||
roleSign: string;
|
||||
sort: number;
|
||||
status: boolean;
|
||||
describe: string;
|
||||
}
|
||||
interface RoleState {
|
||||
isShowDialog: boolean;
|
||||
ruleForm: DialogRow;
|
||||
menuData: Array<MenuDataTree>;
|
||||
menuProps: {
|
||||
children: string;
|
||||
label: string;
|
||||
};
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'systemEditRole',
|
||||
setup() {
|
||||
const state = reactive({
|
||||
const state = reactive<RoleState>({
|
||||
isShowDialog: false,
|
||||
ruleForm: {
|
||||
roleName: '', // 角色名称
|
||||
@ -71,7 +95,7 @@ export default {
|
||||
},
|
||||
});
|
||||
// 打开弹窗
|
||||
const openDialog = (row: Object) => {
|
||||
const openDialog = (row: DialogRow) => {
|
||||
state.ruleForm = row;
|
||||
state.isShowDialog = true;
|
||||
getMenuData();
|
||||
@ -203,7 +227,7 @@ export default {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@ -2,22 +2,22 @@
|
||||
<div class="system-role-container">
|
||||
<el-card shadow="hover">
|
||||
<div class="system-user-search mb15">
|
||||
<el-input size="small" placeholder="请输入角色名称" style="max-width: 180px"> </el-input>
|
||||
<el-button size="small" type="primary" class="ml10">
|
||||
<el-input size="default" placeholder="请输入角色名称" style="max-width: 180px"> </el-input>
|
||||
<el-button size="default" type="primary" class="ml10">
|
||||
<el-icon>
|
||||
<elementSearch />
|
||||
<ele-Search />
|
||||
</el-icon>
|
||||
查询
|
||||
</el-button>
|
||||
<el-button size="small" type="success" class="ml10" @click="onOpenAddRole">
|
||||
<el-button size="default" type="success" class="ml10" @click="onOpenAddRole">
|
||||
<el-icon>
|
||||
<elementFolderAdd />
|
||||
<ele-FolderAdd />
|
||||
</el-icon>
|
||||
新增角色
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table :data="tableData.data" style="width: 100%">
|
||||
<el-table-column type="index" label="序号" width="50" />
|
||||
<el-table-column type="index" label="序号" width="60" />
|
||||
<el-table-column prop="roleName" label="角色名称" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="roleSign" label="角色标识" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="sort" label="排序" show-overflow-tooltip></el-table-column>
|
||||
@ -31,8 +31,8 @@
|
||||
<el-table-column prop="createTime" label="创建时间" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="操作" width="100">
|
||||
<template #default="scope">
|
||||
<el-button :disabled="scope.row.roleName === '超级管理员'" size="mini" type="text" @click="onOpenEditRole(scope.row)">修改</el-button>
|
||||
<el-button :disabled="scope.row.roleName === '超级管理员'" size="mini" type="text" @click="onRowDel(scope.row)">删除</el-button>
|
||||
<el-button :disabled="scope.row.roleName === '超级管理员'" size="small" type="text" @click="onOpenEditRole(scope.row)">修改</el-button>
|
||||
<el-button :disabled="scope.row.roleName === '超级管理员'" size="small" type="text" @click="onRowDel(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@ -56,17 +56,39 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive, onMounted, ref } from 'vue';
|
||||
import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import AddRole from '/@/views/system/role/component/addRole.vue';
|
||||
import EditRole from '/@/views/system/role/component/editRole.vue';
|
||||
export default {
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface TableData {
|
||||
roleName: string;
|
||||
roleSign: string;
|
||||
describe: string;
|
||||
sort: number;
|
||||
status: boolean;
|
||||
createTime: string;
|
||||
}
|
||||
interface TableDataState {
|
||||
tableData: {
|
||||
data: Array<TableData>;
|
||||
total: number;
|
||||
loading: boolean;
|
||||
param: {
|
||||
pageNum: number;
|
||||
pageSize: number;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'systemRole',
|
||||
components: { AddRole, EditRole },
|
||||
setup() {
|
||||
const addRoleRef = ref();
|
||||
const editRoleRef = ref();
|
||||
const state: any = reactive({
|
||||
const state = reactive<TableDataState>({
|
||||
tableData: {
|
||||
data: [],
|
||||
total: 0,
|
||||
@ -79,7 +101,7 @@ export default {
|
||||
});
|
||||
// 初始化表格数据
|
||||
const initTableData = () => {
|
||||
const data: Array<object> = [];
|
||||
const data: Array<TableData> = [];
|
||||
for (let i = 0; i < 2; i++) {
|
||||
data.push({
|
||||
roleName: i === 0 ? '超级管理员' : '普通用户',
|
||||
@ -102,7 +124,7 @@ export default {
|
||||
editRoleRef.value.openDialog(row);
|
||||
};
|
||||
// 删除角色
|
||||
const onRowDel = (row: Object) => {
|
||||
const onRowDel = (row: any) => {
|
||||
ElMessageBox.confirm(`此操作将永久删除角色名称:“${row.roleName}”,是否继续?`, '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
@ -136,10 +158,5 @@ export default {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.system-role-container {
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="system-add-user-container">
|
||||
<el-dialog title="新增用户" v-model="isShowDialog" width="769px">
|
||||
<el-form :model="ruleForm" size="small" label-width="90px">
|
||||
<el-form :model="ruleForm" size="default" label-width="90px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="账户名称">
|
||||
@ -80,8 +80,8 @@
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel" size="small">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" size="small">新 增</el-button>
|
||||
<el-button @click="onCancel" size="default">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" size="default">新 增</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
@ -89,11 +89,40 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { reactive, toRefs, onMounted } from 'vue';
|
||||
export default {
|
||||
import { reactive, toRefs, onMounted, defineComponent } from 'vue';
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface DeptData {
|
||||
deptName: string;
|
||||
createTime: string;
|
||||
status: boolean;
|
||||
sort: number | string;
|
||||
describe: string;
|
||||
id: number;
|
||||
children?: DeptData[];
|
||||
}
|
||||
interface UserState {
|
||||
isShowDialog: boolean;
|
||||
ruleForm: {
|
||||
userName: string;
|
||||
userNickname: string;
|
||||
roleSign: string;
|
||||
department: any;
|
||||
phone: string;
|
||||
email: string;
|
||||
sex: string;
|
||||
password: string;
|
||||
overdueTime: string;
|
||||
status: boolean;
|
||||
describe: string;
|
||||
};
|
||||
deptData: Array<DeptData>;
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'systemAddUser',
|
||||
setup() {
|
||||
const state = reactive({
|
||||
const state = reactive<UserState>({
|
||||
isShowDialog: false,
|
||||
ruleForm: {
|
||||
userName: '', // 账户名称
|
||||
@ -132,7 +161,7 @@ export default {
|
||||
deptName: 'vueNextAdmin',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '顶级部门',
|
||||
id: Math.random(),
|
||||
children: [
|
||||
@ -140,7 +169,7 @@ export default {
|
||||
deptName: 'IT外包服务',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '总部',
|
||||
id: Math.random(),
|
||||
},
|
||||
@ -148,7 +177,7 @@ export default {
|
||||
deptName: '资本控股',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '分部',
|
||||
id: Math.random(),
|
||||
},
|
||||
@ -167,5 +196,5 @@ export default {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="system-edit-user-container">
|
||||
<el-dialog title="修改用户" v-model="isShowDialog" width="769px">
|
||||
<el-form :model="ruleForm" size="small" label-width="90px">
|
||||
<el-form :model="ruleForm" size="default" label-width="90px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="账户名称">
|
||||
@ -80,8 +80,8 @@
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel" size="small">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" size="small">修 改</el-button>
|
||||
<el-button @click="onCancel" size="default">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" size="default">修 改</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
@ -89,11 +89,41 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { reactive, toRefs, onMounted } from 'vue';
|
||||
export default {
|
||||
import { reactive, toRefs, onMounted, defineComponent } from 'vue';
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface DeptData {
|
||||
deptName: string;
|
||||
createTime: string;
|
||||
status: boolean;
|
||||
sort: number | string;
|
||||
describe: string;
|
||||
id: number;
|
||||
children?: DeptData[];
|
||||
}
|
||||
interface RuleFormRow {
|
||||
userName: string;
|
||||
userNickname: string;
|
||||
roleSign: string;
|
||||
department: any;
|
||||
phone: string;
|
||||
email: string;
|
||||
sex: string;
|
||||
password: string;
|
||||
overdueTime: string;
|
||||
status: boolean;
|
||||
describe: string;
|
||||
}
|
||||
interface UserState {
|
||||
isShowDialog: boolean;
|
||||
ruleForm: RuleFormRow;
|
||||
deptData: Array<DeptData>;
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'systemEditUser',
|
||||
setup() {
|
||||
const state = reactive({
|
||||
const state = reactive<UserState>({
|
||||
isShowDialog: false,
|
||||
ruleForm: {
|
||||
userName: '', // 账户名称
|
||||
@ -111,7 +141,7 @@ export default {
|
||||
deptData: [], // 部门数据
|
||||
});
|
||||
// 打开弹窗
|
||||
const openDialog = (row: Object) => {
|
||||
const openDialog = (row: RuleFormRow) => {
|
||||
state.ruleForm = row;
|
||||
state.isShowDialog = true;
|
||||
};
|
||||
@ -133,7 +163,7 @@ export default {
|
||||
deptName: 'vueNextAdmin',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '顶级部门',
|
||||
id: Math.random(),
|
||||
children: [
|
||||
@ -141,7 +171,7 @@ export default {
|
||||
deptName: 'IT外包服务',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '总部',
|
||||
id: Math.random(),
|
||||
},
|
||||
@ -149,7 +179,7 @@ export default {
|
||||
deptName: '资本控股',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '分部',
|
||||
id: Math.random(),
|
||||
},
|
||||
@ -168,5 +198,5 @@ export default {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -2,22 +2,22 @@
|
||||
<div class="system-user-container">
|
||||
<el-card shadow="hover">
|
||||
<div class="system-user-search mb15">
|
||||
<el-input size="small" placeholder="请输入用户名称" style="max-width: 180px"> </el-input>
|
||||
<el-button size="small" type="primary" class="ml10">
|
||||
<el-input size="default" placeholder="请输入用户名称" style="max-width: 180px"> </el-input>
|
||||
<el-button size="default" type="primary" class="ml10">
|
||||
<el-icon>
|
||||
<elementSearch />
|
||||
<ele-Search />
|
||||
</el-icon>
|
||||
查询
|
||||
</el-button>
|
||||
<el-button size="small" type="success" class="ml10" @click="onOpenAddUser">
|
||||
<el-button size="default" type="success" class="ml10" @click="onOpenAddUser">
|
||||
<el-icon>
|
||||
<elementFolderAdd />
|
||||
<ele-FolderAdd />
|
||||
</el-icon>
|
||||
新增用户
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table :data="tableData.data" style="width: 100%">
|
||||
<el-table-column type="index" label="序号" width="50" />
|
||||
<el-table-column type="index" label="序号" width="60" />
|
||||
<el-table-column prop="userName" label="账户名称" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="userNickname" label="用户昵称" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="roleSign" label="关联角色" show-overflow-tooltip></el-table-column>
|
||||
@ -34,8 +34,8 @@
|
||||
<el-table-column prop="createTime" label="创建时间" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="操作" width="100">
|
||||
<template #default="scope">
|
||||
<el-button :disabled="scope.row.userName === 'admin'" size="mini" type="text" @click="onOpenEditUser(scope.row)">修改</el-button>
|
||||
<el-button :disabled="scope.row.userName === 'admin'" size="mini" type="text" @click="onRowDel(scope.row)">删除</el-button>
|
||||
<el-button :disabled="scope.row.userName === 'admin'" size="small" type="text" @click="onOpenEditUser(scope.row)">修改</el-button>
|
||||
<el-button :disabled="scope.row.userName === 'admin'" size="small" type="text" @click="onRowDel(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@ -59,17 +59,45 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive, onMounted, ref } from 'vue';
|
||||
import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import AddUer from '/@/views/system/user/component/addUser.vue';
|
||||
import EditUser from '/@/views/system/user/component/editUser.vue';
|
||||
export default {
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface TableDataRow {
|
||||
userName: string;
|
||||
userNickname: string;
|
||||
roleSign: string;
|
||||
department: string[];
|
||||
phone: string;
|
||||
email: string;
|
||||
sex: string;
|
||||
password: string;
|
||||
overdueTime: Date;
|
||||
status: boolean;
|
||||
describe: string;
|
||||
createTime: string;
|
||||
}
|
||||
interface TableDataState {
|
||||
tableData: {
|
||||
data: Array<TableDataRow>;
|
||||
total: number;
|
||||
loading: boolean;
|
||||
param: {
|
||||
pageNum: number;
|
||||
pageSize: number;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'systemUser',
|
||||
components: { AddUer, EditUser },
|
||||
setup() {
|
||||
const addUserRef = ref();
|
||||
const editUserRef = ref();
|
||||
const state: any = reactive({
|
||||
const state = reactive<TableDataState>({
|
||||
tableData: {
|
||||
data: [],
|
||||
total: 0,
|
||||
@ -82,7 +110,7 @@ export default {
|
||||
});
|
||||
// 初始化表格数据
|
||||
const initTableData = () => {
|
||||
const data: Array<object> = [];
|
||||
const data: Array<TableDataRow> = [];
|
||||
for (let i = 0; i < 2; i++) {
|
||||
data.push({
|
||||
userName: i === 0 ? 'admin' : 'test',
|
||||
@ -107,11 +135,11 @@ export default {
|
||||
addUserRef.value.openDialog();
|
||||
};
|
||||
// 打开修改用户弹窗
|
||||
const onOpenEditUser = (row: Object) => {
|
||||
const onOpenEditUser = (row: TableDataRow) => {
|
||||
editUserRef.value.openDialog(row);
|
||||
};
|
||||
// 删除用户
|
||||
const onRowDel = (row: Object) => {
|
||||
const onRowDel = (row: TableDataRow) => {
|
||||
ElMessageBox.confirm(`此操作将永久删除账户名称:“${row.userName}”,是否继续?`, '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
@ -145,10 +173,5 @@ export default {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.system-user-container {
|
||||
}
|
||||
</style>
|
||||
|
||||
108
vite.config.ts
108
vite.config.ts
@ -1,65 +1,79 @@
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
import { resolve } from 'path';
|
||||
import type { UserConfig } from 'vite';
|
||||
import { loadEnv } from './src/utils/viteBuild';
|
||||
import { defineConfig, loadEnv, ConfigEnv } from 'vite';
|
||||
|
||||
const pathResolve = (dir: string): any => {
|
||||
return resolve(__dirname, '.', dir);
|
||||
};
|
||||
|
||||
const { VITE_PORT, VITE_OPEN, VITE_PUBLIC_PATH } = loadEnv();
|
||||
|
||||
const alias: Record<string, string> = {
|
||||
'/@': pathResolve('./src/'),
|
||||
};
|
||||
|
||||
const viteConfig: UserConfig = {
|
||||
plugins: [vue()],
|
||||
root: process.cwd(),
|
||||
resolve: { alias },
|
||||
base: process.env.NODE_ENV === 'production' ? VITE_PUBLIC_PATH : './',
|
||||
server: {
|
||||
host: '0.0.0.0',
|
||||
port: VITE_PORT,
|
||||
open: VITE_OPEN,
|
||||
proxy: {
|
||||
'/gitee': {
|
||||
target: 'https://gitee.com',
|
||||
ws: true,
|
||||
changeOrigin: true,
|
||||
rewrite: (path) => path.replace(/^\/gitee/, ''),
|
||||
const viteConfig = defineConfig((mode: ConfigEnv) => {
|
||||
const env = loadEnv(mode.mode, process.cwd());
|
||||
return {
|
||||
plugins: [vue()],
|
||||
root: process.cwd(),
|
||||
resolve: { alias },
|
||||
base: mode.command === 'serve' ? './' : env.VITE_PUBLIC_PATH,
|
||||
server: {
|
||||
host: '0.0.0.0',
|
||||
port: env.VITE_PORT as unknown as number,
|
||||
open: env.VITE_OPEN,
|
||||
proxy: {
|
||||
'/gitee': {
|
||||
target: 'https://gitee.com',
|
||||
ws: true,
|
||||
changeOrigin: true,
|
||||
rewrite: (path) => path.replace(/^\/gitee/, ''),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
build: {
|
||||
outDir: 'dist',
|
||||
minify: 'esbuild',
|
||||
sourcemap: false,
|
||||
chunkSizeWarningLimit: 1500,
|
||||
rollupOptions: {
|
||||
output: {
|
||||
entryFileNames: `assets/[name].${new Date().getTime()}.js`,
|
||||
chunkFileNames: `assets/[name].${new Date().getTime()}.js`,
|
||||
assetFileNames: `assets/[name].${new Date().getTime()}.[ext]`,
|
||||
},
|
||||
},
|
||||
},
|
||||
css: {
|
||||
postcss: {
|
||||
plugins: [
|
||||
{
|
||||
postcssPlugin: 'internal:charset-removal',
|
||||
AtRule: {
|
||||
charset: (atRule) => {
|
||||
if (atRule.name === 'charset') {
|
||||
atRule.remove();
|
||||
}
|
||||
},
|
||||
build: {
|
||||
outDir: 'dist',
|
||||
sourcemap: false,
|
||||
chunkSizeWarningLimit: 1500,
|
||||
rollupOptions: {
|
||||
output: {
|
||||
entryFileNames: `assets/[name].${new Date().getTime()}.js`,
|
||||
chunkFileNames: `assets/[name].${new Date().getTime()}.js`,
|
||||
assetFileNames: `assets/[name].${new Date().getTime()}.[ext]`,
|
||||
compact: true,
|
||||
manualChunks: {
|
||||
vue: ['vue', 'vue-router', 'vuex'],
|
||||
echarts: ['echarts'],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
terserOptions: {
|
||||
compress: {
|
||||
drop_console: true,
|
||||
drop_debugger: true,
|
||||
},
|
||||
ie8: true,
|
||||
output: {
|
||||
comments: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
css: {
|
||||
postcss: {
|
||||
plugins: [
|
||||
{
|
||||
postcssPlugin: 'internal:charset-removal',
|
||||
AtRule: {
|
||||
charset: (atRule) => {
|
||||
if (atRule.name === 'charset') {
|
||||
atRule.remove();
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export default viteConfig;
|
||||
|
||||
Reference in New Issue
Block a user