Forráskód Böngészése

样式调整,菜单对接

zhangchong 2 éve
szülő
commit
e96e0cca28
90 módosított fájl, 977 hozzáadás és 395 törlés
  1. 11 3
      index.html
  2. BIN
      public/favicon.ico
  3. BIN
      public/favicon1.ico
  4. 25 7
      src/App.vue
  5. 1 1
      src/api/callCenter/blacklist.ts
  6. 2 2
      src/api/callCenter/tels.ts
  7. 8 1
      src/api/login/index.ts
  8. 0 26
      src/api/menu/index.ts
  9. 38 0
      src/api/system/menu.ts
  10. BIN
      src/assets/images/login/bg.png
  11. BIN
      src/assets/images/logo.png
  12. BIN
      src/assets/images/logoMini.png
  13. BIN
      src/assets/images/phoneControls/active.png
  14. BIN
      src/assets/images/phoneControls/baochi_blue.png
  15. BIN
      src/assets/images/phoneControls/baochi_grey.png
  16. BIN
      src/assets/images/phoneControls/baochi_white.png
  17. BIN
      src/assets/images/phoneControls/guaduan_blue.png
  18. BIN
      src/assets/images/phoneControls/guaduan_grey.png
  19. BIN
      src/assets/images/phoneControls/guaduan_white.png
  20. BIN
      src/assets/images/phoneControls/hujiaozhuanyi_blue.png
  21. BIN
      src/assets/images/phoneControls/hujiaozhuanyi_grey.png
  22. BIN
      src/assets/images/phoneControls/hujiaozhuanyi_white.png
  23. BIN
      src/assets/images/phoneControls/jingyin_blue.png
  24. BIN
      src/assets/images/phoneControls/jingyin_grey.png
  25. BIN
      src/assets/images/phoneControls/jingyin_white.png
  26. BIN
      src/assets/images/phoneControls/pingjia_blue.png
  27. BIN
      src/assets/images/phoneControls/pingjia_grey.png
  28. BIN
      src/assets/images/phoneControls/pingjia_white.png
  29. BIN
      src/assets/images/phoneControls/qianchu_blue.png
  30. BIN
      src/assets/images/phoneControls/qianru_white.png
  31. BIN
      src/assets/images/phoneControls/qinaru_grey.png
  32. BIN
      src/assets/images/phoneControls/sanfang_blue.png
  33. BIN
      src/assets/images/phoneControls/sanfang_grey.png
  34. BIN
      src/assets/images/phoneControls/sanfang_white.png
  35. BIN
      src/assets/images/phoneControls/waihu_blue.png
  36. BIN
      src/assets/images/phoneControls/waihu_grey.png
  37. BIN
      src/assets/images/phoneControls/waihu_white.png
  38. BIN
      src/assets/images/phoneControls/xiaoxiu_blue.png
  39. BIN
      src/assets/images/phoneControls/xiaoxiu_grey.png
  40. BIN
      src/assets/images/phoneControls/xiaoxiu_white.png
  41. BIN
      src/assets/images/phoneControls/zhuanjie_blue.png
  42. BIN
      src/assets/images/phoneControls/zhuanjie_grey.png
  43. BIN
      src/assets/images/phoneControls/zhuanjie_white.png
  44. BIN
      src/assets/images/phoneControls/组 3(1).png
  45. BIN
      src/assets/images/phoneControls/组 3(2).png
  46. BIN
      src/assets/images/phoneControls/组 3(3).png
  47. BIN
      src/assets/images/phoneControls/组 3.png
  48. 1 1
      src/components/iconSelector/index.vue
  49. 9 1
      src/layout/component/header.vue
  50. 16 13
      src/layout/logo/index.vue
  51. 6 4
      src/layout/navBars/breadcrumb/breadcrumb.vue
  52. 13 4
      src/layout/navBars/breadcrumb/index.vue
  53. 181 0
      src/layout/navBars/breadcrumb/phoneControls.vue
  54. 14 7
      src/layout/navBars/breadcrumb/user.vue
  55. 26 5
      src/layout/navBars/tagsView/tagsView.vue
  56. 2 1
      src/main.ts
  57. 41 23
      src/router/backEnd.ts
  58. 3 9
      src/router/frontEnd.ts
  59. 1 0
      src/router/index.ts
  60. 16 32
      src/router/route.ts
  61. 5 5
      src/stores/themeConfig.ts
  62. 19 11
      src/stores/userInfo.ts
  63. 2 2
      src/stores/userState.ts
  64. 13 2
      src/theme/app.scss
  65. 9 0
      src/theme/element.scss
  66. 1 1
      src/theme/icon/iconfont.json
  67. 1 1
      src/theme/iconfont/iconfont.json
  68. 10 1
      src/theme/media/login.scss
  69. 10 10
      src/utils/appConfig.ts
  70. 6 6
      src/utils/formatTime.ts
  71. 19 16
      src/utils/getStyleSheets.ts
  72. 1 0
      src/utils/other.ts
  73. 1 3
      src/utils/request.ts
  74. 9 1
      src/utils/setIconfont.ts
  75. 2 2
      src/views/callCenter/blacklist/index.vue
  76. 3 3
      src/views/callCenter/callRecord/index.vue
  77. 6 6
      src/views/callCenter/iverConfig/details.vue
  78. 1 3
      src/views/callCenter/iverConfig/index.vue
  79. 8 8
      src/views/callCenter/iverConfig/ivrList.vue
  80. 4 4
      src/views/callCenter/systemParameter/index.vue
  81. 2 2
      src/views/callCenter/tels/index.vue
  82. 3 3
      src/views/callCenter/telsGroup/index.vue
  83. 6 5
      src/views/home/index.vue
  84. 65 28
      src/views/login/component/account.vue
  85. 293 0
      src/views/login/component/changePwd.vue
  86. 16 70
      src/views/login/index.vue
  87. 11 9
      src/views/system/menu/component/addMenu.vue
  88. 4 4
      src/views/system/menu/component/editMenu.vue
  89. 31 47
      src/views/system/menu/index.vue
  90. 2 2
      src/views/system/user/index.vue

+ 11 - 3
index.html

@@ -1,13 +1,21 @@
+<!--
+ * @Author: zc
+ * @Description: 
+ * @version: 
+ * @Date: 2022-10-21 09:01:23
+ * @LastEditors: 
+ * @LastEditTime: 2022-11-09 14:24:15
+-->
 <!DOCTYPE html>
 <html lang="zh-CN">
 	<head>
 		<meta charset="utf-8" />
 		<meta http-equiv="X-UA-Compatible" content="IE=edge" />
 		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
-		<meta name="keywords" content="呼叫中心" />
-		<meta name="description" content="呼叫中心" />
+		<meta name="keywords" content="12345" />
+		<meta name="description" content="12345" />
 		<link rel="icon" href="/favicon.ico" />
-		<title>呼叫中心</title>
+		<title>12345</title>
 	</head>
 	<body>
 		<div id="app"></div>

BIN
public/favicon.ico


BIN
public/favicon1.ico


+ 25 - 7
src/App.vue

@@ -1,5 +1,13 @@
+<!--
+ * @Author: zc
+ * @Description: 
+ * @version: 
+ * @Date: 2022-10-21 09:01:22
+ * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-11-08 11:29:55
+-->
 <template>
-	<el-config-provider :size="getGlobalComponentSize" :locale="zhCn">
+	<el-config-provider :size="getGlobalComponentSize" :locale="zhCn" :message="messageConfig" :button="buttonConfig">
 		<router-view v-show="themeConfig.lockScreenTime > 1" />
 		<LockScreen v-if="themeConfig.isLockScreen" />
 		<Setings ref="setingsRef" v-show="themeConfig.lockScreenTime > 1" />
@@ -8,14 +16,14 @@
 </template>
 
 <script lang="ts">
-import { computed, ref, getCurrentInstance, onBeforeMount, onMounted, onUnmounted, nextTick, defineComponent, watch } from 'vue';
+import { computed, ref, getCurrentInstance, onBeforeMount, onMounted, onUnmounted, nextTick, defineComponent, watch, reactive} from 'vue';
 import { useRoute } from 'vue-router';
 import zhCn from 'element-plus/es/locale/lang/zh-cn';
 import { storeToRefs } from 'pinia';
 import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes';
 import { useThemeConfig } from '/@/stores/themeConfig';
 import other from '/@/utils/other';
-import { Local, Session } from '/@/utils/storage';
+import { Session } from '/@/utils/storage';
 import setIntroduction from '/@/utils/setIconfont';
 import LockScreen from '/@/layout/lockScreen/index.vue';
 import Setings from '/@/layout/navBars/breadcrumb/setings.vue';
@@ -30,6 +38,14 @@ export default defineComponent({
 		const stores = useTagsViewRoutes();
 		const storesThemeConfig = useThemeConfig();
 		const { themeConfig } = storeToRefs(storesThemeConfig);
+		// 可同时显示的消息最大数量
+		const messageConfig = reactive({
+			max: 3,
+		})
+		// 自动在两个中文字符之间插入空格
+		const buttonConfig = reactive({ 
+			autoInsertSpace: false,
+		})
 		// 获取全局组件大小
 		const getGlobalComponentSize = computed(() => {
 			return other.globalComponentSize();
@@ -54,10 +70,10 @@ export default defineComponent({
 				});
 				
 				// 获取缓存中的布局配置
-				if (Local.get('themeConfig')) {
-					storesThemeConfig.setThemeConfig(Local.get('themeConfig'));
-					document.documentElement.style.cssText = Local.get('themeConfigStyle');
-				}
+				// if (Local.get('themeConfig')) {
+				// 	storesThemeConfig.setThemeConfig(Local.get('themeConfig'));
+				// 	document.documentElement.style.cssText = Local.get('themeConfigStyle');
+				// }
 				// 获取缓存中的全屏配置
 				if (Session.get('isTagsViewCurrenFull')) {
 					stores.setCurrenFullscreen(Session.get('isTagsViewCurrenFull'));
@@ -83,6 +99,8 @@ export default defineComponent({
 			themeConfig,
 			setingsRef,
 			getGlobalComponentSize,
+			messageConfig,
+			buttonConfig
 		};
 	},
 });

+ 1 - 1
src/api/callCenter/blacklist.ts

@@ -1,6 +1,6 @@
 /*
  * @Author: zc
- * @Description: 通话记录
+ * @Description: 黑名单
  * @version: 
  * @Date: 2022-08-26 14:43:12
  * @LastEditors: Please set LastEditors

+ 2 - 2
src/api/callCenter/tels.ts

@@ -4,7 +4,7 @@
  * @version: 
  * @Date: 2022-08-26 14:43:12
  * @LastEditors: Please set LastEditors
- * @LastEditTime: 2022-09-20 17:57:05
+ * @LastEditTime: 2022-11-09 17:28:20
  */
 import request from '/@/utils/request';
 
@@ -15,7 +15,7 @@ import request from '/@/utils/request';
  */
 export const getTelsList = (params?: object) => {
 	return request({
-		url: '/api/v1/Tel/tels',
+		url: '/api/v1/Tel/tels-frequency',
 		method: 'get',
 		params: params,
 	});

+ 8 - 1
src/api/login/index.ts

@@ -4,7 +4,7 @@
  * @version: 
  * @Date: 2022-08-09 16:19:55
  * @LastEditors: Please set LastEditors
- * @LastEditTime: 2022-10-26 17:35:40
+ * @LastEditTime: 2022-11-08 15:39:38
  */
 import request from '/@/utils/request';
 //  全局配置
@@ -38,3 +38,10 @@ export function signOut(params: object){
 		baseURL:appConfig.identityUrl // 请求地址  可以在不同url中修改
 	});
 }
+
+export function pwdCheck(){ //密码修改状态 未修改直接跳转到修改密码页面  不进入系统
+	return request({
+		url: '/api/v1/User/pwd-changed',
+		method: 'get',
+	});
+}

+ 0 - 26
src/api/menu/index.ts

@@ -1,26 +0,0 @@
-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)
- */
-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
-			});
-		},
-	};
-}

+ 38 - 0
src/api/system/menu.ts

@@ -0,0 +1,38 @@
+/*
+ * @Author: zc
+ * @Description: 菜单配置 和获取菜单
+ * @version: 
+ * @Date: 2022-10-21 09:01:22
+ * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-11-09 17:03:01
+ */
+import request from '/@/utils/request';
+/**
+ * 后端控制菜单模拟json,路径在 https://gitee.com/lyt-top/vue-next-admin-images/tree/master/menu
+ * 后端控制路由,isRequestRoutes 为 true,则开启后端控制路由
+ * @method getMenu 获取后端动态路由菜单(admin)
+ */
+/**
+ * @description: 获取当前用户下的菜单
+ * @param {object} params
+ * @return {*}
+ */
+export const getMenu = (params?: object) => {
+	return request({
+		url: '/api/v1/Home/get-my-auth-menu',
+		method: 'get',
+		params,
+	});
+};
+/**
+ * @description: 获取所有菜单列表
+ * @param {object} params
+ * @return {*}
+ */
+export const getMenuList = (params?: object) => {
+	return request({
+		url: '/api/v1/Sys/getmenujson',
+		method: 'get',
+		params
+	});
+};

