Explorar o código

第一阶段迁移组件库 无法正常使用

ys hai 2 semanas
pai
achega
56693a4502

+ 3 - 2
yushu-uivue3/package.json

@@ -28,14 +28,15 @@
     "@codemirror/lang-sql": "^6.10.0",
     "@codemirror/lang-xml": "^6.1.0",
     "@codemirror/theme-one-dark": "^6.1.3",
-    "@element-plus/icons-vue": "2.3.1",
+    "@ant-design/icons-vue": "^7.0.0",
     "@vueup/vue-quill": "1.2.0",
     "@vueuse/core": "13.3.0",
+    "ant-design-vue": "^4.2.0",
     "axios": "1.9.0",
     "clipboard": "2.0.11",
     "codemirror": "^6.0.2",
+    "dayjs": "^1.11.10",
     "echarts": "5.6.0",
-    "element-plus": "2.10.7",
     "file-saver": "2.0.5",
     "fuse.js": "6.6.2",
     "highlight.js": "^11.11.1",

+ 197 - 0
yushu-uivue3/src/assets/styles/ant-design-vue.scss

@@ -0,0 +1,197 @@
+// Ant Design Vue 样式覆盖
+
+// 上传组件样式
+.ant-upload {
+  input[type="file"] {
+    display: none !important;
+  }
+}
+
+.cell {
+  .ant-tag {
+    margin-right: 0px;
+  }
+}
+
+.small-padding {
+  .cell {
+    padding-left: 5px;
+    padding-right: 5px;
+  }
+}
+
+.fixed-width {
+  .ant-btn-sm {
+    padding: 4px 15px;
+    width: 60px;
+  }
+}
+
+.status-col {
+  .cell {
+    padding: 0 10px;
+    text-align: center;
+
+    .ant-tag {
+      margin-right: 0px;
+    }
+  }
+}
+
+// Modal 样式 - 玻璃质感
+.ant-modal {
+  .ant-modal-content {
+    border-radius: 16px !important;
+    background: rgba(255, 255, 255, 0.7) !important;
+    backdrop-filter: blur(20px) saturate(180%) !important;
+    -webkit-backdrop-filter: blur(20px) saturate(180%) !important;
+    box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25) !important;
+    border: 1px solid rgba(255, 255, 255, 0.5) !important;
+    overflow: hidden;
+  }
+
+  .ant-modal-header {
+    background: transparent !important;
+    border-bottom: 1px solid rgba(0, 0, 0, 0.05);
+    padding: 20px 24px !important;
+    
+    .ant-modal-title {
+      font-weight: 600;
+      color: #1e293b;
+    }
+  }
+
+  .ant-modal-close {
+    top: 24px;
+    right: 24px;
+    color: #94a3b8;
+    transition: all 0.3s;
+    
+    &:hover {
+      color: #ef4444;
+      transform: rotate(90deg);
+    }
+  }
+
+  .ant-modal-body {
+    background: transparent !important;
+    padding: 24px !important;
+    color: #334155;
+  }
+
+  .ant-modal-footer {
+    padding: 16px 24px 24px !important;
+    border-top: 1px solid rgba(0, 0, 0, 0.05);
+    background: transparent !important;
+  }
+}
+
+// Drawer 样式 - 玻璃质感
+.ant-drawer {
+  .ant-drawer-content {
+    background: rgba(255, 255, 255, 0.7) !important;
+    backdrop-filter: blur(20px) saturate(180%) !important;
+    -webkit-backdrop-filter: blur(20px) saturate(180%) !important;
+    box-shadow: -10px 0 30px rgba(0, 0, 0, 0.15) !important;
+    border-left: 1px solid rgba(255, 255, 255, 0.5) !important;
+  }
+  
+  .ant-drawer-header {
+    background: transparent !important;
+    margin-bottom: 0 !important;
+    padding: 20px 24px !important;
+    border-bottom: 1px solid rgba(0, 0, 0, 0.05);
+    
+    .ant-drawer-title {
+      font-weight: 600;
+      color: #1e293b;
+      font-size: 18px;
+    }
+    
+    .ant-drawer-close {
+      transition: all 0.3s;
+      &:hover {
+        color: #ef4444;
+        transform: rotate(90deg);
+      }
+    }
+  }
+  
+  .ant-drawer-body {
+    background: transparent !important;
+    padding: 24px !important;
+    color: #334155;
+  }
+
+  .ant-drawer-footer {
+    padding: 16px 24px 24px !important;
+    border-top: 1px solid rgba(0, 0, 0, 0.05);
+    background: transparent !important;
+  }
+}
+
+// 上传容器
+.upload-container {
+  .ant-upload {
+    width: 100%;
+
+    .ant-upload-dragger {
+      width: 100%;
+      height: 200px;
+    }
+  }
+}
+
+// 日期选择器样式修复
+.ant-picker-range {
+  display: inline-flex !important;
+}
+
+// 菜单样式
+.ant-menu {
+  border: none;
+  
+  &.ant-menu-inline-collapsed {
+    .ant-menu-submenu-title {
+      .ant-menu-submenu-arrow {
+        display: none;
+      }
+    }
+  }
+}
+
+// 下拉菜单样式
+.ant-dropdown-menu {
+  a {
+    display: block;
+  }
+}
+
+// Message 样式
+.ant-message {
+  .ant-message-notice {
+    .ant-message-notice-content {
+      border-radius: 12px !important;
+      box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08) !important;
+      border: 1px solid rgba(255, 255, 255, 0.6) !important;
+      padding: 12px 20px !important;
+      min-width: 300px !important;
+      backdrop-filter: blur(12px) !important;
+      -webkit-backdrop-filter: blur(12px) !important;
+      background: rgba(255, 255, 255, 0.95) !important;
+    }
+  }
+}
+
+// Notification 样式
+.ant-notification {
+  .ant-notification-notice {
+    border-radius: 16px !important;
+    border: 1px solid rgba(255, 255, 255, 0.6) !important;
+    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.1) !important;
+    padding: 16px 24px !important;
+    backdrop-filter: blur(16px) !important;
+    -webkit-backdrop-filter: blur(16px) !important;
+    background: rgba(255, 255, 255, 0.95) !important;
+  }
+}

+ 1 - 1
yushu-uivue3/src/assets/styles/index.scss

@@ -1,6 +1,6 @@
 @use './mixin.scss';
 @use './transition.scss';
-@use './element-ui.scss';
+@use './ant-design-vue.scss';
 @use './sidebar.scss';
 @use './btn.scss';
 @use './yushu.scss';

+ 14 - 0
yushu-uivue3/src/components/SvgIcon/antd-icons.js

@@ -0,0 +1,14 @@
+// Ant Design Vue 图标适配器
+import * as Icons from '@ant-design/icons-vue'
+
+export default {
+  install: (app) => {
+    // 注册所有 Ant Design Vue 图标
+    for (const key in Icons) {
+      const component = Icons[key]
+      if (component && component.name) {
+        app.component(component.name, component)
+      }
+    }
+  }
+}

+ 14 - 11
yushu-uivue3/src/main.js

@@ -2,10 +2,13 @@ import { createApp } from 'vue'
 
 import Cookies from 'js-cookie'
 
-import ElementPlus from 'element-plus'
-import 'element-plus/dist/index.css'
-import 'element-plus/theme-chalk/dark/css-vars.css'
-import locale from 'element-plus/es/locale/lang/zh-cn'
+import Antd from 'ant-design-vue'
+import 'ant-design-vue/dist/reset.css'
+import zhCN from 'ant-design-vue/es/locale/zh_CN'
+import dayjs from 'dayjs'
+import 'dayjs/locale/zh-cn'
+
+dayjs.locale('zh-cn')
 
 import '@/assets/styles/index.scss' // global css
 
@@ -21,7 +24,7 @@ import { download } from '@/utils/request'
 // svg图标
 import 'virtual:svg-icons-register'
 import SvgIcon from '@/components/SvgIcon'
-import elementIcons from '@/components/SvgIcon/svgicon'
+import antdIcons from '@/components/SvgIcon/antd-icons'
 
 import './permission' // permission control
 
@@ -69,16 +72,16 @@ app.component('Editor', Editor)
 app.use(router)
 app.use(store)
 app.use(plugins)
-app.use(elementIcons)
+app.use(antdIcons)
 app.component('svg-icon', SvgIcon)
 
 directive(app)
 
-// 使用element-plus 并且设置全局的大小
-app.use(ElementPlus, {
-  locale: locale,
-  // 支持 large、default、small
-  size: Cookies.get('size') || 'default'
+// 使用 ant-design-vue 并且设置全局配置
+app.use(Antd, {
+  locale: zhCN,
+  // 支持 large、middle、small
+  size: Cookies.get('size') === 'large' ? 'large' : Cookies.get('size') === 'small' ? 'small' : 'middle'
 })
 
 app.mount('#app')

+ 2 - 2
yushu-uivue3/src/permission.js

@@ -1,5 +1,5 @@
 import router from './router'
-import { ElMessage } from 'element-plus'
+import { message } from 'ant-design-vue'
 import NProgress from 'nprogress'
 import 'nprogress/nprogress.css'
 import { getToken } from '@/utils/auth'
@@ -46,7 +46,7 @@ router.beforeEach((to, from, next) => {
           })
         }).catch(err => {
           useUserStore().logOut().then(() => {
-            ElMessage.error(err)
+            message.error(err)
             next({ path: '/' })
           })
         })