BIN
src/assets/images/login/bg.png


BIN
src/assets/images/logo.png


BIN
src/assets/images/logoMini.png


BIN
src/assets/images/phoneControls/active.png


BIN
src/assets/images/phoneControls/baochi_blue.png


BIN
src/assets/images/phoneControls/baochi_grey.png


BIN
src/assets/images/phoneControls/baochi_white.png


BIN
src/assets/images/phoneControls/guaduan_blue.png


BIN
src/assets/images/phoneControls/guaduan_grey.png


BIN
src/assets/images/phoneControls/guaduan_white.png


BIN
src/assets/images/phoneControls/hujiaozhuanyi_blue.png


BIN
src/assets/images/phoneControls/hujiaozhuanyi_grey.png


BIN
src/assets/images/phoneControls/hujiaozhuanyi_white.png


BIN
src/assets/images/phoneControls/jingyin_blue.png


BIN
src/assets/images/phoneControls/jingyin_grey.png


BIN
src/assets/images/phoneControls/jingyin_white.png


BIN
src/assets/images/phoneControls/pingjia_blue.png


BIN
src/assets/images/phoneControls/pingjia_grey.png


BIN
src/assets/images/phoneControls/pingjia_white.png


BIN
src/assets/images/phoneControls/qianchu_blue.png


BIN
src/assets/images/phoneControls/qianru_white.png


BIN
src/assets/images/phoneControls/qinaru_grey.png


BIN
src/assets/images/phoneControls/sanfang_blue.png


BIN
src/assets/images/phoneControls/sanfang_grey.png


BIN
src/assets/images/phoneControls/sanfang_white.png


BIN
src/assets/images/phoneControls/waihu_blue.png


BIN
src/assets/images/phoneControls/waihu_grey.png


BIN
src/assets/images/phoneControls/waihu_white.png


BIN
src/assets/images/phoneControls/xiaoxiu_blue.png


BIN
src/assets/images/phoneControls/xiaoxiu_grey.png


BIN
src/assets/images/phoneControls/xiaoxiu_white.png


BIN
src/assets/images/phoneControls/zhuanjie_blue.png


BIN
src/assets/images/phoneControls/zhuanjie_grey.png


BIN
src/assets/images/phoneControls/zhuanjie_white.png


BIN
src/assets/images/phoneControls/组 3(1).png


BIN
src/assets/images/phoneControls/组 3(2).png


BIN
src/assets/images/phoneControls/组 3(3).png


BIN
src/assets/images/phoneControls/组 3.png


+ 1 - 1
src/components/iconSelector/index.vue

@@ -37,7 +37,7 @@
 						<div class="icon-selector-warp-title-tab" v-if="type === 'all'">
 							<span :class="{ 'span-active': fontIconType === 'ali' }" @click="onIconChange('ali')" class="ml10" title="iconfont 图标">ali</span>
 							<span :class="{ 'span-active': fontIconType === 'ele' }" @click="onIconChange('ele')" class="ml10" title="elementPlus 图标">ele</span>
-							<span :class="{ 'span-active': fontIconType === 'awe' }" @click="onIconChange('awe')" class="ml10" title="fontawesome 图标">awe</span>
+							<!-- <span :class="{ 'span-active': fontIconType === 'awe' }" @click="onIconChange('awe')" class="ml10" title="fontawesome 图标">awe</span> -->
 						</div>
 					</div>
 					<div class="icon-selector-warp-row">

+ 9 - 1
src/layout/component/header.vue

@@ -1,3 +1,11 @@
+<!--
+ * @Author: zc
+ * @Description: 
+ * @version: 
+ * @Date: 2022-10-21 09:01:22
+ * @LastEditors: 
+ * @LastEditTime: 2022-11-08 17:12:59
+-->
 <template>
 	<el-header class="layout-header" :height="setHeaderHeight" v-show="!isTagsViewCurrenFull">
 		<NavBarsIndex />