+ 12 - 6
yushu-uivue3/src/plugins/download.js

@@ -1,5 +1,5 @@
 import axios from 'axios'
-import { ElLoading, ElMessage } from 'element-plus'
+import { message } from 'ant-design-vue'
 import { saveAs } from 'file-saver'
 import { getToken } from '@/utils/auth'
 import errorCode from '@/utils/errorCode'
@@ -45,7 +45,7 @@ export default {
   },
   zip(url, name) {
     var url = baseURL + url
-    downloadLoadingInstance = ElLoading.service({ text: "正在下载数据,请稍候", background: "rgba(0, 0, 0, 0.7)", })
+    downloadLoadingInstance = message.loading({ content: "正在下载数据,请稍候", duration: 0 })
     axios({
       method: 'get',
       url: url,
@@ -59,11 +59,17 @@ export default {
       } else {
         this.printErrMsg(res.data)
       }
-      downloadLoadingInstance.close()
+      if (downloadLoadingInstance) {
+        downloadLoadingInstance()
+        downloadLoadingInstance = null
+      }
     }).catch((r) => {
       console.error(r)
-      ElMessage.error('下载文件出现错误,请联系管理员!')
-      downloadLoadingInstance.close()
+      message.error('下载文件出现错误,请联系管理员!')
+      if (downloadLoadingInstance) {
+        downloadLoadingInstance()
+        downloadLoadingInstance = null
+      }
     })
   },
   saveAs(text, name, opts) {
@@ -73,7 +79,7 @@ export default {
     const resText = await data.text()
     const rspObj = JSON.parse(resText)
     const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
-    ElMessage.error(errMsg)
+    message.error(errMsg)
   }
 }
 

+ 19 - 7
yushu-uivue3/src/store/modules/user.js

@@ -1,5 +1,5 @@
 import router from '@/router'
-import { ElMessageBox, } from 'element-plus'
+import { Modal } from 'ant-design-vue'
 import { login, logout, getInfo, emailLogin } from '@/api/login'
 import { getToken, setToken, removeToken } from '@/utils/auth'
 import { isHttp, isEmpty } from "@/utils/validate"