@@ -22,7 +30,7 @@ export default defineComponent({
 		// 设置 header 的高度
 		const setHeaderHeight = computed(() => {
 			let { isTagsview, layout } = themeConfig.value;
-			if (isTagsview && layout !== 'classic') return '84px';
+			if (isTagsview && layout !== 'classic') return 'auto';
 			else return '50px';
 		});
 		return {

+ 16 - 13
src/layout/logo/index.vue

@@ -1,10 +1,17 @@
+<!--
+ * @Author: zc
+ * @Description: 
+ * @version: 
+ * @Date: 2022-10-21 09:01:22
+ * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-11-09 10:04:06
+-->
 <template>
 	<div class="layout-logo" v-if="setShowLogo" @click="onThemeConfigChange">
-		<img :src="logoMini" class="layout-logo-medium-img" alt=""/>
-		<span>{{ themeConfig.globalTitle }}</span>
+		<img :src="logo" class="layout-logo-medium-img" alt=""/>
 	</div>
 	<div class="layout-logo-size" v-else @click="onThemeConfigChange">
-		<img :src="logoMini" class="layout-logo-size-img" alt=""/>
+		<img src="/src/assets/images/logoMini.png" class="layout-logo-size-img" alt=""/>
 	</div>
 </template>
 
@@ -13,8 +20,7 @@ import { computed, defineComponent } from 'vue';
 import { storeToRefs } from 'pinia';
 import { useThemeConfig } from '/@/stores/themeConfig';
 
-import logoMini from '/@/assets/logo-mini.svg';
-
+import logo from '/@/assets/images/logo.png';
 export default defineComponent({
 	name: 'layoutLogo',
 	setup() {
@@ -31,7 +37,7 @@ export default defineComponent({
 			themeConfig.value.isCollapse = !themeConfig.value.isCollapse;
 		};
 		return {
-			logoMini,
+			logo,
 			setShowLogo,
 			themeConfig,
 			onThemeConfigChange,
@@ -43,7 +49,7 @@ export default defineComponent({
 <style scoped lang="scss">
 .layout-logo {
 	width: 220px;
-	height: 50px;
+	height: 90px;
 	display: flex;
 	align-items: center;
 	justify-content: center;
@@ -61,19 +67,16 @@ export default defineComponent({
 			color: var(--color-primary-light-2);
 		}
 	}
-	&-medium-img {
-		width: 20px;
-		margin-right: 5px;
-	}
+	
 }
 .layout-logo-size {
 	width: 100%;
-	height: 50px;
+	height: 90px;
 	display: flex;
 	cursor: pointer;
 	animation: logoAnimation 0.3s ease-in-out;
 	&-img {
-		width: 20px;
+		width: 50px;
 		margin: auto;
 	}
 	&:hover {

+ 6 - 4
src/layout/navBars/breadcrumb/breadcrumb.vue

@@ -3,10 +3,11 @@
 		<SvgIcon
 			class="layout-navbars-breadcrumb-icon"
 			:name="themeConfig.isCollapse ? 'ele-Expand' : 'ele-Fold'"
-			:size="16"
+			:size="24"
 			@click="onThemeConfigChange"
+			color="#3A51E0"
 		/>
-		<el-breadcrumb class="layout-navbars-breadcrumb-hide">
+		<!-- <el-breadcrumb class="layout-navbars-breadcrumb-hide">
 			<transition-group name="breadcrumb">
 				<el-breadcrumb-item v-for="(v, k) in breadcrumbList" :key="!v.meta.tagsViewName ? v.meta.title : v.meta.tagsViewName">
 					<span v-if="k === breadcrumbList.length - 1" class="layout-navbars-breadcrumb-span">
@@ -19,7 +20,7 @@
 					</a>
 				</el-breadcrumb-item>
 			</transition-group>
-		</el-breadcrumb>
+		</el-breadcrumb> -->
 	</div>
 </template>
 
@@ -124,10 +125,11 @@ export default defineComponent({
 
 <style scoped lang="scss">
 .layout-navbars-breadcrumb {
-	flex: 1;
+	margin-right: 20px;
 	height: inherit;
 	display: flex;
 	align-items: center;
+	margin-left: 10px;
 	.layout-navbars-breadcrumb-icon {
 		cursor: pointer;
 		font-size: 18px;

+ 13 - 4
src/layout/navBars/breadcrumb/index.vue

@@ -1,14 +1,16 @@
 <template>
-	<div class="layout-navbars-breadcrumb-index">
+	<div class="layout-navbars-breadcrumb-index" :class="isShowControls ? 'showControl' : ''">
 		<Logo v-if="setIsShowLogo" />
 		<Breadcrumb />
+		<PhoneControls v-if="isShowControls"/>
+		<div v-else style="flex:1"></div>
 		<Horizontal :menuList="menuList" v-if="isLayoutTransverse" />
 		<User />
 	</div>
 </template>
 
 <script lang="ts">
-import { computed, reactive, toRefs, onMounted, onUnmounted, getCurrentInstance, defineComponent } from 'vue';
+import { computed, reactive, toRefs, onMounted, onUnmounted, getCurrentInstance, defineComponent, ref } from 'vue';
 import { useRoute } from 'vue-router';
 import { storeToRefs } from 'pinia';
 import { useRoutesList } from '/@/stores/routesList';
@@ -17,6 +19,7 @@ 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';
+import PhoneControls from "/@/layout/navBars/breadcrumb/phoneControls.vue"
 
 // 定义接口来定义对象的类型
 interface IndexState {
@@ -25,7 +28,7 @@ interface IndexState {
 
 export default defineComponent({
 	name: 'layoutBreadcrumbIndex',
-	components: { Breadcrumb, User, Logo, Horizontal },
+	components: { Breadcrumb, User, Logo, Horizontal, PhoneControls },
 	setup() {
 		const { proxy } = <any>getCurrentInstance();
 		const stores = useRoutesList();
@@ -33,6 +36,7 @@ export default defineComponent({
 		const { themeConfig } = storeToRefs(storesThemeConfig);
 		const { routesList } = storeToRefs(stores);
 		const route = useRoute();
+		const isShowControls = ref(true)
 		const state = reactive<IndexState>({
 			menuList: [],
 		});
@@ -102,6 +106,7 @@ export default defineComponent({
 		return {
 			setIsShowLogo,
 			isLayoutTransverse,
+			isShowControls,
 			...toRefs(state),
 		};
 	},
@@ -110,10 +115,14 @@ export default defineComponent({
 
 <style scoped lang="scss">
 .layout-navbars-breadcrumb-index {
-	height: 50px;
+	height: 90px;
 	display: flex;
 	align-items: center;
 	background: var(--next-bg-topBar);
 	border-bottom: 1px solid var(--next-border-color-light);
 }
+.showControl{
+	border: none;
+	background: none;
+}
 </style>

+ 181 - 0
src/layout/navBars/breadcrumb/phoneControls.vue

@@ -0,0 +1,181 @@
+<!--
+ * @Author: zc
+ * @Description: 电话控件
+ * @version: 
+ * @Date: 2022-11-08 14:16:48
+ * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-11-09 14:17:20
+-->
+<template>
+    <div class="phoneControls">
+        <div class="infos">
+            <div><span>分机号:</span>1123131</div>
+            <div class="bottom_line"><span>状态:</span><b class="qianru_status">签入</b></div>
+        </div>
+        <div class="btns">
+            <div class="item" :class="active.includes('qianru') ? 'active' : ''" v-if="status === 1" @click="onControlClick('qianru')">
+                <img v-if="active.includes('qianru')" src="/src/assets/images/phoneControls/qianru_white.png" alt="">
+                <img v-else :src="status === 1 ? '/src/assets/images/phoneControls/qinaru_grey.png' : '/src/assets/images/phoneControls/qinaru_blue.png'" alt="">
+                <span>签入</span>
+            </div>
+            <div class="item" v-else @click="onControlClick('qianchu')">
+                <img src="/src/assets/images/phoneControls/qianchu_blue.png" alt="">
+                <span>签出</span>
+            </div>
+            <div class="item" :class="active.includes('guaduan') ? 'active' : ''"  @click="onControlClick('guaduan')">
+                <img v-if="active.includes('guaduan')" src="/src/assets/images/phoneControls/guaduan_white.png" alt="">
+                <img v-else :src="status === 1 ? '/src/assets/images/phoneControls/guaduan_grey.png' : '/src/assets/images/phoneControls/guaduan_blue.png'" alt="">
+                <span>挂断</span>
+            </div>
+            <div class="item" :class="active.includes('xiaoxiu') ? 'active' : ''"  @click="onControlClick('xiaoxiu')">
+                <img v-if="active.includes('xiaoxiu')" src="/src/assets/images/phoneControls/xiaoxiu_white.png" alt="">
+                <img v-else :src="status === 1 ? '/src/assets/images/phoneControls/xiaoxiu_grey.png' : '/src/assets/images/phoneControls/xiaoxiu_blue.png'" alt="">
+                <span>小休</span>
+            </div>
+            <div class="item" :class="active.includes('baochi') ? 'active' : ''"  @click="onControlClick('baochi')">
+                <img v-if="active.includes('baochi')" src="/src/assets/images/phoneControls/baochi_white.png" alt="">
+                <img v-else :src="status === 1 ? '/src/assets/images/phoneControls/baochi_grey.png' : '/src/assets/images/phoneControls/baochi_blue.png'" alt="">
+                <span>保持</span>
+            </div>
+            <div class="item" :class="active.includes('jingyin') ? 'active' : ''" @click="onControlClick('jingyin')">
+                <img v-if="active.includes('jingyin')" src="/src/assets/images/phoneControls/jingyin_white.png" alt="">
+                <img v-else :src="status === 1 ? '/src/assets/images/phoneControls/jingyin_grey.png' : '/src/assets/images/phoneControls/jingyin_blue.png'" alt="">
+                <span>静音</span>
+            </div>
+            <div class="item" :class="active.includes('zhuanjie') ? 'active' : ''" @click="onControlClick('zhuanjie')">
+                <img v-if="active.includes('zhuanjie')" src="/src/assets/images/phoneControls/zhuanjie_white.png" alt="">
+                <img v-else :src="status === 1 ? '/src/assets/images/phoneControls/zhuanjie_grey.png' : '/src/assets/images/phoneControls/zhuanjie_blue.png'" alt="">
+                <span>转接</span>
+            </div>
+            <div class="item" :class="active.includes('sanfang') ? 'active' : ''" @click="onControlClick('sanfang')">
+                <img v-if="active.includes('sanfang')" src="/src/assets/images/phoneControls/sanfang_white.png" alt="">
+                <img v-else :src="status === 1 ? '/src/assets/images/phoneControls/sanfang_grey.png' : '/src/assets/images/phoneControls/sanfang_blue.png'" alt="">
+                <span>三方会议</span>
+            </div>
+            <div class="item" :class="active.includes('waihu') ? 'active' : ''" @click="onControlClick('waihu')">
+                <img v-if="active.includes('waihu')" src="/src/assets/images/phoneControls/waihu_white.png" alt="">
+                <img v-else :src="status === 1 ? '/src/assets/images/phoneControls/waihu_grey.png' : '/src/assets/images/phoneControls/waihu_blue.png'" alt="">
+                <span>外呼</span>
+            </div>
+            <div class="item" :class="active.includes('hujiaozhuanyi') ? 'active' : ''" @click="onControlClick('zhuanyi')">
+                <img v-if="active.includes('hujiaozhuanyi')" src="/src/assets/images/phoneControls/hujiaozhuanyi_white.png" alt="">
+                <img v-else :src="status === 1 ? '/src/assets/images/phoneControls/hujiaozhuanyi_grey.png' : '/src/assets/images/phoneControls/hujiaozhuanyi_blue.png'" alt="">
+                <span>呼叫转移</span>
+            </div>
+            <div class="item" :class="active.includes('pingjia') ? 'active' : ''" @click="onControlClick('pingjia')">
+                <img v-if="active.includes('pingjia')" src="/src/assets/images/phoneControls/pingjia_white.png" alt="">
+                <img v-else :src="status === 1 ? '/src/assets/images/phoneControls/pingjia_grey.png' : '/src/assets/images/phoneControls/pingjia_blue.png'" alt="">
+                <span>评价</span>
+            </div>
+        </div>
+    </div>
+    <div class="seizeSeat-box">
+
+    </div>
+</template>
+
+<script setup lang="ts">
+import {reactive,toRefs} from "vue";
+const state = reactive({
+    status:2,
+    active:['guaduan','waihu','pingjia']
+})
+const {status,active} = toRefs(state);
+// 点击事件
+const onControlClick = (val:string)=>{
+    // console.log(val)
+    switch (val) {
+        case 'qianru':
+            
+            break;
+    
+        default:
+            break;
+    }
+}
+</script>
+
+<style scoped lang="scss">
+.seizeSeat-box{
+    display: none;
+}
+.phoneControls {
+    display: flex;
+    flex: 1;
+    background: #FFFFFF;
+    box-shadow: 0px 1px 8px 0px rgba(0, 15, 49, 0.1);
+    border-bottom-left-radius: 90px;
+    border-bottom-right-radius: 90px;
+    padding: 0 52px;
+    color: #333;
+    height: 100%;
+    .infos {
+        margin: 20px 0;
+        text-align: left;
+        width: 120px;
+        .bottom_line {
+            padding-top: 5px;
+        }
+
+        .qianru_status {
+            color: var(--el-color-primary);
+            font-weight: normal;
+        }
+
+        span {
+            display: inline-block;
+            width: 60px;
+            text-align: right;
+        }
+    }
+
+    .btns {
+        display: flex;
+        margin-left: 10px;
+        width: calc(100% - 120px);
+        justify-content: space-between;
+        .item {
+            text-align: center;
+            cursor: pointer;
+            width: 100%;
+            height: 100%;
+            &:hover{
+                transition: inherit;
+                color: var(--el-color-primary) !important;
+                background-color: var(--next-color-seting-main) !important;
+            }
+            img {
+                display: block;
+                margin: 0 auto;
+                padding-top: 20px;
+            }
+            span {
+                padding-top: 10px;
+            }
+        }
+        .active{
+            color: #fff;
+            background-image: url('src/assets/images/phoneControls/active.png');
+            background-repeat: no-repeat;
+            background-size: 100% 100%;
+            height: calc(100% + 20px);
+            background-color: var(--next-bg-main-color);
+            img {
+                display: block;
+                margin: 0 auto;
+                padding-top: 30px;
+            }
+            span {
+                padding-top: 10px;
+            }
+             &:hover{
+                transition: inherit;
+                color: var(--next-color-white) !important;
+                background-color: var(--next-bg-main-color) !important;
+            }
+        }
+        
+    }
+
+}
+</style>

+ 14 - 7
src/layout/navBars/breadcrumb/user.vue

@@ -1,6 +1,8 @@
 <template>
-	<div class="layout-navbars-breadcrumb-user pr15" :style="{ flex: layoutUserFlexNum }">
-		<el-dropdown :show-timeout="70" :hide-timeout="50" trigger="click" @command="onComponentSizeChange">
+
+	<!--  :style="{ flex: layoutUserFlexNum }" -->
+	<div class="layout-navbars-breadcrumb-user pr15">
+		<!-- <el-dropdown :show-timeout="70" :hide-timeout="50" trigger="click" @command="onComponentSizeChange">
 			<div class="layout-navbars-breadcrumb-user-icon"  title="组件大小">
 				<i class="iconfont icon-ziti"></i>
 			</div>
@@ -19,7 +21,7 @@
 		</div>
 		<div class="layout-navbars-breadcrumb-user-icon" @click="onLayoutSetingClick" title="布局配置">
 			<i class="icon-skin iconfont"></i>
-		</div>
+		</div> -->
 		<!-- <div class="layout-navbars-breadcrumb-user-icon">
 			<el-popover placement="bottom" trigger="click" transition="el-zoom-in-top" :width="300" :persistent="false">
 				<template #reference>
@@ -34,14 +36,14 @@
 				</template>
 			</el-popover>
 		</div> -->
-		<div class="layout-navbars-breadcrumb-user-icon" @click="onLockScreen" title="锁屏">
+		<!-- <div class="layout-navbars-breadcrumb-user-icon" @click="onLockScreen" title="锁屏">
 			<el-icon>
 				<ele-Lock />
 			</el-icon>
 		</div>
 		<div class="layout-navbars-breadcrumb-user-icon mr10" @click="onScreenfullClick" :title="isScreenfull ? '关全屏' : '开全屏'" >
 			<i class="iconfont" :class="!isScreenfull ? 'icon-quanping1' : 'icon-tuichuquanping'"></i>
-		</div>
+		</div> -->
 		<el-dropdown :show-timeout="70" :hide-timeout="50" @command="onHandleCommandClick">
 			<span class="layout-navbars-breadcrumb-user-link">
 				<el-avatar :src="userInfos.photo" :icon="UserFilled" class="layout-navbars-breadcrumb-user-link-photo mr5" />
@@ -57,7 +59,11 @@
 					<el-dropdown-item divided command="offduty" v-else-if="userStates.isOnDuty">下班 <span v-if="userStates.telNo">({{userStates.telNo}})</span></el-dropdown-item>
 					<el-dropdown-item divided command="telRest" v-if="userStates.isOnDuty && !userStates.isResting">分机休息</el-dropdown-item>
 					<el-dropdown-item divided command="telUnrest" v-else-if="userStates.isOnDuty && userStates.isResting">结束休息</el-dropdown-item>
-					<el-dropdown-item divided command="logOut">退出登录</el-dropdown-item>
+					<el-dropdown-item divided command="logOut">
+						<el-icon class="el-input__icon">
+							<ele-User />
+						</el-icon>退出
+					</el-dropdown-item>
 				</el-dropdown-menu>
 			</template>
 		</el-dropdown>
@@ -317,7 +323,7 @@ export default defineComponent({
 		}
 		const getTelsLists = () =>{// 查询所有分机
 			getTelsList().then((res: any) => {//查询所有的分机
-				state.telsList = res.content;
+				state.telsList = res?.content ?? [];
 			})
 		}
 		const showDutyDialog = ref(false);
@@ -383,6 +389,7 @@ export default defineComponent({
 	display: flex;
 	align-items: center;
 	justify-content: flex-end;
+	margin-left: 40px;
 	&-link {
 		height: 100%;
 		display: flex;

+ 26 - 5
src/layout/navBars/tagsView/tagsView.vue

@@ -1,5 +1,5 @@
 <template>
-	<div class="layout-navbars-tagsview" :class="{ 'layout-navbars-tagsview-shadow': getThemeConfig.layout === 'classic' }">
+	<div class="layout-navbars-tagsview" :class="{ 'layout-navbars-tagsview-shadow': getThemeConfig.layout === 'classic','isShowControls':isShowControls }">
 		<el-scrollbar ref="scrollbarRef" @wheel.prevent="onHandleScroll">
 			<ul class="layout-navbars-tagsview-ul" :class="setTagsStyle" ref="tagsUlRef">
 				<li
@@ -26,14 +26,14 @@
 							@click.stop="refreshCurrentTagsView($route.fullPath)"
 						/>
 						<SvgIcon
-							name="ele-Close"
+							name="ele-CircleCloseFilled"
 							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="ele-Close"
+						name="ele-CircleCloseFilled"
 						class="layout-navbars-tagsview-ul-li-icon layout-icon-three"
 						v-if="!v.meta.isAffix"
 						@click.stop="closeCurrentTagsView(getThemeConfig.isShareTagsView ? v.path : v.url)"
@@ -119,6 +119,7 @@ export default defineComponent({
 		const storesKeepALiveNames = useKeepALiveNames();
 		const route = useRoute();
 		const router = useRouter();
+		const isShowControls = ref(true)
 		const state = reactive<TagsViewState>({
 			routeActive: '',
 			routePath: route.path,
@@ -592,6 +593,7 @@ export default defineComponent({
 			getThemeConfig,
 			setTagsStyle,
 			setTagsViewNameI18n,
+			isShowControls,
 			refreshCurrentTagsView,
 			closeCurrentTagsView,
 			onCurrentContextmenuClick,
@@ -614,7 +616,6 @@ export default defineComponent({
 		list-style: none;
 		margin: 0;
 		padding: 0;
-		height: 34px;
 		display: flex;
 		align-items: center;
 		color: var(--el-text-color-regular);
@@ -720,14 +721,34 @@ export default defineComponent({
 				color: unset;
 			}
 		}
+		.layout-navbars-tagsview-ul-li-icon{
+			color: #D4D4D4;
+		}
 		.is-active {
 			@extend .tags-style-five-svg;
-			background: var(--el-color-primary-light-9) !important;
+			background: var(--next-bg-main-color) !important;
 			color: var(--el-color-primary) !important;
 			z-index: 1;
 		}
 	}
 }
+.isShowControls{
+	background: none;
+	margin-top: 20px;
+	.tags-style-five {
+		.layout-navbars-tagsview-ul-li {
+			&:hover {
+				@extend .tags-style-five-svg;
+				background: var(--el-color-primary-light-9);
+				color: unset;
+			}
+		}
+		.is-active {
+			@extend .tags-style-five-svg;
+			background: #fff !important;
+		}
+	}
+}
 .layout-navbars-tagsview-shadow {
 	box-shadow: rgb(0 21 41 / 4%) 0px 1px 4px;
 }

+ 2 - 1
src/main.ts

@@ -4,7 +4,7 @@
  * @version: 
  * @Date: 2022-08-09 16:19:55
  * @LastEditors: Please set LastEditors
- * @LastEditTime: 2022-10-26 14:48:18
+ * @LastEditTime: 2022-10-31 17:39:52
  */
 import { createApp } from 'vue';
 import pinia from '/@/stores/index';
@@ -42,6 +42,7 @@ const app = createApp(App);
 //  signalR 初始化signalr 
 signalR.init(appConfig.socketUrl);
 
+
 // 自定义指令和svg组件
 directive(app);
 other.elSvg(app);

+ 41 - 23
src/router/backEnd.ts

@@ -1,17 +1,15 @@
-import { RouteRecordRaw } from 'vue-router';
-import { storeToRefs } from 'pinia';
+import {RouteRecordRaw} from 'vue-router';
+// import { storeToRefs } from 'pinia';
 import pinia from '/@/stores/index';
-import { useUserInfo } from '/@/stores/userInfo';
-import { useRequestOldRoutes } from '/@/stores/requestOldRoutes';
-import { Session } from '/@/utils/storage';
-import { NextLoading } from '/@/utils/loading';
-import { dynamicRoutes, notFoundAndNoPower } from '/@/router/route';
-import { formatTwoStageRoutes, formatFlatteningRoutes, router } from '/@/router/index';
-import { useRoutesList } from '/@/stores/routesList';
-import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes';
-import { useMenuApi } from '/@/api/menu';
-
-const menuApi = useMenuApi();
+import {useUserInfo} from '/@/stores/userInfo';
+import {useRequestOldRoutes} from '/@/stores/requestOldRoutes';
+import {Session} from '/@/utils/storage';
+import {NextLoading} from '/@/utils/loading';
+import {dynamicRoutes, notFoundAndNoPower} from '/@/router/route';
+import {formatFlatteningRoutes, formatTwoStageRoutes, router} from '/@/router/index';
+import {useRoutesList} from '/@/stores/routesList';
+import {useTagsViewRoutes} from '/@/stores/tagsViewRoutes';
+import {getMenu} from '/@/api/system/menu';
 
 const layouModules: any = import.meta.glob('../layout/routerView/*.{vue,tsx}');
 const viewsModules: any = import.meta.glob('../views/**/*.{vue,tsx}');
@@ -25,6 +23,30 @@ const viewsModules: any = import.meta.glob('../views/**/*.{vue,tsx}');
  */
 const dynamicViewsModules: Record<string, Function> = Object.assign({}, { ...layouModules }, { ...viewsModules });
 
+// 菜单格式化
+function formatRouter(arr:Array<any>){
+	if (!arr.length){
+		router.push('/');
+		Session.clear();
+		throw Error('没有返回菜单,重新登录')
+	}
+	arr.forEach((v: any) => {
+		v.name = v.ruleName;
+		v.meta = {};
+		v.meta.title = v.pageName;
+		v.meta.icon = v.icon;
+		v.meta.isHide = v.isHide;
+		v.meta.isKeepAlive = v.isKeepAlive;
+		v.meta.isAffix = v.isAffix;
+		v.meta.isLink = v.isLink;
+		v.meta.isIframe = v.isIframe;
+		if(v.children.length) {
+			formatRouter(v.children)
+		}
+	});
+	return arr;
+}
+
 /**
  * 后端控制路由:初始化方法,防止刷新时路由丢失
  * @method NextLoading 界面 loading 动画开始执行
@@ -43,11 +65,13 @@ export async function initBackEndControlRoutes() {
 	// https://gitee.com/lyt-top/vue-next-admin/issues/I5F1HP
 	await useUserInfo().setUserInfos();
 	// 获取路由菜单数据
-	const res = await getBackEndControlRoutes();
+	let res:any = await getBackEndControlRoutes();
+	// 路由内容格式化
+	let resRouter = formatRouter(res.result); // 递归处理路由数据
 	// 存储接口原始路由(未处理component),根据需求选择使用
-	useRequestOldRoutes().setRequestOldRoutes(JSON.parse(JSON.stringify(res.data)));
+	useRequestOldRoutes().setRequestOldRoutes(JSON.parse(JSON.stringify(resRouter)));
 	// 处理路由(component),替换 dynamicRoutes(/@/router/route)第一个顶级 children 的路由
-	dynamicRoutes[0].children = await backEndComponent(res.data);
+	dynamicRoutes[0].children = await backEndComponent(resRouter);
 	// 添加动态路由
 	await setAddRoute();
 	// 设置路由到 vuex routesList 中(已处理成多级嵌套路由)及缓存多级嵌套数组处理后的一维数组
@@ -103,14 +127,8 @@ export async function setAddRoute() {
  * @returns 返回后端路由菜单数据
  */
 export function getBackEndControlRoutes() {
-	// 模拟 admin 与 test
-	const stores = useUserInfo(pinia);
-	const { userInfos } = storeToRefs(stores);
-	const auth = userInfos.value.roles[0];
 	// 管理员 admin
-	if (auth === 'admin') return menuApi.getMenuAdmin();
-	// 其它用户 test
-	else return menuApi.getMenuTest();
+	return getMenu();
 }
 
 /**

+ 3 - 9
src/router/frontEnd.ts

@@ -75,17 +75,11 @@ export function setFilterRouteEnd() {
  * @returns 返回有当前用户权限标识的路由数组
  */
 export function setFilterRoute(chil: any) {
-	const stores = useUserInfo(pinia);
-	const { userInfos } = storeToRefs(stores);
+	// const stores = useUserInfo(pinia);
+	// const { userInfos } = storeToRefs(stores);
 	let filterRoute: any = [];
 	chil.forEach((route: any) => {
-		if (route.meta.roles) {
-			route.meta.roles.forEach((metaRoles: any) => {
-				userInfos.value.roles.forEach((roles: any) => {
-					if (metaRoles === roles) filterRoute.push({ ...route });
-				});
-			});
-		}
+		filterRoute.push({ ...route });
 	});
 	return filterRoute;
 }

+ 1 - 0
src/router/index.ts

@@ -57,6 +57,7 @@ export function formatFlatteningRoutes(arr: any) {
  * @param arr 处理后的一维路由菜单数组
  * @returns 返回将一维数组重新处理成 `定义动态路由(dynamicRoutes)` 的格式
  */
+
 export function formatTwoStageRoutes(arr: any) {
 	if (arr.length <= 0) return false;
 	const newArr: any = [];

+ 16 - 32
src/router/route.ts

@@ -42,7 +42,6 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
 					isKeepAlive: true,
 					isAffix: true,
 					isIframe: false,
-					roles: ['admin', 'common'],
 					icon: 'iconfont icon-shouye',
 				},
 			},
@@ -58,7 +57,6 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
 					isKeepAlive: true,
 					isAffix: false,
 					isIframe: false,
-					roles: ['admin', 'common'],
 					icon: 'iconfont icon-xitongshezhi',
 				},
 				children: [
@@ -73,25 +71,9 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
 							isKeepAlive: true,
 							isAffix: false,
 							isIframe: false,
-							roles: ['admin'],
 							icon: 'iconfont icon-caidan',
 						},
 					},
-					{
-						path: '/system/role',
-						name: 'systemRole',
-						component: () => import('/@/views/system/role/index.vue'),
-						meta: {
-							title: '角色管理',
-							isLink: '',
-							isHide: false,
-							isKeepAlive: true,
-							isAffix: false,
-							isIframe: false,
-							roles: ['admin'],
-							icon: 'ele-ColdDrink',
-						},
-					},
 					{
 						path: '/system/user',
 						name: 'systemUser',
@@ -103,7 +85,6 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
 							isKeepAlive: true,
 							isAffix: false,
 							isIframe: false,
-							roles: ['admin', 'common'],
 							icon: 'iconfont icon-icon-',
 						},
 					},
@@ -118,7 +99,6 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
 							isKeepAlive: true,
 							isAffix: false,
 							isIframe: false,
-							roles: ['admin', 'common'],
 							icon: 'ele-Phone',
 						},
 					},
@@ -133,7 +113,6 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
 							isKeepAlive: true,
 							isAffix: false,
 							isIframe: false,
-							roles: ['admin', 'common'],
 							icon: 'ele-Phone',
 						},
 					},
@@ -148,7 +127,6 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
 							isKeepAlive: true,
 							isAffix: false,
 							isIframe: false,
-							roles: ['admin', 'common'],
 							icon: 'ele-List',
 						},
 					},
@@ -163,7 +141,6 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
 							isKeepAlive: true,
 							isAffix: false,
 							isIframe: false,
-							roles: ['admin', 'common'],
 							icon: 'ele-DocumentCopy',
 						},
 					},
@@ -178,10 +155,23 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
 							isKeepAlive: true,
 							isAffix: false,
 							isIframe: false,
-							roles: ['admin', 'common'],
 							icon: 'ele-Reading',
 						},
 					},
+					{
+						path: '/system/role',
+						name: 'systemRole',
+						component: () => import('/@/views/system/role/index.vue'),
+						meta: {
+							title: '角色管理',
+							isLink: '',
+							isHide: true,
+							isKeepAlive: true,
+							isAffix: false,
+							isIframe: false,
+							icon: 'ele-ColdDrink',
+						},
+					},
 					{
 						path: '/system/dept',
 						name: 'systemDept',
@@ -189,11 +179,10 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
 						meta: {
 							title: '部门管理',
 							isLink: '',
-							isHide: false,
+							isHide: true,
 							isKeepAlive: true,
 							isAffix: false,
 							isIframe: false,
-							roles: ['admin'],
 							icon: 'ele-OfficeBuilding',
 						},
 					},
@@ -204,11 +193,10 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
 						meta: {
 							title: '字典管理',
 							isLink: '',
-							isHide: false,
+							isHide: true,
 							isKeepAlive: true,
 							isAffix: false,
 							isIframe: false,
-							roles: ['admin'],
 							icon: 'ele-SetUp',
 						},
 					},
@@ -226,7 +214,6 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
 					isKeepAlive: true,
 					isAffix: false,
 					isIframe: false,
-					roles: ['admin', 'common'],
 					icon: 'iconfont icon-putong',
 				},
 				children:[
@@ -241,7 +228,6 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
 							isKeepAlive: true,
 							isAffix: false,
 							isIframe: false,
-							roles: ['admin', 'common'],
 							icon: 'ele-Operation',
 						},
 					},
@@ -256,7 +242,6 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
 							isKeepAlive: true,
 							isAffix: false,
 							isIframe: false,
-							roles: ['admin', 'common'],
 							icon: 'ele-List',
 						},
 					},
@@ -271,7 +256,6 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
 							isKeepAlive: true,
 							isAffix: false,
 							isIframe: false,
-							roles: ['admin', 'common'],
 							icon: 'ele-CreditCard',
 						},
 					},

+ 5 - 5
src/stores/themeConfig.ts

@@ -20,7 +20,7 @@ export const useThemeConfig = defineStore('themeConfig', {
 			 * 全局主题
 			 */
 			// 默认 primary 主题颜色
-			primary: '#409eff',
+			primary: '#3C50E0',
 			// 是否开启深色模式
 			isIsDark: false,
 
@@ -37,9 +37,9 @@ export const useThemeConfig = defineStore('themeConfig', {
 			// 是否开启顶栏背景颜色渐变
 			isTopBarColorGradual: false,
 			// 默认菜单导航背景颜色
-			menuBar: '#545c64',
+			menuBar: '#3C50E0',
 			// 默认菜单导航字体颜色
-			menuBarColor: '#eaeaea',
+			menuBarColor: '#bfcdff',
 			// 是否开启菜单背景颜色渐变
 			isMenuBarColorGradual: false,
 			// 默认分栏菜单背景颜色
@@ -89,7 +89,7 @@ export const useThemeConfig = defineStore('themeConfig', {
 			// 是否开启 TagsView 共用
 			isShareTagsView: false,
 			// 是否开启 Footer 底部版权信息
-			isFooter: true,
+			isFooter: false,
 			// 是否开启灰色模式
 			isGrayscale: false,
 			// 是否开启色弱模式
@@ -124,7 +124,7 @@ export const useThemeConfig = defineStore('themeConfig', {
 			 * 后端控制路由
 			 */
 			// 是否开启后端控制路由
-			isRequestRoutes: false,
+			isRequestRoutes: true,
 
 			/**
 			 * 全局网站标题 / 副标题

+ 19 - 11
src/stores/userInfo.ts

@@ -1,3 +1,11 @@
+/*
+ * @Author: zc
+ * @Description: 
+ * @version: 
+ * @Date: 2022-10-21 09:01:22
+ * @LastEditors: 
+ * @LastEditTime: 2022-11-08 15:49:57
+ */
 import {defineStore} from 'pinia';
 import Cookies from 'js-cookie';
 import {UserInfosStates} from './interface';
@@ -36,22 +44,22 @@ export const useUserInfo = defineStore('userInfo', {
 					// 模拟数据
 					let defaultRoles: Array<string> = [];
 					let defaultAuthBtnList: Array<string> = [];
-					// admin 页面权限标识,对应路由 meta.roles,用于控制路由的显示/隐藏
-					let adminRoles: Array<string> = ['admin'];
+					// // admin 页面权限标识,对应路由 meta.roles,用于控制路由的显示/隐藏
+					// let adminRoles: Array<string> = ['admin'];
 					// admin 按钮权限标识
 					let adminAuthBtnList: Array<string> = ['btn.add', 'btn.del', 'btn.edit', 'btn.link'];
 					// test 页面权限标识,对应路由 meta.roles,用于控制路由的显示/隐藏
-					let testRoles: Array<string> = ['common'];
-					// test 按钮权限标识
-					let testAuthBtnList: Array<string> = ['btn.add', 'btn.link'];
+					// let testRoles: Array<string> = ['common'];
+					// // test 按钮权限标识
+					// let testAuthBtnList: Array<string> = ['btn.add', 'btn.link'];
 					// 不同用户模拟不同的用户权限
-					if (userName === 'admin') {
-						defaultRoles = adminRoles;
+					// if (userName === 'admin') {
+						// defaultRoles = adminRoles;
 						defaultAuthBtnList = adminAuthBtnList;
-					} else {
-						defaultRoles = testRoles;
-						defaultAuthBtnList = testAuthBtnList;
-					}
+					// } else {
+					// 	defaultRoles = testRoles;
+					// 	defaultAuthBtnList = testAuthBtnList;
+					// }
 					// 用户信息模拟数据
 					const userInfos = {
 						userName: userName,

+ 2 - 2
src/stores/userState.ts

@@ -4,7 +4,7 @@
  * @version: 
  * @Date: 2022-09-29 09:37:40
  * @LastEditors: Please set LastEditors
- * @LastEditTime: 2022-10-08 16:03:41
+ * @LastEditTime: 2022-11-08 16:04:27
  */
 import {defineStore} from 'pinia';
 import {UserStateInfos} from './interface';
@@ -24,7 +24,7 @@ export const useUserState = defineStore('userState', {
 	actions: {
 		getUserStateAction() {
 			getUserState().then((res: any) => {//获取用户状态
-				this.userStates = res.content;
+				this.userStates = res?.content ?? false;
 			})
 		}
 	},

+ 13 - 2
src/theme/app.scss

@@ -9,7 +9,7 @@
 
 :root {
 	--next-color-white: #ffffff;
-	--next-bg-main-color: #f8f8f8;
+	--next-bg-main-color: #F0F4FF;
 	--next-bg-color: #f5f5ff;
 	--next-border-color-light: #f1f2f3;
 	--next-color-primary-lighter: #ecf5ff;
@@ -17,11 +17,13 @@
 	--next-color-warning-lighter: #fdf6ec;
 	--next-color-danger-lighter: #fef0f0;
 	--next-color-dark-hover: #0000001a;
-	--next-color-menu-hover: rgba(0, 0, 0, 0.2);
+	--next-color-menu-hover: #2935BA;
+	// --next-color-menu-hover: rgba(0, 0, 0, 0.2);
 	--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;
+	--next--login-text-color:#4564E9;
 }
 
 html,
@@ -289,6 +291,15 @@ body,
 .mt8 {
 	margin-bottom: 8px;
 }
+.mb20{
+	margin-bottom: 20px;
+}
+.mt20{
+	margin-top: 20px;
+}
+.mt30{
+	margin-top: 30px;
+}
 /* 弹窗头部样式
 ------------------------------- */
 .dialog-title{

+ 9 - 0
src/theme/element.scss

@@ -88,6 +88,9 @@
 .el-sub-menu:not(.is-opened):hover .el-sub-menu__title {
 	@extend .el-menu-hover-bg-color;
 }
+.el-menu-item.is-active{
+	color: #fff;
+}
 .el-sub-menu.is-active.is-opened .el-sub-menu__title {
 	background-color: unset !important;
 }
@@ -281,4 +284,10 @@
 .el-transfer-panel{
 	width: auto;
 }
+/* card的样式
+------------------------------- */
+.el-card{
+	--el-card-border-radius: 8px;
+	border: 0;
+}
 

+ 1 - 1
src/theme/icon/iconfont.json

@@ -1,6 +1,6 @@
 {
   "id": "3595250",
-  "name": "呼叫中心",
+  "name": "12345",
   "font_family": "iconfont",
   "css_prefix_text": "icon-",
   "description": "",

+ 1 - 1
src/theme/iconfont/iconfont.json

@@ -1,6 +1,6 @@
 {
   "id": "3595250",
-  "name": "呼叫中心",
+  "name": "12345",
   "font_family": "iconfont",
   "css_prefix_text": "icon-",
   "description": "",

+ 10 - 1
src/theme/media/login.scss

@@ -40,7 +40,7 @@
 		.login-content {
 			width: 100% !important;
 			height: 100% !important;
-			padding: 20px 0 !important;
+			padding: 20px !important;
 			border-radius: 0 !important;
 			box-shadow: unset !important;
 			border: none !important;
@@ -49,6 +49,15 @@
 			display: flex !important;
 		}
 	}
+	// 电话控件不显示
+	.phoneControls{
+		display: none !important;
+		width: 0 !important;
+	}
+	.seizeSeat-box{
+		display: block !important;
+		width: 100% !important;
+	}
 }
 
 /* 页面宽度小于375px

+ 10 - 10
src/utils/appConfig.ts

@@ -4,7 +4,7 @@
  * @version: 
  * @Date: 2022-10-26 13:55:31
  * @LastEditors: Please set LastEditors
- * @LastEditTime: 2022-10-26 15:00:03
+ * @LastEditTime: 2022-11-09 14:24:41
  */
 interface appConfigState{
     apiUrl:string,// 基础请求地址
@@ -27,10 +27,10 @@ switch (import.meta.env.VITE_MODE_NAME) {
             socketUrl:'http://192.168.100.223:50110/hubs/callcenter',
             logKey:'BrXoFNY0kBtPAHtIegYX1dQdKWhtyyMMLfcF03L9',
             logServerUrl:'http://log.fw.com',
-            sendLog:true,
+            sendLog:false,
             clientLog:true,
-            globalTitle:"呼叫中心", 
-            globalViceTitle:'呼叫中心', 
+            globalTitle:"12345", 
+            globalViceTitle:'12345', 
         }
         break;
     case 'test': // 测试环境
@@ -42,8 +42,8 @@ switch (import.meta.env.VITE_MODE_NAME) {
             logServerUrl:'http://log.fw.com',
             sendLog:true,
             clientLog:true,
-            globalTitle:"呼叫中心",
-            globalViceTitle:'呼叫中心',
+            globalTitle:"12345",
+            globalViceTitle:'12345',
         }
         break;
     case 'production': // 生产环境
@@ -55,8 +55,8 @@ switch (import.meta.env.VITE_MODE_NAME) {
             logServerUrl:'http://log.fw.com',
             sendLog:true,
             clientLog:true,
-            globalTitle:"呼叫中心",
-            globalViceTitle:'呼叫中心',
+            globalTitle:"12345",
+            globalViceTitle:'12345',
         }
         break;
     default:
@@ -68,8 +68,8 @@ switch (import.meta.env.VITE_MODE_NAME) {
             logServerUrl:'http://log.fw.com',
             sendLog:true,
             clientLog:true,
-            globalTitle:"呼叫中心",
-            globalViceTitle:'呼叫中心',
+            globalTitle:"12345",
+            globalViceTitle:'12345',
         }
         break;
 }

+ 6 - 6
src/utils/formatTime.ts

@@ -126,12 +126,12 @@ export function formatPast(param: string | Date, format: string = 'YYYY-mm-dd'):
  */
 export function formatAxis(param: Date): string {
 	let hour: number = new Date(param).getHours();
-	if (hour < 6) return '凌晨好';
-	else if (hour < 9) return '早上好';
+	// if (hour < 6) return '凌晨好';
+	if (hour < 9) return '早上好';
 	else if (hour < 12) return '上午好';
-	else if (hour < 14) return '中午好';
-	else if (hour < 17) return '下午好';
-	else if (hour < 19) return '傍晚好';
-	else if (hour < 22) return '晚上好';
+	// else if (hour < 14) return '中午好';
+	else if (hour < 18) return '下午好';
+	// else if (hour < 19) return '傍晚好';
+	else if (hour < 24) return '晚上好';
 	else return '夜里好';
 }

+ 19 - 16
src/utils/getStyleSheets.ts

@@ -1,26 +1,29 @@
 import { nextTick } from 'vue';
 import * as svg from '@element-plus/icons-vue';
-
+import tsconfig from '/@/theme/iconfont/iconfont.json'; // 读取本地json文件
 // 获取阿里字体图标
 const getAlicdnIconfont = () => {
 	return new Promise((resolve, reject) => {
 		nextTick(() => {
-			const styles: any = document.styleSheets;
-			let sheetsList = [];
+			// const styles: any = document.styleSheets;
+			// let sheetsList = [];
 			let sheetsIconList = [];
-			for (let i = 0; i < styles.length; i++) {
-				if (styles[i].href && styles[i].href.indexOf('at.alicdn.com') > -1) {
-					sheetsList.push(styles[i]);
-				}
-			}
-			for (let i = 0; i < sheetsList.length; i++) {
-				for (let j = 0; j < sheetsList[i].cssRules.length; j++) {
-					if (sheetsList[i].cssRules[j].selectorText && sheetsList[i].cssRules[j].selectorText.indexOf('.icon-') > -1) {
-						sheetsIconList.push(
-							`${sheetsList[i].cssRules[j].selectorText.substring(1, sheetsList[i].cssRules[j].selectorText.length).replace(/\:\:before/gi, '')}`
-						);
-					}
-				}
+			// for (let i = 0; i < styles.length; i++) {
+			// 	if (styles[i].href && styles[i].href.indexOf('at.alicdn.com') > -1) {
+			// 		sheetsList.push(styles[i]);
+			// 	}
+			// }
+			// for (let i = 0; i < sheetsList.length; i++) {
+			// 	for (let j = 0; j < sheetsList[i].cssRules.length; j++) {
+			// 		if (sheetsList[i].cssRules[j].selectorText && sheetsList[i].cssRules[j].selectorText.indexOf('.icon-') > -1) {
+			// 			sheetsIconList.push(
+			// 				`${sheetsList[i].cssRules[j].selectorText.substring(1, sheetsList[i].cssRules[j].selectorText.length).replace(/\:\:before/gi, '')}`
+			// 			);
+			// 		}
+			// 	}
+			// }
+			for (let i of tsconfig.glyphs){
+				sheetsIconList.push('icon-'+i.font_class)
 			}
 			if (sheetsIconList.length > 0) resolve(sheetsIconList);
 			else reject('未获取到值,请刷新重试');

+ 1 - 0
src/utils/other.ts

@@ -31,6 +31,7 @@ export function useTitle() {
 	nextTick(() => {
 		let webTitle = '';
 		let globalTitle: string = themeConfig.value.globalTitle;
+		
 		const { path, meta } = router.currentRoute.value;
 		if (path === '/login') {
 			webTitle = <any>meta.title;

+ 1 - 3
src/utils/request.ts

@@ -4,12 +4,11 @@
  * @version: 
  * @Date: 2022-08-09 16:19:57
  * @LastEditors: Please set LastEditors
- * @LastEditTime: 2022-10-26 14:24:11
+ * @LastEditTime: 2022-11-08 15:59:43
  */
 import axios, {AxiosInstance, AxiosResponse} from 'axios';
 import { ElMessage, ElMessageBox } from 'element-plus';
 import { Session } from '/@/utils/storage';
-
 //exception log
 import { Exceptionless } from "@exceptionless/browser";
 // 全局配置
@@ -84,7 +83,6 @@ service.interceptors.response.use(
 				ElMessage.error(error.response.data.error);
 			} else ElMessage.error('接口路径找不到');
 		}
-		
 		return Promise.reject(error);
 	}
 );

+ 9 - 1
src/utils/setIconfont.ts

@@ -1,6 +1,14 @@
+/*
+ * @Author: zc
+ * @Description:  字体图标引入地址
+ * @version: 
+ * @Date: 2022-10-21 09:01:23
+ * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-11-08 15:31:40
+ */
 // 字体图标 url
 const cssCdnUrlList: Array<string> = [
-	// '//at.alicdn.com/t/font_2298093_y6u00apwst.css',
+	// '//at.alicdn.com/t/c/font_3595250_oy8mub9ix5g.css',
 	// '//netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css',
 ];
 // 第三方 js url

+ 2 - 2
src/views/callCenter/blacklist/index.vue

@@ -106,11 +106,11 @@ const handleQuery = throttle(()=> {
 const getList = () => {
 	loading.value = true;
 	blacklistPaged(queryParams.value).then((response: any) => {
-		list.value = response.content.items;
+		list.value = response?.content.items;
 		for (let i of list.value) {
 			i.creationTime = formatDate(new Date(i.creationTime), 'YYYY-mm-dd HH:MM:SS');
 		}
-		total.value = response.content.total;
+		total.value = response?.content.total;
 		setTimeout(() => {
 			loading.value = false;
 		}, 300);

+ 3 - 3
src/views/callCenter/callRecord/index.vue

@@ -4,7 +4,7 @@
  * @version: 
  * @Date: 2022-08-16 13:46:36
  * @LastEditors: Please set LastEditors
- * @LastEditTime: 2022-10-24 17:14:27
+ * @LastEditTime: 2022-11-08 16:05:37
 -->
 <template>
 	<div class="system-user-container">
@@ -83,11 +83,11 @@ const handleQuery = throttle(()=> {
 const getList = () => {
 	loading.value = true;
 	callPaged(queryParams.value).then((response: any) => {
-		list.value = response.content.items;
+		list.value = response?.content.items;
 		for (let i of list.value) {
 			i.creationTime = formatDate(new Date(i.creationTime), 'YYYY-mm-dd HH:MM:SS');
 		}
-		total.value = response.content.total;
+		total.value = response?.content.total;
 		setTimeout(() => {
 			loading.value = false;
 		}, 300);

+ 6 - 6
src/views/callCenter/iverConfig/details.vue

@@ -566,7 +566,7 @@ const confrimReplace = ()=>{ //替换保存
 const getConfig = () => { //获取树形结构和初始化数据
     loading.value = true;
     getIvrTree(route.params.id).then((res: any) => {
-        state.data = res.content;
+        state.data = res?.content ?? [];
         getCenter();
         setTimeout(() => {
             loading.value = false;
@@ -577,17 +577,17 @@ const getConfig = () => { //获取树形结构和初始化数据
 }
 const init=()=>{// 获取页面上初始数据
     getIvrById(route.params.id).then((res: any) => {// 根据分类ID查出分类下所有的ivr  排除根节点
-        state.ivrList = res.content.ivrs.filter((item:any)=>item.id != state.data.id);
+        state.ivrList = res?.content.ivrs.filter((item:any)=>item.id != state.data.id) ?? [];
     })
     getTelsList().then((res: any) => {//查询所有的分机
-        state.telsList = res.content;
+        state.telsList = res?.content ?? [];
     })
     getTelsGroupList().then((res: any) => { // 查询所有的分机组
-        state.telsGroup = res.content;
+        state.telsGroup = res?.content ?? [];
     })
     baseInfo().then((res: any) => {// 获取页面基础信息
-        state.ivrAnswerTypes = res.content.ivrAnswerTypes;
-        state.ivrStrategeTypes = res.content.ivrStrategeTypes;
+        state.ivrAnswerTypes = res?.content.ivrAnswerTypes ?? [];
+        state.ivrStrategeTypes = res?.content.ivrStrategeTypes ?? [];
     })
     voicequerylist().then((response: any) => {/** 获取所有语音文件列表 */
         state.voiceList = response.content.map((item:any)=>{

+ 1 - 3
src/views/callCenter/iverConfig/index.vue

@@ -112,15 +112,13 @@ const onDelCategroy = (row:any)=>{ //删除分类
 const handleQuery = ()=>{ //查询列表
     loading.value = true;
     getIvrCategories().then((res:any)=>{
-        list.value = res.content;
+        list.value = res?.content ?? [];
         for (let i of list.value) {
             i.creationTime = formatDate(new Date(i.creationTime), 'YYYY-mm-dd HH:MM:SS');
         }
         setTimeout(() => {
 			loading.value = false;
 		}, 300);
-    }).catch(()=>{
-
     })
 }
 const onSubmit = ()=>{// 保存

+ 8 - 8
src/views/callCenter/iverConfig/ivrList.vue

@@ -617,7 +617,7 @@ let ivrAnswerType = ref<any>(0)
 const getList = () => {
     loading.value = true;
     getIvrList().then((response: any) => {
-        list.value = response.content;
+        list.value = response?.content ?? [];
         setTimeout(() => {
 			loading.value = false;
 		}, 300);
@@ -709,7 +709,7 @@ const save = ()=>{ // 保存分机组配置
 let CategorieList = ref<any>([]);
 const getIvrCategorieList = ()=>{ // 获取分类列表
     getIvrCategories().then((res:any)=>{
-        CategorieList.value = res.content;
+        CategorieList.value = res?.content ?? [];
     }).catch(()=>{
 
     })
@@ -717,15 +717,15 @@ const getIvrCategorieList = ()=>{ // 获取分类列表
 const ivrTypes = ref<any>([])
 const getBaseInfo = ()=>{ // 获取页面基础信息
     getTelsList().then((res: any) => {//查询所有的分机
-        state.telsList = res.content;
+        state.telsList = res?.content ?? [];
     })
     getTelsGroupList().then((res: any) => { // 查询所有的分机组
-        state.telsGroup = res.content;
+        state.telsGroup = res?.content ?? [];
     })
     baseInfo().then((res: any) => {// 获取页面基础信息
-        ivrTypes.value = res.content.ivrTypes;
-        state.ivrAnswerTypes = res.content.ivrAnswerTypes;
-        state.ivrStrategeTypes = res.content.ivrStrategeTypes;
+        ivrTypes.value = res?.content.ivrTypes ?? [];
+        state.ivrAnswerTypes = res?.content.ivrAnswerTypes ?? [];
+        state.ivrStrategeTypes = res?.content.ivrStrategeTypes ?? [];
     })
 }
 
@@ -758,7 +758,7 @@ const currentIvr = ref<any>(undefined);
 const ivrConfigure = (row:any)=>{// 配置策略
     currentIvr.value = JSON.parse(JSON.stringify(row));
     getIvrById(row.ivrCategoryId).then((res: any) => {// 根据分类ID查出分类下所有的ivr  排除根节点
-        state.ivrList = res.content.ivrs.filter((item:any)=>item.id != row.ivrCategoryId);
+        state.ivrList = res?.content.ivrs.filter((item:any)=>item.id != row.ivrCategoryId) ?? [];
     });
     state.form1 = {
         ivr:null,

+ 4 - 4
src/views/callCenter/systemParameter/index.vue

@@ -1,8 +1,8 @@
 <template>
     <div class="systemParameter">
-        <el-card shadow="hover" v-loading="loading">
-			<template v-if="list.length" >
-			<el-form :model="ruleForm" label-width="200px" ref="ruleFormRef">
+        <el-card shadow="hover">
+			<template v-if="list.length">
+			<el-form :model="ruleForm" label-width="200px" ref="ruleFormRef" v-loading="loading">
 				<el-row :gutter="35">
 						<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" v-for="(items) in list" :key="items.id">
 							<el-divider content-position="left">{{items.groupName}}</el-divider>
@@ -129,7 +129,7 @@ const getSetList = ()=>{//获取参数列表
 	loading.value = true;
 	arr.value = [];
     getsyssettings().then((res:any)=>{
-        list.value = res.content;
+        list.value = res?.content ?? [];
 		for(let j of list.value){
 			for(let i of j.systemSettings){
 				arr.value.push({

+ 2 - 2
src/views/callCenter/tels/index.vue

@@ -4,7 +4,7 @@
  * @version: 
  * @Date: 2022-08-16 13:42:46
  * @LastEditors: Please set LastEditors
- * @LastEditTime: 2022-10-24 17:11:15
+ * @LastEditTime: 2022-11-08 16:05:56
 -->
 <template>
     <div class="tels">
@@ -47,7 +47,7 @@ const getList = () => {
     loading.value = true;
     getTelsList()
         .then((response: any) => {
-            list.value = response.content;
+            list.value = response?.content ?? [];
             for (let i of list.value) {
                 i.creationTime = formatDate(new Date(i.creationTime), 'YYYY-mm-dd HH:MM:SS');
             }

+ 3 - 3
src/views/callCenter/telsGroup/index.vue

@@ -160,14 +160,14 @@ const getAudioList = () => {
         loading.value = false;
     });
     baseInfoTelsGroup().then((res: any) => {// 获取页面基础信息
-        state.distributions = res.content.distributions;
+        state.distributions = res?.content.distributions ?? [];
     })
 };
 /** 获取分机列表 */
 const getList = () => {
     loading.value = true;
     getTelsGroupList().then((response: any) => {
-        list.value = response.content;
+        list.value = response?.content ?? [];
         for(let i of list.value){
             i.voiceList = i.voice ? i.voice.split('+') : [];
             i.creationTime = formatDate(new Date(i.creationTime),'YYYY-mm-dd HH:MM:SS');
@@ -219,7 +219,7 @@ const onAddTelsGroup = ()=>{//新增分机组
 /** 获取分机列表 */
 const getTelList = () => {
     getTelsList().then((response: any) => {
-        data.value = response.content;
+        data.value = response?.content ?? [];
     }).catch(() => {
         
     });

+ 6 - 5
src/views/home/index.vue

@@ -4,11 +4,12 @@
  * @version: 
  * @Date: 2022-08-09 16:19:57
  * @LastEditors: Please set LastEditors
- * @LastEditTime: 2022-10-26 14:48:50
+ * @LastEditTime: 2022-11-09 10:12:42
 -->
 <template>
-	<div class="error layout-view-bg-white" :style="{ height: `calc(100vh - ${initTagViewHeight}` }">
-		<div class="error-flex">
+	<div class="error" :style="{ height: `calc(100vh - ${initTagViewHeight}` }">
+		<el-card>
+			<div class="error-flex">
 			<div class="left">
 				<div class="left-item">
 					<div class="left-item-animation left-item-num">资源建设中~</div>
@@ -19,6 +20,7 @@
 				<img v-lazy="src"  alt=""/>
 			</div>
 		</div>
+		</el-card>
 	</div>
 </template>
 
@@ -49,8 +51,7 @@ import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes';
 <style scoped lang="scss">
 .error {
 	height: 100%;
-	background-color: var(--el-color-white);
-	display: flex;
+	width: 100%;
 	.error-flex {
 		margin: auto;
 		display: flex;

+ 65 - 28
src/views/login/component/account.vue

@@ -1,17 +1,17 @@
 <template>
-	<el-form size="large" class="login-content-form"  ref="ruleFormRef" :model="ruleForm" @submit.native.prevent>
-		<el-form-item class="login-animation1" prop="username" :rules="[{ required: true, message: '请输入账号', trigger: 'blur' }]">
-			<el-input type="text" placeholder="请输入账号" v-model="ruleForm.username" clearable @keyup.enter="onSignIn(ruleFormRef)" autocomplete="off">
+	<el-form size="large" class="login-content-form" ref="ruleFormRef" :model="ruleForm" @submit.native.prevent>
+		<el-form-item class="login-animation1 mb30" prop="username" :rules="[{ required: true, message: '请输入账号', trigger: 'blur' }]">
+			<el-input type="text" class="inputDeep" placeholder="请输入账号" v-model="ruleForm.username" clearable @keyup.enter="onSignIn(ruleFormRef)" autocomplete="off">
 				<template #prefix>
 					<el-icon class="el-input__icon">
-						<ele-Cellphone />
+						<ele-User />
 					</el-icon>
 					<!-- <i class="iconfont icon-tongzhi1"></i> -->
 				</template>
 			</el-input>
 		</el-form-item>
-		<el-form-item class="login-animation2" prop="password" :rules="[{required: true,message: '请输入密码',trigger: 'blur'}]">
-			<el-input :type="isShowPassword ? 'text' : 'password'" placeholder="请输入密码" v-model="ruleForm.password" @keyup.enter="onSignIn(ruleFormRef)"
+		<el-form-item class="login-animation2 mb30" prop="password" :rules="[{required: true,message: '请输入密码',trigger: 'blur'}]">
+			<el-input class="inputDeep" clearable :type="isShowPassword ? 'text' : 'password'" placeholder="请输入密码" v-model="ruleForm.password" @keyup.enter="onSignIn(ruleFormRef)"
 				autocomplete="off">
 				<template #prefix>
 					<el-icon class="el-input__icon">
@@ -40,12 +40,16 @@
 			</el-col>
 		</el-form-item> -->
 		<el-form-item class="login-animation4">
-			<el-button type="primary" class="login-content-submit" round @click="onSignIn(ruleFormRef)" v-waves="'light'" :loading="loading.signIn" >
-				<span>登 录</span>
-			</el-button> 
+			<el-button type="primary" class="login-content-submit" round @click="onSignIn(ruleFormRef)" v-waves="'light'" :loading="loading.signIn">登录</el-button> 
 		</el-form-item>
-		<div class="font12 mt30 login-animation4 login-msg">
+		<!-- <div class="font12 mt30 login-animation4 login-msg">
 			* 温馨提示:建议使用谷歌、Microsoft Edge,版本 79.0.1072.62 及以上浏览器,360浏览器请使用极速模式
+		</div> -->
+		<div class="login-msg login-animation4">
+			<div>
+				联系管理员<b>重置密码</b>
+			</div>
+			<div>忘记密码</div>
 		</div>
 	</el-form>
 </template>
@@ -64,7 +68,7 @@ import { formatAxis } from '/@/utils/formatTime';
 import { NextLoading } from '/@/utils/loading';
 import Watermark from '/@/utils/wartermark';
 import type { FormInstance } from 'element-plus';
-import { signIn } from '/@/api/login';
+import { signIn,pwdCheck } from '/@/api/login';
 // 登录参数类型
 interface LoginState {
 	grant_type: string;
@@ -112,17 +116,7 @@ export default defineComponent({
 						Session.set('token', res.access_token);
 						// 模拟数据,对接接口时,记得删除多余代码及对应依赖的引入。用于 `/src/stores/userInfo.ts` 中不同用户登录判断(模拟数据)
 						Cookies.set('userName', state.ruleForm.username);
-						if (!themeConfig.value.isRequestRoutes) {
-							// 前端控制路由,2、请注意执行顺序
-							await initFrontEndControlRoutes();
-							signInSuccess();
-						} else {
-							// 模拟后端控制路由,isRequestRoutes 为 true,则开启后端控制路由
-							// 添加完动态路由,再进行 router 跳转,否则可能报错 No match found for location with path "/"
-							await initBackEndControlRoutes();
-							// 执行完 initBackEndControlRoutes,再执行 signInSuccess
-							signInSuccess();
-						}
+						checkPwdStatus(); //检查密码修改状态
 					}).catch(()=>{
 						state.loading.signIn = false;
 					})
@@ -130,7 +124,6 @@ export default defineComponent({
 					console.log('error submit!', fields)
 				}
 			})
-			
 		};
 		// 登录成功后的跳转
 		const signInSuccess = () => {
@@ -159,8 +152,27 @@ export default defineComponent({
 			const signInText = '欢迎回来!';
 			ElMessage.success(`${currentTimeInfo},${signInText}`);
 			NextLoading.start();
-
 		};
+		// 登录后检查密码是否修改过 入未修改直接跳转到修改密码页面
+		const checkPwdStatus = ()=>{
+			pwdCheck().then(async (res:any)=>{
+				if(res.result){// 修改过 直接进入系统
+					if (!themeConfig.value.isRequestRoutes) {
+						// 前端控制路由,2、请注意执行顺序
+						await initFrontEndControlRoutes();
+						signInSuccess();
+					} else {
+						// 模拟后端控制路由,isRequestRoutes 为 true,则开启后端控制路由
+						// 添加完动态路由,再进行 router 跳转,否则可能报错 No match found for location with path "/"
+						await initBackEndControlRoutes();
+						// 执行完 initBackEndControlRoutes,再执行 signInSuccess
+						signInSuccess();
+					}
+				}else{// 没有修改过 跳转到修改密码页面
+					
+				}
+			})
+		}
 		return {
 			onSignIn,
 			ruleFormRef,
@@ -171,9 +183,23 @@ export default defineComponent({
 </script>
 
 <style scoped lang="scss">
+
+.inputDeep {
+  :deep(.el-input__wrapper) {
+    box-shadow: 0 0 0 0 var(--el-input-border-color, var(--el-border-color)) inset;
+	border-radius: 0;
+	border-bottom: 1px solid var(--el-input-border-color, var(--el-border-color));
+  }
+}
 .login-content-form {
 	margin-top: 20px;
-
+	font-size: 16px;
+	:deep(.el-input--large) {
+		font-size: 16px;
+	}
+	:deep(.el-form-item__error) {
+		font-size: 14px;
+	}
 	@for $i from 1 through 4 {
 		.login-animation#{$i} {
 			opacity: 0;
@@ -203,13 +229,24 @@ export default defineComponent({
 
 	.login-content-submit {
 		width: 100%;
-		letter-spacing: 2px;
 		font-weight: 300;
-		margin-top: 15px;
+		margin-top: 85px;
+		height: 60px;
+		border-radius: 30px;
+		font-size: 18px;
+		letter-spacing: 5px;
 	}
 
 	.login-msg {
-		color: var(--el-text-color-placeholder);
+		margin-top: 39px;
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+		color: var(--next--login-text-color);
+		b{
+			color: #999;
+			padding-left: 4px;
+		}
 	}
 }
 </style>

+ 293 - 0
src/views/login/component/changePwd.vue

@@ -0,0 +1,293 @@
+<template>
+	<el-form size="large" class="login-content-form" ref="ruleFormRef" :model="ruleForm" @submit.native.prevent label-width="100px">
+		<el-form-item class="login-animation1" label="旧密码" prop="username" :rules="[{ required: true, message: '请输入旧密码', trigger: 'blur' }]">
+			<el-input type="password" class="inputDeep"  placeholder="请输入旧密码" show-password v-model="ruleForm.username" clearable @keyup.enter="onSignIn(ruleFormRef)" autocomplete="off">
+				<template #prefix>
+					<el-icon class="el-input__icon">
+						<ele-Unlock />
+					</el-icon>
+				</template>
+			</el-input>
+		</el-form-item>
+		<el-form-item class="login-animation2" prop="password"  label="新密码" :rules="[{required: true,validator: checkPassword,trigger: ['change','blur']}]">
+			<el-input class="inputDeep" clearable type="password" show-password placeholder="请输入新密码" v-model="ruleForm.password" @keyup.enter="onSignIn(ruleFormRef)"
+				autocomplete="off">
+				<template #prefix>
+					<el-icon class="el-input__icon">
+						<ele-Unlock />
+					</el-icon>
+				</template>
+			</el-input>
+            <div class="intensity login-animation4">
+                <span class="psdText">密码强度:{{modes === 1 ? '低' : modes === 2 ? '中' : modes === 3 ? '高' : ''}}</span>
+                <span
+                    class="line"
+                    :class="modes === 1 ? 'low' : ''"
+                ></span>
+                <span
+                    class="line"
+                    :class="modes === 2 ? 'middle' : ''"
+                ></span>
+                <span
+                    class="line"
+                    :class="modes === 3 ? 'high' : ''"
+                ></span>
+            </div>
+		</el-form-item>
+        <el-form-item prop="confirmPwd" label="确认密码" class="login-animation2" :rules="[{required: true,validator: checkConfirmPassword,trigger: 'blur'}]">
+            <el-input class="inputDeep" clearable type="password" show-password placeholder="请再次输入密码" v-model="ruleForm.confirmPwd" @keyup.enter="onSignIn(ruleFormRef)"
+                autocomplete="off">
+                <template #prefix>
+                    <el-icon class="el-input__icon">
+                        <ele-Unlock />
+                    </el-icon>
+                </template>
+            </el-input>
+      </el-form-item>
+		<el-form-item class="login-animation4">
+			<el-button type="primary" class="login-content-submit" round @click="onSignIn(ruleFormRef)" v-waves="'light'" :loading="loading.signIn">登录</el-button> 
+		</el-form-item>
+	</el-form>
+</template>
+
+<script lang="ts">
+import { toRefs, reactive, defineComponent, computed, ref } from 'vue';
+import { useRoute, useRouter } from 'vue-router';
+import { ElMessage } from 'element-plus';
+import Cookies from 'js-cookie';
+import { storeToRefs } from 'pinia';
+import { useThemeConfig } from '/@/stores/themeConfig';
+import { initFrontEndControlRoutes } from '/@/router/frontEnd';
+import { initBackEndControlRoutes } from '/@/router/backEnd';
+import { Session, Local } from '/@/utils/storage';
+import { formatAxis } from '/@/utils/formatTime';
+import { NextLoading } from '/@/utils/loading';
+import Watermark from '/@/utils/wartermark';
+import type { FormInstance } from 'element-plus';
+import { signIn } from '/@/api/login';
+// 登录参数类型
+interface LoginState {
+	grant_type: string;
+	client_id:string;
+	client_secret:string;
+	username:string;
+	password:string;
+    confirmPwd:string
+}
+export default defineComponent({
+	name: 'changePwd',
+	setup() {
+		const storesThemeConfig = useThemeConfig();
+		const { themeConfig } = storeToRefs(storesThemeConfig);
+		const route = useRoute();
+		const router = useRouter();
+		const state = reactive({
+			ruleForm: {
+				username: '',
+				password: '',
+                confirmPwd:''
+			},
+			loading: {
+			signIn: false,
+			},
+		});
+		const ruleFormRef = ref<FormInstance>()
+		// 时间获取
+		const currentTime = computed(() => {
+			return formatAxis(new Date());
+		});
+		// 存储布局配置
+		const setLocalThemeConfig = () => {
+			Local.remove('themeConfig');
+			Local.set('themeConfig', themeConfig.value);
+		};
+		// 登录
+		const onSignIn = async (formEl: FormInstance | undefined) => {
+			if (!formEl) return
+			await formEl.validate((valid, fields) => {
+				if (valid) {
+					state.loading.signIn = true;
+					let req:LoginState = Object.assign({grant_type:'password',client_id:'hotline_admin',client_secret:'8c6c0b2b-6fd8-401c-849c-95888f4248ed'},state.ruleForm);
+					signIn(req).then(async (res:any)=>{//登录
+						// 存储 token 到浏览器缓存
+						Session.set('token', res.access_token);
+						// 模拟数据,对接接口时,记得删除多余代码及对应依赖的引入。用于 `/src/stores/userInfo.ts` 中不同用户登录判断(模拟数据)
+						Cookies.set('userName', state.ruleForm.username);
+						if (!themeConfig.value.isRequestRoutes) {
+							// 前端控制路由,2、请注意执行顺序
+							await initFrontEndControlRoutes();
+							signInSuccess();
+						} else {
+							// 模拟后端控制路由,isRequestRoutes 为 true,则开启后端控制路由
+							// 添加完动态路由,再进行 router 跳转,否则可能报错 No match found for location with path "/"
+							await initBackEndControlRoutes();
+							// 执行完 initBackEndControlRoutes,再执行 signInSuccess
+							signInSuccess();
+						}
+					}).catch(()=>{
+						state.loading.signIn = false;
+					})
+				} else {
+					console.log('error submit!', fields)
+				}
+			})
+			
+		};
+		// 登录成功后的跳转
+		const signInSuccess = () => {
+			// 初始化登录成功时间问候语
+			let currentTimeInfo = currentTime.value;
+			// 登录成功,跳到转首页
+			// 如果是复制粘贴的路径,非首页/登录页,那么登录成功后重定向到对应的路径中
+			if (route.query?.redirect) {
+				router.push({
+					path: <string>route.query?.redirect,
+					query: Object.keys(<string>route.query?.params).length > 0 ? JSON.parse(<string>route.query?.params) : '',
+				});
+			} else {
+				router.push('/');
+			}
+
+			// 设置水印
+			themeConfig.value.isWartermark = true;
+			themeConfig.value.wartermarkText = state.ruleForm.username;
+			Watermark.set(state.ruleForm.username)
+			setLocalThemeConfig();
+
+			// 登录成功提示
+			// 关闭 loading
+			state.loading.signIn = true;
+			const signInText = '欢迎回来!';
+			ElMessage.success(`${currentTimeInfo},${signInText}`);
+			NextLoading.start();
+		};
+        //  检查密码强度
+		let modes = ref<number>(0);
+        const checkPassword = (rule:any,value:string, callback:Function)=>{
+            if (!value) {
+                modes.value = 0;
+                return callback('新密码不能为空')
+            }
+            if (value.length < 8) {
+                modes.value = 0;
+                return callback('新密码不少于8位')
+            }
+			/*
+				最短8位, {6,}
+				可以包含小写大母 [a-z] 和大写字母 [A-Z]
+				可以包含数字 [0-9]
+				可以包含下划线 [ _ ] 和减号 [ - ]
+			*/
+			if (/^[\w_-]{6,}$/.test(state.ruleForm.password)) {
+                modes.value = 1; 
+            }
+			/*
+				最短8位, {8,}
+				必须包含1个数字
+				必须包含1个小写字母
+				必须包含1个大写字母
+				必须包含1个特殊字符
+			*/
+			if (/^\S*(?=\S{8,})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])(?=\S*[!@#$%^&*.?])\S*$/.test(state.ruleForm.password)) modes.value  = 2 ; //中等
+			/*
+				最短8位, {8,}
+				必须包含1个数字
+				必须包含1个小写字母
+				必须包含1个大写字母
+				必须包含2个特殊字符
+			*/
+            if (/^\S*(?=\S{8,})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])(?=\S*[!@#$%^&*.?]{2,})\S*$/.test(state.ruleForm.password)) modes.value  = 3; //强密码
+            if(modes.value == 0 || modes.value == 1){
+                return callback('提示:密码不得少于8位数,且必须包含字母大小写和特殊字符') //弱密码
+            }
+            console.log(modes.value)
+            return callback()
+        }
+        // 检查输入密码是否一致
+        const  checkConfirmPassword =(rule:any,value:string, callback:Function)=>{
+            if (!value) {
+                return callback('请再次输入密码')
+            }
+            if (value != state.ruleForm.password) {
+                return callback('两次密码输入不一致,请重新输入')
+            }
+        }
+		return {
+			onSignIn,
+			ruleFormRef,
+			modes,
+            checkPassword,
+            checkConfirmPassword,
+			...toRefs(state),
+		};
+	},
+});
+</script>
+
+<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: 20px;
+		cursor: pointer;
+		&:hover {
+			color: #909399;
+		}
+	}
+
+	.login-content-code {
+		width: 100%;
+		padding: 0;
+		font-weight: bold;
+		letter-spacing: 5px;
+	}
+
+	.login-content-submit {
+		width: 100%;
+		font-weight: 300;
+		margin-top: 15px;
+	}
+
+	.login-msg {
+		color: var(--el-text-color-placeholder);
+	}
+    .intensity {
+    .psdText {
+        font-size: 14px;
+        margin-right: 10px;
+        color: #5a5a5a;
+    }
+    .line {
+        display: inline-block;
+        width: 48px;
+        height: 4px;
+        background: #d8d8d8;
+        border-radius: 3px;
+        margin-right: 8px;
+        &.low {
+            background: #f4664a;
+        }
+        &.middle {
+            background: #ffb700;
+        }
+        &.high {
+            background: #2cbb79;
+        }
+    }
+    .level {
+        margin: 0 16px 0 8px;
+    }
+    }
+}
+</style>

+ 16 - 70
src/views/login/index.vue

@@ -1,15 +1,9 @@
 <template>
 	<div class="login-container">
-		<div class="login-icon-group">
-			<div class="login-icon-group-title">
-				<img :src="logoMini"  alt=""/>
-				<div class="login-icon-group-title-text font25">{{ getThemeConfig.globalViceTitle }}</div>
-			</div>
-			<img :src="loginIconTwo" class="login-icon-group-icon"  alt=""/>
-		</div>
 		<div class="login-content">
 			<div class="login-content-main">
-				<h4 class="login-content-title ml15">{{ getThemeConfig.globalTitle }}</h4>
+				<!-- <h4 class="login-content-title ml15">{{ getThemeConfig.globalTitle }}</h4> -->
+				<h4 class="login-content-title ml15">账户登录</h4>
 				<div v-if="!isScan">
 					<el-tabs v-model="tabsActiveName">
 						<!-- <el-tab-pane label="账号密码登录" name="account"> -->
@@ -37,8 +31,8 @@ import { useThemeConfig } from '/@/stores/themeConfig';
 import logoMini from '/@/assets/logo-mini.svg';
 import loginIconTwo from '/@/assets/login-icon-two.svg';
 import { NextLoading } from '/@/utils/loading';
-import Account from '/@/views/login/component/account.vue';
 import { Local } from '/@/utils/storage';
+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 Watermark from '/@/utils/wartermark';
@@ -51,7 +45,7 @@ interface LoginState {
 
 export default defineComponent({
 	name: 'loginIndex',
-	components: { Account,
+	components: { Account
     // Mobile, Scan
   },
 	setup() {
@@ -88,80 +82,32 @@ export default defineComponent({
 	width: 100%;
 	height: 100%;
 	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;
-		}
-	}
+	background-image: url('../../assets/images/login/bg.png');
 	.login-content {
 		width: 500px;
-		padding: 20px;
+		padding:83px 80px 60px 80px;
 		position: absolute;
 		right: 200px;
 		top: 50%;
 		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;
+		// border: 5px solid var(--el-color-primary-light-8);
+		border-radius: 20px;
 		overflow: hidden;
 		z-index: 1;
-		height: 460px;
+		height: 600px;
+		box-shadow: 0px 0px 20px 0px rgba(26,64,144,0.46);
 		.login-content-main {
 			margin: 0 auto;
-			width: 80%;
-			.login-content-title {
-				color: var(--el-text-color-primary);
+			.login-content-title {			
+				color: var(--next--login-text-color);
+				font-size: 28px;
+				font-weight: 500;
+				font-family: Source Han Sans CN;
+				line-height: 48px;
 				font-weight: 500;
-				font-size: 22px;
 				text-align: center;
 				letter-spacing: 4px;
-				margin: 15px 0 30px;
 				white-space: nowrap;
 				z-index: 5;
 				position: relative;

+ 11 - 9
src/views/system/menu/component/addMenu.vue

@@ -1,7 +1,7 @@
 <template>
 	<div class="system-add-menu-container">
-		<el-dialog title="新增菜单" v-model="isShowDialog" width="769px">
-			<el-form :model="ruleForm" size="default" label-width="80px">
+		<el-dialog title="新增菜单" v-model="isShowDialog" width="769px" draggable>
+			<el-form :model="ruleForm" 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="上级菜单">
@@ -51,7 +51,7 @@
 						</el-col>
 						<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
 							<el-form-item label="菜单图标">
-								<IconSelector placeholder="请输入菜单图标" v-model="ruleForm.meta.icon" type="all" />
+								<IconSelector placeholder="请输入菜单图标" v-model="ruleForm.meta.icon" type="all"/>
 							</el-form-item>
 						</el-col>
 						<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
@@ -132,8 +132,8 @@
 			</el-form>
 			<template #footer>
 				<span class="dialog-footer">
-					<el-button @click="onCancel" size="default">取 消</el-button>
-					<el-button type="primary" @click="onSubmit" size="default">新 增</el-button>
+					<el-button @click="onCancel">取 消</el-button>
+					<el-button type="primary" @click="onSubmit">新 增</el-button>
 				</span>
 			</template>
 		</el-dialog>
@@ -146,6 +146,7 @@ import { storeToRefs } from 'pinia';
 import { useRoutesList } from '/@/stores/routesList';
 import IconSelector from '/@/components/iconSelector/index.vue';
 // import { setBackEndControlRefreshRoutes } from "/@/router/backEnd";
+import {getMenuList} from "/@/api/system/menu";
 
 export default defineComponent({
 	name: 'systemAddMenu',
@@ -179,12 +180,11 @@ export default defineComponent({
 			},
 			menuData: [], // 上级菜单数据
 		});
-		// 获取 vuex 中的路由
+		// 获取全部菜单
 		const getMenuData = (routes: any) => {
 			const arr: any = [];
 			routes.map((val: any) => {
-				val['title'] = val.meta.title;
-				val['id'] = Math.random();
+				val['title'] = val.pageName;
 				arr.push({ ...val });
 				if (val.children) getMenuData(val.children);
 			});
@@ -214,7 +214,9 @@ export default defineComponent({
 		};
 		// 页面加载时
 		onMounted(() => {
-			state.menuData = getMenuData(routesList.value);
+			getMenuList().then((res:any)=>{
+				state.menuData = getMenuData(res.result);
+			})
 		});
 		return {
 			openDialog,

+ 4 - 4
src/views/system/menu/component/editMenu.vue

@@ -1,7 +1,7 @@
 <template>
 	<div class="system-edit-menu-container">
-		<el-dialog title="修改菜单" v-model="isShowDialog" width="769px">
-			<el-form :model="ruleForm" size="default" label-width="80px">
+		<el-dialog title="修改菜单" v-model="isShowDialog" width="769px" draggable>
+			<el-form :model="ruleForm" 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="上级菜单">
@@ -132,8 +132,8 @@
 			</el-form>
 			<template #footer>
 				<span class="dialog-footer">
-					<el-button @click="onCancel" size="default">取 消</el-button>
-					<el-button type="primary" @click="onSubmit" size="default">修 改</el-button>
+					<el-button @click="onCancel">取 消</el-button>
+					<el-button type="primary" @click="onSubmit">修 改</el-button>
 				</span>
 			</template>
 		</el-dialog>

+ 31 - 47
src/views/system/menu/index.vue

@@ -1,26 +1,27 @@
+<!--
+ * @Author: zc
+ * @Description: 
+ * @version: 
+ * @Date: 2022-10-21 09:01:23
+ * @LastEditors: 
+ * @LastEditTime: 2022-11-09 17:31:29
+-->
 <template>
 	<div class="system-menu-container">
 		<el-card shadow="hover">
 			<div class="system-menu-search mb15">
-				<el-input size="default" placeholder="请输入菜单名称" style="max-width: 180px"> </el-input>
-				<el-button size="default" type="primary" class="ml10">
-					<el-icon>
-						<ele-Search />
-					</el-icon>
-					查询
-				</el-button>
-				<el-button size="default" type="success" class="ml10" @click="onOpenAddMenu">
+				<el-button type="success" class="ml10" @click="onOpenAddMenu">
 					<el-icon>
 						<ele-FolderAdd />
 					</el-icon>
 					新增菜单
 				</el-button>
 			</div>
-			<el-table :data="menuTableData" style="width: 100%" row-key="path" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }">
+			<el-table :data="menuTableData" style="width: 100%" row-key="id" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }">
 				<el-table-column label="菜单名称" show-overflow-tooltip>
 					<template #default="scope">
-						<SvgIcon :name="scope.row.meta.icon" />
-						<span class="ml10">{{ scope.row.meta.title }}</span>
+						<SvgIcon :name="scope.row.icon"/>
+						<span class="ml10">{{ scope.row.pageName }}</span>
 					</template>
 				</el-table-column>
 				<el-table-column prop="path" label="路由路径" show-overflow-tooltip></el-table-column>
@@ -29,11 +30,6 @@
 						<span>{{ scope.row.component }}</span>
 					</template>
 				</el-table-column>
-				<el-table-column label="权限标识" show-overflow-tooltip>
-					<template #default="scope">
-						<span>{{ scope.row.meta.roles }}</span>
-					</template>
-				</el-table-column>
 				<el-table-column label="排序" show-overflow-tooltip width="80">
 					<template #default="scope">
 						{{ scope.$index }}
@@ -41,14 +37,13 @@
 				</el-table-column>
 				<el-table-column label="类型" show-overflow-tooltip width="80">
 					<template #default="scope">
-						<el-tag type="success" size="small">{{ scope.row.xx }}菜单</el-tag>
+						<el-tag type="success">{{ scope.row.xx }}菜单</el-tag>
 					</template>
 				</el-table-column>
-				<el-table-column label="操作" show-overflow-tooltip width="140">
+				<el-table-column label="操作" show-overflow-tooltip width="160" align="center">
 					<template #default="scope">
-						<el-button size="small" text type="primary" @click="onOpenAddMenu">新增</el-button>
-						<el-button size="small" text type="primary" @click="onOpenEditMenu(scope.row)">修改</el-button>
-						<el-button size="small" text type="primary" @click="onTabelRowDel(scope.row)">删除</el-button>
+						<el-button text type="primary" @click="onOpenEditMenu(scope.row)">修改</el-button>
+						<el-button text type="danger" @click="onTabelRowDel(scope.row)">删除</el-button>
 					</template>
 				</el-table-column>
 			</el-table>
@@ -58,28 +53,23 @@
 	</div>
 </template>
 
-<script lang="ts">
+<script lang="ts" setup name="menuConfig">
 import { ref, toRefs, reactive, computed, defineComponent } from 'vue';
 import { RouteRecordRaw } from 'vue-router';
 import { ElMessageBox, ElMessage } from 'element-plus';
 import { storeToRefs } from 'pinia';
 import { useRoutesList } from '/@/stores/routesList';
+import {getMenuList} from "/@/api/system/menu";
 import AddMenu from '/@/views/system/menu/component/addMenu.vue';
 import EditMenu from '/@/views/system/menu/component/editMenu.vue';
-
-export default defineComponent({
-	name: 'systemMenu',
-	components: { AddMenu, EditMenu },
-	setup() {
 		const stores = useRoutesList();
 		const { routesList } = storeToRefs(stores);
 		const addMenuRef = ref();
 		const editMenuRef = ref();
-		const state = reactive({});
-		// 获取 vuex 中的路由
-		const menuTableData = computed(() => {
-			return routesList.value;
-		});
+		const state = reactive({
+      menuTableData:<any>[], // 获取所有菜单
+    });
+    const {menuTableData} = toRefs(state);
 		// 打开新增菜单弹窗
 		const onOpenAddMenu = () => {
 			addMenuRef.value.openDialog();
@@ -94,21 +84,15 @@ export default defineComponent({
 				confirmButtonText: '删除',
 				cancelButtonText: '取消',
 				type: 'warning',
-			})
-				.then(() => {
+			}).then(() => {
 					ElMessage.success('删除成功');
-				})
-				.catch(() => {});
-		};
-		return {
-			addMenuRef,
-			editMenuRef,
-			onOpenAddMenu,
-			onOpenEditMenu,
-			menuTableData,
-			onTabelRowDel,
-			...toRefs(state),
+				}).catch(() => {});
 		};
-	},
-});
+    // 获取所有菜单
+    const getMenuListApi = ()=>{
+      getMenuList().then((res:any)=>{
+        state.menuTableData = res.result;
+      })
+    }
+getMenuListApi();
 </script>

+ 2 - 2
src/views/system/user/index.vue

@@ -104,11 +104,11 @@ const handleQuery = throttle(()=> {
 const getList = () => {
 	loading.value = true;
 	getUserListPaged(data.queryParams).then((response: any) => {
-		list.value = response.content.items;
+		list.value = response?.content.items;
 		for (let i of list.value) {
 			i.creationTime = formatDate(new Date(i.creationTime), 'YYYY-mm-dd HH:MM:SS');
 		}
-		total.value = response.content.total;
+		total.value = response?.content.total;
 		setTimeout(() => {
 			loading.value = false;
 		}, 300);