@@ -69,15 +69,27 @@ const useUserStore = defineStore(
             this.avatar = avatar
             /* 初始密码提示 */
             if(res.isDefaultModifyPwd) {
-              ElMessageBox.confirm('您的密码还是初始密码,请修改密码!',  '安全提示', {  confirmButtonText: '确定',  cancelButtonText: '取消',  type: 'warning' }).then(() => {
-                router.push({ name: 'Profile', params: { activeTab: 'resetPwd' } })
-              }).catch(() => {})
+              Modal.warning({
+                title: '安全提示',
+                content: '您的密码还是初始密码,请修改密码!',
+                okText: '确定',
+                cancelText: '取消',
+                onOk: () => {
+                  router.push({ name: 'Profile', params: { activeTab: 'resetPwd' } })
+                }
+              })
             }
             /* 过期密码提示 */
             if(!res.isDefaultModifyPwd && res.isPasswordExpired) {
-              ElMessageBox.confirm('您的密码已过期,请尽快修改密码!',  '安全提示', {  confirmButtonText: '确定',  cancelButtonText: '取消',  type: 'warning' }).then(() => {
-                router.push({ name: 'Profile', params: { activeTab: 'resetPwd' } })
-              }).catch(() => {})
+              Modal.warning({
+                title: '安全提示',
+                content: '您的密码已过期,请尽快修改密码!',
+                okText: '确定',
+                cancelText: '取消',
+                onOk: () => {
+                  router.push({ name: 'Profile', params: { activeTab: 'resetPwd' } })
+                }
+              })
             }
             resolve(res)
           }).catch(error => {

+ 31 - 18
yushu-uivue3/src/utils/request.js

@@ -1,5 +1,5 @@
 import axios from 'axios'
-import { ElNotification , ElMessageBox, ElMessage, ElLoading } from 'element-plus'
+import { notification, Modal, message } from 'ant-design-vue'
 import { getToken } from '@/utils/auth'
 import errorCode from '@/utils/errorCode'
 import { tansParams, blobValidate } from '@/utils/yushu'
@@ -84,24 +84,31 @@ service.interceptors.response.use(res => {
     if (code === 401) {
       if (!isRelogin.show) {
         isRelogin.show = true
-        ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
-          isRelogin.show = false
-          useUserStore().logOut().then(() => {
-            location.href = '/index'
-          })
-      }).catch(() => {
-        isRelogin.show = false
-      })
+        Modal.confirm({
+          title: '系统提示',
+          content: '登录状态已过期,您可以继续留在该页面,或者重新登录',
+          okText: '重新登录',
+          cancelText: '取消',
+          onOk: () => {
+            isRelogin.show = false
+            useUserStore().logOut().then(() => {
+              location.href = '/index'
+            })
+          },
+          onCancel: () => {
+            isRelogin.show = false
+          }
+        })
     }
       return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
     } else if (code === 500) {
-      ElMessage({ message: msg, type: 'error' })
+      message.error(msg)
       return Promise.reject(new Error(msg))
     } else if (code === 601) {
-      ElMessage({ message: msg, type: 'warning' })
+      message.warning(msg)
       return Promise.reject(new Error(msg))
     } else if (code !== 200) {
-      ElNotification.error({ title: msg })
+      notification.error({ message: '系统提示', description: msg })
       return Promise.reject('error')
     } else {
       return  Promise.resolve(res.data)
@@ -117,14 +124,14 @@ service.interceptors.response.use(res => {
     } else if (message.includes("Request failed with status code")) {
       message = "系统接口" + message.substr(message.length - 3) + "异常"
     }
-    ElMessage({ message: message, type: 'error', duration: 5 * 1000 })
+    message.error({ content: message, duration: 5 })
     return Promise.reject(error)
   }
 )
 
 // 通用下载方法
 export function download(url, params, filename, config) {
-  downloadLoadingInstance = ElLoading.service({ text: "正在下载数据,请稍候", background: "rgba(0, 0, 0, 0.7)", })
+  downloadLoadingInstance = message.loading({ content: "正在下载数据,请稍候", duration: 0 })
   return service.post(url, params, {
     transformRequest: [(params) => { return tansParams(params) }],
     headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
@@ -139,13 +146,19 @@ export function download(url, params, filename, config) {
       const resText = await data.text()
       const rspObj = JSON.parse(resText)
       const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
-      ElMessage.error(errMsg)
+      message.error(errMsg)
+    }
+    if (downloadLoadingInstance) {
+      downloadLoadingInstance()
+      downloadLoadingInstance = null
     }
-    downloadLoadingInstance.close()
   }).catch((r) => {
     console.error(r)
-    ElMessage.error('下载文件出现错误,请联系管理员!')
-    downloadLoadingInstance.close()
+    message.error('下载文件出现错误,请联系管理员!')
+    if (downloadLoadingInstance) {
+      downloadLoadingInstance()
+      downloadLoadingInstance = null
+    }
   })
 }
 

+ 12 - 13
yushu-uivue3/src/utils/websocket.js

@@ -3,7 +3,7 @@
  * 用于实时接收消息通知
  */
 import { getToken } from '@/utils/auth'
-import { ElNotification } from 'element-plus'
+import { notification } from 'ant-design-vue'
 
 class WebSocketService {
   constructor() {
@@ -122,12 +122,11 @@ class WebSocketService {
    */
   handleNewMessage(payload) {
     // 弹窗通知
-    ElNotification({
-      title: payload.senderName || '新消息',
-      message: payload.content?.substring(0, 50) || '您收到一条新消息',
-      type: 'info',
-      duration: 5000,
-      position: 'top-right',
+    notification.info({
+      message: payload.senderName || '新消息',
+      description: payload.content?.substring(0, 50) || '您收到一条新消息',
+      duration: 5,
+      placement: 'topRight',
       onClick: () => {
         // 点击跳转到消息中心
         window.location.href = '/#/message'
@@ -143,12 +142,12 @@ class WebSocketService {
    */
   handleNewNotification(payload) {
     // 弹窗通知
-    ElNotification({
-      title: payload.title || '系统通知',
-      message: payload.content?.substring(0, 100) || '您收到一条系统通知',
-      type: payload.priority === '2' ? 'warning' : 'info',
-      duration: payload.priority === '2' ? 0 : 5000, // 紧急通知不自动关闭
-      position: 'top-right',
+    const notifyMethod = payload.priority === '2' ? notification.warning : notification.info
+    notifyMethod({
+      message: payload.title || '系统通知',
+      description: payload.content?.substring(0, 100) || '您收到一条系统通知',
+      duration: payload.priority === '2' ? 0 : 5, // 紧急通知不自动关闭
+      placement: 'topRight',
       onClick: () => {
         window.location.href = '/#/message'
       }