Merge branch 'master' of http://139.196.74.78:10010/r/jagzwxm/ja_web
20 files modified
7 files added
4 files deleted
| | |
| | | let locationFlag = false |
| | | let watchId = null |
| | | let userLocationMarker = null |
| | | const setMapLocation = () => { |
| | | locationFlag = true |
| | | |
| | | // 初始化实时位置监听 |
| | | const initLocationWatch = () => { |
| | | // 在WebView加载的网页中 |
| | | // 检查浏览器是否支持 geolocation |
| | | if (navigator.geolocation) { |
| | |
| | | // 停止监听位置 |
| | | navigator.geolocation.clearWatch(watchId) |
| | | } |
| | | |
| | | // 开始持续获取用户的位置 |
| | | watchId = navigator.geolocation.watchPosition( |
| | | function (position) { |
| | |
| | | const lat = position.coords.latitude // 纬度 |
| | | const lng = position.coords.longitude // 经度 |
| | | |
| | | if (locationFlag) { |
| | | if (userLocationMarker) { |
| | | userLocationMarker.setLatLng([lat, lng]) |
| | | } else { |
| | | userLocationMarker = L.marker([lat, lng], { |
| | | icon: L.icon({ |
| | | // 确保位置标记存在并更新位置 |
| | | if (userLocationMarker) { |
| | | userLocationMarker.setLatLng([lat, lng]) |
| | | } else { |
| | | userLocationMarker = L.marker([lat, lng], { |
| | | icon: L.icon({ |
| | | iconUrl: userLocationIcon, // 图片路径 |
| | | iconSize: [24, 24], // 图标尺寸 |
| | | iconAnchor: [12, 12], // 锚点位置 |
| | | }), |
| | | }).addTo(map) |
| | | } |
| | | iconSize: [24, 24], // 图标尺寸 |
| | | iconAnchor: [12, 12], // 锚点位置 |
| | | }), |
| | | }).addTo(map) |
| | | } |
| | | |
| | | // 如果是点击定位按钮触发的,将地图视图定位到当前位置 |
| | | if (locationFlag) { |
| | | mapSetView({ |
| | | lat, |
| | | lng, |
| | | }) |
| | | |
| | | locationFlag = false |
| | | |
| | | return |
| | | } |
| | | |
| | | if (userLocationMarker) { |
| | | userLocationMarker.setLatLng([lat, lng]) |
| | | } |
| | | }, |
| | | function (error) { |
| | |
| | | ) |
| | | } else { |
| | | console.log('该浏览器不支持地理定位功能。') |
| | | } |
| | | } |
| | | |
| | | const setMapLocation = () => { |
| | | locationFlag = true |
| | | // 如果还没有开始监听位置,先初始化监听 |
| | | if (!watchId) { |
| | | initLocationWatch() |
| | | } else { |
| | | // 已经在监听位置,会自动定位到当前位置 |
| | | // 可以添加一个视觉反馈,比如位置标记闪烁效果 |
| | | if (userLocationMarker) { |
| | | // 添加闪烁效果 |
| | | userLocationMarker.getElement().classList.add('location-blink') |
| | | setTimeout(() => { |
| | | userLocationMarker.getElement().classList.remove('location-blink') |
| | | }, 1000) |
| | | } |
| | | } |
| | | } |
| | | let lastLocationMarker = null |
| | |
| | | initMap() |
| | | map.addLayer(layers[0].map) |
| | | |
| | | // 初始化实时位置监听 |
| | | initLocationWatch() |
| | | |
| | | EventBus.on('mapSetView', mapSetView) |
| | | EventBus.on('mapAddMarker', mapAddMarker) |
| | | EventBus.on('mapAddAirMarker', mapAddAirMarker) |
| | |
| | | }) |
| | | |
| | | onUnmounted(() => { |
| | | // 清理位置监听 |
| | | if (watchId) { |
| | | navigator.geolocation.clearWatch(watchId) |
| | | watchId = null |
| | | } |
| | | // 移除位置标记 |
| | | if (userLocationMarker) { |
| | | map.removeLayer(userLocationMarker) |
| | | userLocationMarker = null |
| | | } |
| | | |
| | | EventBus.off('mapSetView', mapSetView) |
| | | EventBus.off('mapAddMarker', mapAddMarker) |
| | | EventBus.off('mapAddAirMarker', mapAddAirMarker) |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 位置标记闪烁效果 |
| | | .location-blink { |
| | | animation: blink 1s ease-in-out; |
| | | } |
| | | |
| | | @keyframes blink { |
| | | 0% { |
| | | transform: scale(1); |
| | | opacity: 1; |
| | | } |
| | | 50% { |
| | | transform: scale(1.2); |
| | | opacity: 0.8; |
| | | } |
| | | 100% { |
| | | transform: scale(1); |
| | | opacity: 1; |
| | | } |
| | | } |
| | | </style> |
| New file |
| | |
| | | <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="search-normal"> |
| | | <g id="search-normal_2"> |
| | | <g id="search-normal_3"> |
| | | <g id="vuesax/linear/search-normal"> |
| | | <g id="search-normal_4"> |
| | | <path id="Vector" d="M7.66659 14C11.1644 14 13.9999 11.1644 13.9999 7.66665C13.9999 4.16884 11.1644 1.33331 7.66659 1.33331C4.16878 1.33331 1.33325 4.16884 1.33325 7.66665C1.33325 11.1644 4.16878 14 7.66659 14Z" stroke="#191919" stroke-linecap="round" stroke-linejoin="round"/> |
| | | <path id="Vector_2" d="M14.6666 14.6666L13.3333 13.3333" stroke="#191919" stroke-linecap="round" stroke-linejoin="round"/> |
| | | </g> |
| | | </g> |
| | | </g> |
| | | </g> |
| | | </g> |
| | | </svg> |
| | |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2026-01-16 11:12:30 |
| | | * @FilePath : \applications\task-work-order\src\config\website.js |
| | | * @Description : |
| | | * Copyright 2026 OBKoro1, All Rights Reserved. |
| | | * @Description : |
| | | * Copyright 2026 OBKoro1, All Rights Reserved. |
| | | * 2026-01-06 09:47:27 |
| | | */ |
| | | /** |
| | | * 全局配置文件 |
| | | */ |
| | | export default { |
| | | title: 'saber', |
| | | logo: 'S', |
| | | key: 'work', //配置主键,目前用于存储 |
| | | indexTitle: '', |
| | | clientId: 'saber', // 客户端id |
| | | clientSecret: 'saber_secret', // 客户端密钥 |
| | | tenantMode: true, // 是否开启租户模式 |
| | | tenantId: '000000', // 管理组租户编号 |
| | | captchaMode: true, // 是否开启验证码模式 |
| | | switchMode: false, // 是否开启部门切换模式 |
| | | lockPage: '/lock', |
| | | tokenTime: 3000, |
| | | tokenHeader: 'Blade-Auth', |
| | | //http的status默认放行不才用统一处理的, |
| | | statusWhiteList: [], |
| | | //配置首页不可关闭 |
| | | setting: { |
| | | sidebar: 'vertical', |
| | | tag: true, |
| | | debug: true, |
| | | collapse: true, |
| | | search: true, |
| | | color: true, |
| | | lock: true, |
| | | screenshot: true, |
| | | fullscreen: true, |
| | | theme: true, |
| | | menu: true, |
| | | }, |
| | | fistPage: { |
| | | name: '数据驾驶舱', |
| | | path: '/dataCockpit/index', |
| | | // path: '/tickets/ticket', |
| | | |
| | | }, |
| | | //配置菜单的属性 |
| | | menu: { |
| | | iconDefault: 'icon-caidan', |
| | | label: 'name', |
| | | path: 'path', |
| | | icon: 'source', |
| | | children: 'children', |
| | | query: 'query', |
| | | href: 'path', |
| | | meta: 'meta', |
| | | }, |
| | | //oauth2配置 |
| | | oauth2: { |
| | | // 是否开启注册功能 |
| | | registerMode: true, |
| | | // 使用后端工程 @org.springblade.test.Sm2KeyGenerator 获取 |
| | | publicKey: '请配置国密sm2公钥', |
| | | // 第三方系统授权地址 |
| | | authUrl: 'http://localhost/blade-auth/oauth/render', |
| | | // 单点登录系统认证(cloud端口为8100,boot端口为80) |
| | | ssoUrl: |
| | | 'http://localhost:8100/oauth/authorize?client_id=saber3&response_type=code&redirect_uri=', |
| | | // 单点登录回调地址(Saber服务的登录界面地址) |
| | | redirectUri: 'http://localhost:2888/login', |
| | | }, |
| | | //设计器配置 |
| | | design: { |
| | | // 流程设计器类型(true->nutflow,false->flowable) |
| | | designMode: true, |
| | | // 流程设计器地址(flowable模式) |
| | | designUrl: 'http://localhost:9999', |
| | | // 报表设计器地址(cloud端口为8108,boot端口为80) |
| | | reportUrl: 'http://localhost:8108/ureport', |
| | | }, |
| | | title: 'saber', |
| | | logo: 'S', |
| | | key: 'work', //配置主键,目前用于存储 |
| | | indexTitle: '', |
| | | clientId: 'saber', // 客户端id |
| | | clientSecret: 'saber_secret', // 客户端密钥 |
| | | tenantMode: true, // 是否开启租户模式 |
| | | tenantId: '000000', // 管理组租户编号 |
| | | captchaMode: true, // 是否开启验证码模式 |
| | | switchMode: false, // 是否开启部门切换模式 |
| | | lockPage: '/lock', |
| | | tokenTime: 3000, |
| | | tokenHeader: 'Blade-Auth', |
| | | //http的status默认放行不才用统一处理的, |
| | | statusWhiteList: [], |
| | | //配置首页不可关闭 |
| | | setting: { |
| | | sidebar: 'vertical', |
| | | tag: true, |
| | | debug: true, |
| | | collapse: true, |
| | | search: true, |
| | | color: true, |
| | | lock: true, |
| | | screenshot: true, |
| | | fullscreen: true, |
| | | theme: true, |
| | | menu: true, |
| | | }, |
| | | fistPage: { |
| | | name: '测试页', |
| | | path: '/test', |
| | | }, |
| | | //配置菜单的属性 |
| | | menu: { |
| | | iconDefault: 'icon-caidan', |
| | | label: 'name', |
| | | path: 'path', |
| | | icon: 'source', |
| | | children: 'children', |
| | | query: 'query', |
| | | href: 'path', |
| | | meta: 'meta', |
| | | }, |
| | | //oauth2配置 |
| | | oauth2: { |
| | | // 是否开启注册功能 |
| | | registerMode: true, |
| | | // 使用后端工程 @org.springblade.test.Sm2KeyGenerator 获取 |
| | | publicKey: '请配置国密sm2公钥', |
| | | // 第三方系统授权地址 |
| | | authUrl: 'http://localhost/blade-auth/oauth/render', |
| | | // 单点登录系统认证(cloud端口为8100,boot端口为80) |
| | | ssoUrl: 'http://localhost:8100/oauth/authorize?client_id=saber3&response_type=code&redirect_uri=', |
| | | // 单点登录回调地址(Saber服务的登录界面地址) |
| | | redirectUri: 'http://localhost:2888/login', |
| | | }, |
| | | //设计器配置 |
| | | design: { |
| | | // 流程设计器类型(true->nutflow,false->flowable) |
| | | designMode: true, |
| | | // 流程设计器地址(flowable模式) |
| | | designUrl: 'http://localhost:9999', |
| | | // 报表设计器地址(cloud端口为8108,boot端口为80) |
| | | reportUrl: 'http://localhost:8108/ureport', |
| | | }, |
| | | } |
| | |
| | | query: firstMenu.query || {}, |
| | | meta: firstMenu.meta || {}, |
| | | }) |
| | | |
| | | store.commit('ADD_TAG', { |
| | | name: toMenu.name, |
| | | path: toMenu.path, |
| | |
| | | const pageTitle = isLoginPage ? '中图智飞低空感知网平台' : '综合管理平台' |
| | | document.title = pageTitle |
| | | store.commit('SET_IS_SEARCH', false) |
| | | }) |
| | | }) |
| | |
| | | import Store from '@/store/' |
| | | |
| | | export default [ |
| | | { |
| | | path: '/login', |
| | | name: '登录页', |
| | | component: () => |
| | | Store.getters.isMacOs ? import('@/mac/login.vue') : import('@/page/login/index.vue'), |
| | | meta: { |
| | | keepAlive: true, |
| | | isTab: false, |
| | | isAuth: false, |
| | | }, |
| | | }, |
| | | { |
| | | path: '/oauth/redirect/:source', |
| | | name: '第三方登录', |
| | | component: () => |
| | | Store.getters.isMacOs ? import('@/mac/login.vue') : import('@/page/login/index.vue'), |
| | | meta: { |
| | | keepAlive: true, |
| | | isTab: false, |
| | | isAuth: false, |
| | | }, |
| | | }, |
| | | { |
| | | path: '/lock', |
| | | name: '锁屏页', |
| | | component: () => |
| | | Store.getters.isMacOs ? import('@/mac/lock.vue') : import('@/page/lock/index.vue'), |
| | | meta: { |
| | | keepAlive: true, |
| | | isTab: false, |
| | | isAuth: false, |
| | | }, |
| | | }, |
| | | { |
| | | path: '/404', |
| | | component: () => import(/* webpackChunkName: "page" */ '@/components/error-page/404.vue'), |
| | | name: '404', |
| | | meta: { |
| | | keepAlive: true, |
| | | isTab: false, |
| | | isAuth: false, |
| | | }, |
| | | }, |
| | | { |
| | | path: '/403', |
| | | component: () => import(/* webpackChunkName: "page" */ '@/components/error-page/403.vue'), |
| | | name: '403', |
| | | meta: { |
| | | keepAlive: true, |
| | | isTab: false, |
| | | isAuth: false, |
| | | }, |
| | | }, |
| | | { |
| | | path: '/500', |
| | | component: () => import(/* webpackChunkName: "page" */ '@/components/error-page/500.vue'), |
| | | name: '500', |
| | | meta: { |
| | | keepAlive: true, |
| | | isTab: false, |
| | | isAuth: false, |
| | | }, |
| | | }, |
| | | { |
| | | path: '/', |
| | | name: '主页', |
| | | redirect: '/wel', |
| | | }, |
| | | // { |
| | | // path: '/', |
| | | // name: '主页', |
| | | // redirect: '/tickets/ticket', |
| | | // }, |
| | | { |
| | | path: '/login', |
| | | name: '登录页', |
| | | component: () => (Store.getters.isMacOs ? import('@/mac/login.vue') : import('@/page/login/index.vue')), |
| | | meta: { |
| | | keepAlive: true, |
| | | isTab: false, |
| | | isAuth: false, |
| | | }, |
| | | }, |
| | | { |
| | | path: '/oauth/redirect/:source', |
| | | name: '第三方登录', |
| | | component: () => (Store.getters.isMacOs ? import('@/mac/login.vue') : import('@/page/login/index.vue')), |
| | | meta: { |
| | | keepAlive: true, |
| | | isTab: false, |
| | | isAuth: false, |
| | | }, |
| | | }, |
| | | { |
| | | path: '/lock', |
| | | name: '锁屏页', |
| | | component: () => (Store.getters.isMacOs ? import('@/mac/lock.vue') : import('@/page/lock/index.vue')), |
| | | meta: { |
| | | keepAlive: true, |
| | | isTab: false, |
| | | isAuth: false, |
| | | }, |
| | | }, |
| | | { |
| | | path: '/404', |
| | | component: () => import(/* webpackChunkName: "page" */ '@/components/error-page/404.vue'), |
| | | name: '404', |
| | | meta: { |
| | | keepAlive: true, |
| | | isTab: false, |
| | | isAuth: false, |
| | | }, |
| | | }, |
| | | { |
| | | path: '/403', |
| | | component: () => import(/* webpackChunkName: "page" */ '@/components/error-page/403.vue'), |
| | | name: '403', |
| | | meta: { |
| | | keepAlive: true, |
| | | isTab: false, |
| | | isAuth: false, |
| | | }, |
| | | }, |
| | | { |
| | | path: '/500', |
| | | component: () => import(/* webpackChunkName: "page" */ '@/components/error-page/500.vue'), |
| | | name: '500', |
| | | meta: { |
| | | keepAlive: true, |
| | | isTab: false, |
| | | isAuth: false, |
| | | }, |
| | | }, |
| | | ] |
| | |
| | | } |
| | | ], |
| | | }, |
| | | // 事件工单 |
| | | // { |
| | | // path: '/tickets', |
| | | // component: () => |
| | | // Store.getters.isMacOs ? import('@/mac/index.vue') : import('@/page/index/index.vue'), |
| | | // redirect: '/tickets/ticket', |
| | | // children: [ |
| | | // { |
| | | // path: 'ticket', |
| | | // name: '事件工单', |
| | | // meta: { |
| | | // i18n: 'dashboard', |
| | | // }, |
| | | // component: () => import(/* webpackChunkName: "views" */ '@/views/tickets/ticket.vue'), |
| | | // }, |
| | | // ], |
| | | // }, |
| | | |
| | | { |
| | | path: '/test', |
| | | component: Layout, |
| | |
| | | import { |
| | | setToken, |
| | | setRefreshToken, |
| | | removeToken, |
| | | removeRefreshToken, |
| | | getRefreshToken, |
| | | } from '@/utils/auth'; |
| | | import { setStore, getStore } from '@/utils/store'; |
| | | import { validatenull } from '@/utils/validate'; |
| | | import { deepClone } from '@/utils/util'; |
| | | import { setToken, setRefreshToken, removeToken, removeRefreshToken, getRefreshToken } from '@/utils/auth' |
| | | import { setStore, getStore } from '@/utils/store' |
| | | import { validatenull } from '@/utils/validate' |
| | | import { deepClone } from '@/utils/util' |
| | | import defaultAva from '@/assets/images/defaultava.png' |
| | | import { |
| | | loginByUsername, |
| | | loginBySocial, |
| | | loginBySso, |
| | | loginByPhone, |
| | | getUserInfo, |
| | | logout, |
| | | refreshToken, |
| | | getButtons, |
| | | registerUser, |
| | | getParentDeptInfo |
| | | } from '@/api/user'; |
| | | import { getRoutes, getTopMenu } from '@/api/system/menu'; |
| | | import { formatPath } from '@/router/avue-router'; |
| | | import { ElMessage } from 'element-plus'; |
| | | import { encrypt } from '@/utils/sm2'; |
| | | import md5 from 'js-md5'; |
| | | |
| | | loginByUsername, |
| | | loginBySocial, |
| | | loginBySso, |
| | | loginByPhone, |
| | | getUserInfo, |
| | | logout, |
| | | refreshToken, |
| | | getButtons, |
| | | registerUser, |
| | | getParentDeptInfo, |
| | | } from '@/api/user' |
| | | import { getRoutes, getTopMenu } from '@/api/system/menu' |
| | | import { formatPath } from '@/router/avue-router' |
| | | import { ElMessage } from 'element-plus' |
| | | import { encrypt } from '@/utils/sm2' |
| | | import md5 from 'js-md5' |
| | | |
| | | const user = { |
| | | state: { |
| | | tenantId: getStore({ name: 'tenantId' }) || '', |
| | | userInfo: getStore({ name: 'userInfo' }) || [], |
| | | permission: getStore({ name: 'permission' }) || {}, |
| | | roles: [], |
| | | menuId: {}, |
| | | menu: getStore({ name: 'menu' }) || [], |
| | | menuAll: getStore({ name: 'menuAll' }) || [], |
| | | token: getStore({ name: 'token' }) || '', |
| | | refreshToken: getStore({ name: 'refreshToken' }) || '', |
| | | parentDeptInfo: getStore({ name: 'parentDeptInfo' }) || '', |
| | | state: { |
| | | tenantId: getStore({ name: 'tenantId' }) || '', |
| | | userInfo: getStore({ name: 'userInfo' }) || [], |
| | | permission: getStore({ name: 'permission' }) || {}, |
| | | roles: [], |
| | | menuId: {}, |
| | | menu: getStore({ name: 'menu' }) || [], |
| | | menuAll: getStore({ name: 'menuAll' }) || [], |
| | | token: getStore({ name: 'token' }) || '', |
| | | refreshToken: getStore({ name: 'refreshToken' }) || '', |
| | | parentDeptInfo: getStore({ name: 'parentDeptInfo' }) || '', |
| | | }, |
| | | actions: { |
| | | //根据用户名登录 |
| | | LoginByUsername({ commit }, userInfo = {}) { |
| | | return new Promise((resolve, reject) => { |
| | | loginByUsername( |
| | | userInfo.tenantId, |
| | | userInfo.deptId, |
| | | userInfo.roleId, |
| | | userInfo.username, |
| | | md5(userInfo.password), |
| | | userInfo.type, |
| | | userInfo.key, |
| | | userInfo.code |
| | | ) |
| | | .then(res => { |
| | | const data = res.data |
| | | if (data.error_description) { |
| | | ElMessage({ |
| | | message: data.error_description, |
| | | type: 'error', |
| | | }) |
| | | } else { |
| | | commit('SET_TOKEN', data.access_token) |
| | | commit('SET_REFRESH_TOKEN', data.refresh_token) |
| | | commit('SET_TENANT_ID', data.tenant_id) |
| | | commit('SET_USER_INFO', data) |
| | | commit('SET_PARENT_DEPT_INFO', data.dept_id) |
| | | commit('DEL_ALL_TAG') |
| | | commit('CLEAR_LOCK') |
| | | } |
| | | resolve() |
| | | }) |
| | | .catch(err => { |
| | | reject(err) |
| | | }) |
| | | }) |
| | | }, |
| | | //根据第三方信息登录 |
| | | LoginBySocial({ commit }, userInfo) { |
| | | return new Promise((resolve, reject) => { |
| | | loginBySocial(userInfo.tenantId, userInfo.source, userInfo.code, userInfo.state) |
| | | .then(res => { |
| | | const data = res.data |
| | | if (data.error_description) { |
| | | ElMessage({ |
| | | message: data.error_description, |
| | | type: 'error', |
| | | }) |
| | | } else { |
| | | commit('SET_TOKEN', data.access_token) |
| | | commit('SET_REFRESH_TOKEN', data.refresh_token) |
| | | commit('SET_USER_INFO', data) |
| | | commit('SET_TENANT_ID', data.tenant_id) |
| | | commit('DEL_ALL_TAG') |
| | | commit('CLEAR_LOCK') |
| | | } |
| | | resolve() |
| | | }) |
| | | .catch(err => { |
| | | reject(err) |
| | | }) |
| | | }) |
| | | }, |
| | | //根据单点信息登录 |
| | | LoginBySso({ commit }, userInfo) { |
| | | return new Promise((resolve, reject) => { |
| | | loginBySso(userInfo.state, userInfo.code) |
| | | .then(res => { |
| | | const data = res.data |
| | | if (data.error_description) { |
| | | ElMessage({ |
| | | message: data.error_description, |
| | | type: 'error', |
| | | }) |
| | | } else { |
| | | commit('SET_TOKEN', data.access_token) |
| | | commit('SET_REFRESH_TOKEN', data.refresh_token) |
| | | commit('SET_USER_INFO', data) |
| | | commit('SET_TENANT_ID', data.tenant_id) |
| | | commit('DEL_ALL_TAG') |
| | | commit('CLEAR_LOCK') |
| | | } |
| | | resolve() |
| | | }) |
| | | .catch(err => { |
| | | reject(err) |
| | | }) |
| | | }) |
| | | }, |
| | | //根据手机信息登录 |
| | | LoginByPhone({ commit }, userInfo) { |
| | | return new Promise((resolve, reject) => { |
| | | loginByPhone(userInfo.tenantId, encrypt(userInfo.phone), userInfo.codeId, userInfo.codeValue) |
| | | .then(res => { |
| | | const data = res.data |
| | | if (data.error_description) { |
| | | ElMessage({ |
| | | message: data.error_description, |
| | | type: 'error', |
| | | }) |
| | | } else { |
| | | commit('SET_TOKEN', data.access_token) |
| | | commit('SET_REFRESH_TOKEN', data.refresh_token) |
| | | commit('SET_USER_INFO', data) |
| | | commit('SET_TENANT_ID', data.tenant_id) |
| | | commit('DEL_ALL_TAG') |
| | | commit('CLEAR_LOCK') |
| | | } |
| | | resolve() |
| | | }) |
| | | .catch(err => { |
| | | reject(err) |
| | | }) |
| | | }) |
| | | }, |
| | | //用户注册 |
| | | RegisterUser({ commit }, userInfo = {}) { |
| | | return new Promise((resolve, reject) => { |
| | | registerUser( |
| | | userInfo.tenantId, |
| | | userInfo.name, |
| | | userInfo.account, |
| | | encrypt(userInfo.password), |
| | | userInfo.phone, |
| | | userInfo.email |
| | | ).then(res => { |
| | | const data = res.data |
| | | if (data.error_description) { |
| | | ElMessage({ |
| | | message: data.error_description, |
| | | type: 'error', |
| | | }) |
| | | reject(data.error_description) |
| | | } else { |
| | | commit('SET_TOKEN', data.access_token) |
| | | commit('SET_REFRESH_TOKEN', data.refresh_token) |
| | | commit('SET_USER_INFO', data) |
| | | commit('SET_TENANT_ID', data.tenant_id) |
| | | commit('DEL_ALL_TAG') |
| | | commit('CLEAR_LOCK') |
| | | } |
| | | resolve() |
| | | }) |
| | | }) |
| | | }, |
| | | GetUserInfo({ commit }) { |
| | | return new Promise((resolve, reject) => { |
| | | getUserInfo() |
| | | .then(res => { |
| | | const data = res.data.data |
| | | commit('SET_ROLES', data.roles) |
| | | resolve(data) |
| | | }) |
| | | .catch(err => { |
| | | reject(err) |
| | | }) |
| | | }) |
| | | }, |
| | | //刷新token |
| | | RefreshToken({ state, commit }, userInfo) { |
| | | return new Promise((resolve, reject) => { |
| | | refreshToken( |
| | | getRefreshToken(), |
| | | state.tenantId, |
| | | !validatenull(userInfo) ? userInfo.deptId : state.userInfo.dept_id, |
| | | !validatenull(userInfo) ? userInfo.roleId : state.userInfo.role_id |
| | | ) |
| | | .then(res => { |
| | | const data = res.data |
| | | commit('SET_TOKEN', data.access_token) |
| | | commit('SET_REFRESH_TOKEN', data.refresh_token) |
| | | commit('SET_USER_INFO', data) |
| | | resolve() |
| | | }) |
| | | .catch(error => { |
| | | reject(error) |
| | | }) |
| | | }) |
| | | }, |
| | | // 登出 |
| | | LogOut({ commit }) { |
| | | return new Promise((resolve, reject) => { |
| | | logout() |
| | | .then(() => { |
| | | commit('SET_TOKEN', '') |
| | | commit('SET_MENU_ALL_NULL', []) |
| | | commit('SET_MENU', []) |
| | | commit('SET_ROLES', []) |
| | | commit('DEL_ALL_TAG', []) |
| | | commit('CLEAR_LOCK') |
| | | removeToken() |
| | | removeRefreshToken() |
| | | resolve() |
| | | }) |
| | | .catch(error => { |
| | | reject(error) |
| | | }) |
| | | }) |
| | | }, |
| | | //注销session |
| | | FedLogOut({ commit }) { |
| | | return new Promise(resolve => { |
| | | commit('SET_TOKEN', '') |
| | | commit('SET_MENU_ALL_NULL', []) |
| | | commit('SET_MENU', []) |
| | | commit('SET_ROLES', []) |
| | | commit('DEL_ALL_TAG', []) |
| | | commit('CLEAR_LOCK') |
| | | removeToken() |
| | | removeRefreshToken() |
| | | removeToken() |
| | | resolve() |
| | | }) |
| | | }, |
| | | GetTopMenu() { |
| | | return new Promise(resolve => { |
| | | getTopMenu().then(res => { |
| | | const data = res.data.data || [] |
| | | resolve(data) |
| | | }) |
| | | }) |
| | | }, |
| | | GetMenu({ commit, dispatch }, tenantId) { |
| | | const errLogOut = () => { |
| | | dispatch('LogOut').then(() => { |
| | | const env = import.meta.env.VITE_APP_ENV |
| | | const adminUrl = import.meta.env.VITE_APP_DASHBOARD_URL |
| | | env === 'development' |
| | | ? (window.location.href = '/task-work-order/login') |
| | | : window.location.replace(`${adminUrl}#/login`) |
| | | }) |
| | | } |
| | | return new Promise(resolve => { |
| | | getRoutes({ tenantId, sysType: 6 }) |
| | | .then(res => { |
| | | const data = res.data.data |
| | | let menu = deepClone(data) |
| | | if (!res.data?.data?.length) { |
| | | errLogOut() |
| | | return |
| | | } |
| | | menu.forEach(ele => formatPath(ele, true)) |
| | | commit('SET_MENU', menu) |
| | | commit('SET_MENU_ALL', menu) |
| | | dispatch('GetButtons') |
| | | resolve(menu) |
| | | }) |
| | | .catch(err => { |
| | | errLogOut() |
| | | }) |
| | | }) |
| | | }, |
| | | GetButtons({ commit }) { |
| | | return new Promise(resolve => { |
| | | getButtons({ sysType: 6 }).then(res => { |
| | | const data = res.data.data |
| | | commit('SET_PERMISSION', data) |
| | | resolve() |
| | | }) |
| | | }) |
| | | }, |
| | | }, |
| | | mutations: { |
| | | SET_PARENT_DEPT_INFO(state, deptId) { |
| | | getParentDeptInfo({ deptId: deptId }).then(res => { |
| | | const data = res.data.data |
| | | state.parentDeptInfo = data |
| | | setStore({ name: 'parentDeptInfo', content: data }) |
| | | }) |
| | | }, |
| | | SET_TOKEN: (state, token) => { |
| | | setToken(token) |
| | | state.token = token |
| | | setStore({ name: 'token', content: state.token }) |
| | | }, |
| | | SET_REFRESH_TOKEN: (state, refreshToken) => { |
| | | setRefreshToken(refreshToken) |
| | | state.refreshToken = refreshToken |
| | | setStore({ name: 'refreshToken', content: state.refreshToken }) |
| | | }, |
| | | SET_MENU_ID(state, menuId) { |
| | | state.menuId = menuId |
| | | }, |
| | | SET_TENANT_ID: (state, tenantId) => { |
| | | state.tenantId = tenantId |
| | | setStore({ name: 'tenantId', content: state.tenantId }) |
| | | }, |
| | | SET_USER_INFO: (state, userInfo) => { |
| | | if (validatenull(userInfo.user_id) && validatenull(userInfo.account)) { |
| | | state.userInfo = { user_name: 'unauth', role_name: 'unauth' } |
| | | } else { |
| | | if (validatenull(userInfo.avatar)) { |
| | | userInfo.avatar = defaultAva |
| | | } |
| | | state.userInfo = userInfo |
| | | } |
| | | setStore({ name: 'userInfo', content: state.userInfo }) |
| | | }, |
| | | SET_MENU_ALL: (state, menuAll) => { |
| | | let menu = state.menuAll |
| | | menuAll.forEach(ele => { |
| | | let index = menu.findIndex(item => item.path === ele.path) |
| | | if (index === -1) { |
| | | menu.push(ele) |
| | | } else { |
| | | menu[index] = ele |
| | | } |
| | | }) |
| | | state.menuAll = menu |
| | | setStore({ name: 'menuAll', content: state.menuAll }) |
| | | }, |
| | | SET_MENU_ALL_NULL: state => { |
| | | state.menuAll = [] |
| | | setStore({ name: 'menuAll', content: state.menuAll }) |
| | | }, |
| | | SET_MENU: (state, menu) => { |
| | | state.menu = menu |
| | | setStore({ name: 'menu', content: state.menu }) |
| | | }, |
| | | SET_ROLES: (state, roles) => { |
| | | state.roles = roles |
| | | }, |
| | | SET_PERMISSION: (state, permission) => { |
| | | let result = [] |
| | | |
| | | }, |
| | | actions: { |
| | | //根据用户名登录 |
| | | LoginByUsername({ commit }, userInfo = {}) { |
| | | return new Promise((resolve, reject) => { |
| | | loginByUsername( |
| | | userInfo.tenantId, |
| | | userInfo.deptId, |
| | | userInfo.roleId, |
| | | userInfo.username, |
| | | md5(userInfo.password), |
| | | userInfo.type, |
| | | userInfo.key, |
| | | userInfo.code |
| | | ) |
| | | .then(res => { |
| | | const data = res.data; |
| | | if (data.error_description) { |
| | | ElMessage({ |
| | | message: data.error_description, |
| | | type: 'error', |
| | | }); |
| | | } else { |
| | | commit('SET_TOKEN', data.access_token); |
| | | commit('SET_REFRESH_TOKEN', data.refresh_token); |
| | | commit('SET_TENANT_ID', data.tenant_id); |
| | | commit('SET_USER_INFO', data); |
| | | commit('SET_PARENT_DEPT_INFO', data.dept_id); |
| | | commit('DEL_ALL_TAG'); |
| | | commit('CLEAR_LOCK'); |
| | | } |
| | | resolve(); |
| | | }) |
| | | .catch(err => { |
| | | reject(err); |
| | | }); |
| | | }); |
| | | }, |
| | | //根据第三方信息登录 |
| | | LoginBySocial({ commit }, userInfo) { |
| | | return new Promise((resolve, reject) => { |
| | | loginBySocial(userInfo.tenantId, userInfo.source, userInfo.code, userInfo.state) |
| | | .then(res => { |
| | | const data = res.data; |
| | | if (data.error_description) { |
| | | ElMessage({ |
| | | message: data.error_description, |
| | | type: 'error', |
| | | }); |
| | | } else { |
| | | commit('SET_TOKEN', data.access_token); |
| | | commit('SET_REFRESH_TOKEN', data.refresh_token); |
| | | commit('SET_USER_INFO', data); |
| | | commit('SET_TENANT_ID', data.tenant_id); |
| | | commit('DEL_ALL_TAG'); |
| | | commit('CLEAR_LOCK'); |
| | | } |
| | | resolve(); |
| | | }) |
| | | .catch(err => { |
| | | reject(err); |
| | | }); |
| | | }); |
| | | }, |
| | | //根据单点信息登录 |
| | | LoginBySso({ commit }, userInfo) { |
| | | return new Promise((resolve, reject) => { |
| | | loginBySso(userInfo.state, userInfo.code) |
| | | .then(res => { |
| | | const data = res.data; |
| | | if (data.error_description) { |
| | | ElMessage({ |
| | | message: data.error_description, |
| | | type: 'error', |
| | | }); |
| | | } else { |
| | | commit('SET_TOKEN', data.access_token); |
| | | commit('SET_REFRESH_TOKEN', data.refresh_token); |
| | | commit('SET_USER_INFO', data); |
| | | commit('SET_TENANT_ID', data.tenant_id); |
| | | commit('DEL_ALL_TAG'); |
| | | commit('CLEAR_LOCK'); |
| | | } |
| | | resolve(); |
| | | }) |
| | | .catch(err => { |
| | | reject(err); |
| | | }); |
| | | }); |
| | | }, |
| | | //根据手机信息登录 |
| | | LoginByPhone({ commit }, userInfo) { |
| | | return new Promise((resolve, reject) => { |
| | | loginByPhone( |
| | | userInfo.tenantId, |
| | | encrypt(userInfo.phone), |
| | | userInfo.codeId, |
| | | userInfo.codeValue |
| | | ) |
| | | .then(res => { |
| | | const data = res.data; |
| | | if (data.error_description) { |
| | | ElMessage({ |
| | | message: data.error_description, |
| | | type: 'error', |
| | | }); |
| | | } else { |
| | | commit('SET_TOKEN', data.access_token); |
| | | commit('SET_REFRESH_TOKEN', data.refresh_token); |
| | | commit('SET_USER_INFO', data); |
| | | commit('SET_TENANT_ID', data.tenant_id); |
| | | commit('DEL_ALL_TAG'); |
| | | commit('CLEAR_LOCK'); |
| | | } |
| | | resolve(); |
| | | }) |
| | | .catch(err => { |
| | | reject(err); |
| | | }); |
| | | }); |
| | | }, |
| | | //用户注册 |
| | | RegisterUser({ commit }, userInfo = {}) { |
| | | return new Promise((resolve, reject) => { |
| | | registerUser( |
| | | userInfo.tenantId, |
| | | userInfo.name, |
| | | userInfo.account, |
| | | encrypt(userInfo.password), |
| | | userInfo.phone, |
| | | userInfo.email |
| | | ).then(res => { |
| | | const data = res.data; |
| | | if (data.error_description) { |
| | | ElMessage({ |
| | | message: data.error_description, |
| | | type: 'error', |
| | | }); |
| | | reject(data.error_description); |
| | | } else { |
| | | commit('SET_TOKEN', data.access_token); |
| | | commit('SET_REFRESH_TOKEN', data.refresh_token); |
| | | commit('SET_USER_INFO', data); |
| | | commit('SET_TENANT_ID', data.tenant_id); |
| | | commit('DEL_ALL_TAG'); |
| | | commit('CLEAR_LOCK'); |
| | | } |
| | | resolve(); |
| | | }); |
| | | }); |
| | | }, |
| | | GetUserInfo({ commit }) { |
| | | return new Promise((resolve, reject) => { |
| | | getUserInfo() |
| | | .then(res => { |
| | | const data = res.data.data; |
| | | commit('SET_ROLES', data.roles); |
| | | resolve(data); |
| | | }) |
| | | .catch(err => { |
| | | reject(err); |
| | | }); |
| | | }); |
| | | }, |
| | | //刷新token |
| | | RefreshToken({ state, commit }, userInfo) { |
| | | return new Promise((resolve, reject) => { |
| | | refreshToken( |
| | | getRefreshToken(), |
| | | state.tenantId, |
| | | !validatenull(userInfo) ? userInfo.deptId : state.userInfo.dept_id, |
| | | !validatenull(userInfo) ? userInfo.roleId : state.userInfo.role_id |
| | | ) |
| | | .then(res => { |
| | | const data = res.data; |
| | | commit('SET_TOKEN', data.access_token); |
| | | commit('SET_REFRESH_TOKEN', data.refresh_token); |
| | | commit('SET_USER_INFO', data); |
| | | resolve(); |
| | | }) |
| | | .catch(error => { |
| | | reject(error); |
| | | }); |
| | | }); |
| | | }, |
| | | // 登出 |
| | | LogOut({ commit }) { |
| | | return new Promise((resolve, reject) => { |
| | | logout() |
| | | .then(() => { |
| | | commit('SET_TOKEN', ''); |
| | | commit('SET_MENU_ALL_NULL', []); |
| | | commit('SET_MENU', []); |
| | | commit('SET_ROLES', []); |
| | | commit('DEL_ALL_TAG', []); |
| | | commit('CLEAR_LOCK'); |
| | | removeToken(); |
| | | removeRefreshToken(); |
| | | resolve(); |
| | | }) |
| | | .catch(error => { |
| | | reject(error); |
| | | }); |
| | | }); |
| | | }, |
| | | //注销session |
| | | FedLogOut({ commit }) { |
| | | return new Promise(resolve => { |
| | | commit('SET_TOKEN', ''); |
| | | commit('SET_MENU_ALL_NULL', []); |
| | | commit('SET_MENU', []); |
| | | commit('SET_ROLES', []); |
| | | commit('DEL_ALL_TAG', []); |
| | | commit('CLEAR_LOCK'); |
| | | removeToken(); |
| | | removeRefreshToken(); |
| | | removeToken(); |
| | | resolve(); |
| | | }); |
| | | }, |
| | | GetTopMenu() { |
| | | return new Promise(resolve => { |
| | | getTopMenu().then(res => { |
| | | const data = res.data.data || []; |
| | | resolve(data); |
| | | }); |
| | | }); |
| | | }, |
| | | GetMenu({ commit, dispatch }, tenantId) { |
| | | const errLogOut = () => { |
| | | dispatch('LogOut').then(()=>{ |
| | | const env = import.meta.env.VITE_APP_ENV |
| | | const adminUrl = import.meta.env.VITE_APP_DASHBOARD_URL |
| | | env === 'development' |
| | | ? window.location.href = "/manage/login" |
| | | : window.location.replace(`${adminUrl}#/login`) |
| | | }) |
| | | } |
| | | return new Promise(resolve => { |
| | | getRoutes({tenantId,sysType: 6}).then(res => { |
| | | const data = res.data.data; |
| | | let menu = deepClone(data); |
| | | if (!res.data?.data?.length){ |
| | | errLogOut() |
| | | return |
| | | } |
| | | menu.forEach(ele => formatPath(ele, true)); |
| | | commit('SET_MENU', menu); |
| | | commit('SET_MENU_ALL', menu); |
| | | dispatch('GetButtons'); |
| | | resolve(menu); |
| | | }).catch(err =>{ |
| | | errLogOut() |
| | | }) |
| | | }); |
| | | }, |
| | | GetButtons({ commit }) { |
| | | return new Promise(resolve => { |
| | | getButtons({sysType: 6}).then(res => { |
| | | const data = res.data.data; |
| | | commit('SET_PERMISSION', data); |
| | | resolve(); |
| | | }); |
| | | }); |
| | | }, |
| | | }, |
| | | mutations: { |
| | | SET_PARENT_DEPT_INFO(state, deptId){ |
| | | getParentDeptInfo({deptId:deptId}).then(res=>{ |
| | | const data = res.data.data; |
| | | state.parentDeptInfo = data; |
| | | setStore({ name: 'parentDeptInfo', content: data }); |
| | | }) |
| | | }, |
| | | SET_TOKEN: (state, token) => { |
| | | setToken(token); |
| | | state.token = token; |
| | | setStore({ name: 'token', content: state.token }); |
| | | }, |
| | | SET_REFRESH_TOKEN: (state, refreshToken) => { |
| | | setRefreshToken(refreshToken); |
| | | state.refreshToken = refreshToken; |
| | | setStore({ name: 'refreshToken', content: state.refreshToken }); |
| | | }, |
| | | SET_MENU_ID(state, menuId) { |
| | | state.menuId = menuId; |
| | | }, |
| | | SET_TENANT_ID: (state, tenantId) => { |
| | | state.tenantId = tenantId; |
| | | setStore({ name: 'tenantId', content: state.tenantId }); |
| | | }, |
| | | SET_USER_INFO: (state, userInfo) => { |
| | | if (validatenull(userInfo.user_id) && validatenull(userInfo.account)) { |
| | | state.userInfo = { user_name: 'unauth', role_name: 'unauth' }; |
| | | } else { |
| | | if (validatenull(userInfo.avatar)) { |
| | | userInfo.avatar = defaultAva; |
| | | } |
| | | state.userInfo = userInfo; |
| | | } |
| | | setStore({ name: 'userInfo', content: state.userInfo }); |
| | | }, |
| | | SET_MENU_ALL: (state, menuAll) => { |
| | | let menu = state.menuAll; |
| | | menuAll.forEach(ele => { |
| | | let index = menu.findIndex(item => item.path === ele.path); |
| | | if (index === -1) { |
| | | menu.push(ele); |
| | | } else { |
| | | menu[index] = ele; |
| | | } |
| | | }); |
| | | state.menuAll = menu; |
| | | setStore({ name: 'menuAll', content: state.menuAll }); |
| | | }, |
| | | SET_MENU_ALL_NULL: state => { |
| | | state.menuAll = []; |
| | | setStore({ name: 'menuAll', content: state.menuAll }); |
| | | }, |
| | | SET_MENU: (state, menu) => { |
| | | state.menu = menu; |
| | | setStore({ name: 'menu', content: state.menu }); |
| | | }, |
| | | SET_ROLES: (state, roles) => { |
| | | state.roles = roles; |
| | | }, |
| | | SET_PERMISSION: (state, permission) => { |
| | | let result = []; |
| | | function getCode(list) { |
| | | list.forEach(ele => { |
| | | if (typeof ele === 'object') { |
| | | const children = ele.children |
| | | const code = ele.code |
| | | if (children) { |
| | | getCode(children) |
| | | } else { |
| | | result.push(code) |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | |
| | | function getCode(list) { |
| | | list.forEach(ele => { |
| | | if (typeof ele === 'object') { |
| | | const children = ele.children; |
| | | const code = ele.code; |
| | | if (children) { |
| | | getCode(children); |
| | | } else { |
| | | result.push(code); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | |
| | | getCode(permission); |
| | | state.permission = {}; |
| | | result.forEach(ele => { |
| | | state.permission[ele] = true; |
| | | }); |
| | | setStore({ name: 'permission', content: state.permission, type: 'session' }); |
| | | }, |
| | | }, |
| | | }; |
| | | export default user; |
| | | getCode(permission) |
| | | state.permission = {} |
| | | result.forEach(ele => { |
| | | state.permission[ele] = true |
| | | }) |
| | | setStore({ name: 'permission', content: state.permission, type: 'session' }) |
| | | }, |
| | | }, |
| | | } |
| | | export default user |
| | |
| | | //变量 |
| | | $gd-placeholder: #86909C; |
| | | |
| | | .gd-table { |
| | | height: 0; |
| | |
| | | border-bottom: 1px solid #DBDFF1 !important; |
| | | |
| | | .cell { |
| | | padding: 0; |
| | | padding-left: 16px; |
| | | |
| | | padding: 0 0 0 16px; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | |
| | | height: 56px; |
| | | |
| | | .cell { |
| | | padding: 0; |
| | | padding-left: 16px; |
| | | |
| | | padding: 0 0 0 16px; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | .gd-input { |
| | | .el-input__wrapper { |
| | | .el-input__wrapper,.el-textarea__inner { |
| | | padding: 0 8px !important; |
| | | background: #DDE2ED; |
| | | background: #F2F3F5; |
| | | box-shadow: none !important; |
| | | border: none; |
| | | } |
| | | |
| | | .el-input__inner { |
| | | color: #383874; |
| | | |
| | | &::placeholder { |
| | | color: #A1A3D4; |
| | | } |
| | | .el-input__inner,.el-textarea__inner { |
| | | &::placeholder { |
| | | color: $gd-placeholder; |
| | | } |
| | | } |
| | | |
| | | |
| | | &.is-disabled { |
| | | .el-input__wrapper { |
| | | background-color: #DDE2ED; |
| | | background: #DDE2ED; |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | .el-select__placeholder { |
| | | &.is-transparent { |
| | | color: #A1A3D4 !important; |
| | | color: $gd-placeholder !important; |
| | | } |
| | | |
| | | &.el-select__selected-item { |
| | |
| | | color: #fff; |
| | | |
| | | &::placeholder { |
| | | color: #A1A3D4; |
| | | color: $gd-placeholder; |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | .el-textarea { |
| | | |
| | | .el-textarea__inner { |
| | | color: #fff; |
| | | background: #DDE2ED !important; |
| | | border: none; |
| | | box-shadow: none; |
| | | } |
| | | } |
| | | |
| | | .el-button { |
| | | color: #fff; |
| | | background: #DDE2ED !important; |
| | |
| | | } |
| | | } |
| | | |
| | | .el-input { |
| | | .el-input__wrapper { |
| | | padding: 0 8px !important; |
| | | background: #F2F3F5; |
| | | box-shadow: none !important; |
| | | border: none; |
| | | |
| | | .el-input__inner { |
| | | color: #383874; |
| | | |
| | | &::placeholder { |
| | | color: #86909C; |
| | | } |
| | | } |
| | | } |
| | | |
| | | &.is-disabled { |
| | | .el-input__wrapper { |
| | | background-color: #F2F3F5; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | <template> |
| | | <el-dialog class="gd-dialog" v-model="visible" :title="titleEnum[dialogMode]" @closed="handleClosed" destroy-on-close> |
| | | <el-dialog |
| | | class="gd-dialog" |
| | | v-model="visible" |
| | | :title="titleEnum[dialogMode]" |
| | | @closed="visible = false" |
| | | destroy-on-close |
| | | > |
| | | <div class="detail-container" v-if="dialogReadonly"> |
| | | <div class="detail-title">设备详情</div> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <div class="label">设备名称</div> |
| | |
| | | <div class="val">{{ formData.manufacturer }}</div> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <div class="detail-title">维护详情</div> |
| | | <div class="gd-table-container" v-loading="loading"> |
| | | <div class="gd-table-content"> |
| | | <el-table class="gd-table" :data="list"> |
| | | <el-table-column type="index" width="60" label="序号" /> |
| | | <el-table-column prop="maintainTime" label="维护时间" /> |
| | | <el-table-column prop="maintainContent" label="维护内容" /> |
| | | <el-table-column prop="replacePart" label="跟换部件" /> |
| | | </el-table> |
| | | </div> |
| | | |
| | | <div class="gd-pagination-parent"> |
| | | <el-pagination |
| | | popper-class="gd-select-popper" |
| | | v-model:current-page="searchParams.current" |
| | | v-model:page-size="searchParams.size" |
| | | layout="total, prev, pager, next, sizes" |
| | | :total="total" |
| | | @change="getList" |
| | | /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <el-form |
| | |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="维护计划时间" prop="planCycleValue"> |
| | | <el-select |
| | | class="gd-select" |
| | | popper-class="gd-select-popper" |
| | | v-model="formData.planCycleValue" |
| | | placeholder="请选择" |
| | | clearable |
| | | multiple |
| | | :disabled="!formData.planCycleType" |
| | | > |
| | | <el-option |
| | | v-for="item in planCycleValueOptions" |
| | | :key="item.value" |
| | | :label="item.value" |
| | | :value="item.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button color="#F2F3F5" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button> |
| | | <el-button color="#F2F3F5" @click="visible = false">{{ dialogReadonly ? '关闭' : '取消' }}</el-button> |
| | | <el-button |
| | | class="save-btn" |
| | | color="#4C34FF" |
| | |
| | | import { computed, ref } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import { fieldRules, getDictLabel } from '@ztzf/utils' |
| | | import { fwDeviceMaintainRecordPageApi } from '@/views/basicManage/maintainRecord/fwDeviceMaintainRecord' |
| | | import { |
| | | fwDeviceMaintainPlanDetailApi, |
| | | fwDeviceMaintainPlanSubmitApi, |
| | | fwDevicePageApi, |
| | | } from '@/views/basicManage/maintainRecord/maintainRecordApi' |
| | | |
| | | const initForm = () => ({ |
| | |
| | | }) |
| | | |
| | | const planCycleOptions = inject('planCycleOptions') |
| | | const planCycleValueOptions = ref([]) |
| | | |
| | | const emit = defineEmits(['success']) |
| | | const formRef = ref(null) // 表单实例 |
| | | const formData = ref(initForm()) // 表单数据 |
| | | const visible = ref(false) // 弹框显隐 |
| | | const visible = defineModel() // 弹框显隐 |
| | | const dialogMode = ref('add') // 弹框模式 |
| | | const submitting = ref(false) // 提交中 |
| | | const deviceList = ref([]) // 设备列表 |
| | | const getPlanCycleLabel = inject('getPlanCycleLabel') |
| | | const dictObj = inject('dictObj') |
| | | const dialogReadonly = computed(() => dialogMode.value === 'view') |
| | | const titleEnum = ref({ edit: '编辑', view: '查看', add: '维护计划' }) |
| | | |
| | | const planCycleLabel = computed(() => { |
| | | const item = planCycleOptions.find(option => option.value === formData.value.planCycleType) |
| | | return item?.label || formData.value.planCycleType || '-' |
| | | }) |
| | | const titleEnum = ref({ edit: '编辑', view: '查看', add: '新增' }) |
| | | |
| | | const rules = { |
| | | deviceId: fieldRules(true), |
| | | planCycleType: fieldRules(true), |
| | | planCycleValue: [{ required: true, message: '请选择', trigger: ['blur', 'change'] }], |
| | | } |
| | | |
| | | // 获取设备列表 |
| | | function getDeviceList() { |
| | | return fwDevicePageApi({ current: 1, size: 999 }).then(res => { |
| | | deviceList.value = res?.data?.data?.records ?? [] |
| | | }) |
| | | } |
| | | |
| | | // 关闭弹框 |
| | | function handleCancel() { |
| | | visible.value = false |
| | | } |
| | | |
| | | // 提交新增/编辑 |
| | |
| | | if (!formData.value.id) return |
| | | const res = await fwDeviceMaintainPlanDetailApi({ id: formData.value.id }) |
| | | formData.value = res?.data?.data ?? {} |
| | | console.log(formData.value, 66) |
| | | } |
| | | |
| | | // 关闭后重置 |
| | | function handleClosed() { |
| | | formData.value = initForm() |
| | | } |
| | | |
| | | const initSearchParams = () => ({ |
| | | current: 1, // 当前页 |
| | | size: 10, // 每页大小 |
| | | }) |
| | | const searchParams = ref(initSearchParams()) |
| | | const total = ref(0) // 总条数 |
| | | const loading = ref(true) // 列表加载中 |
| | | const list = ref([]) // 列表数据 |
| | | async function getList() { |
| | | loading.value = true |
| | | try { |
| | | const params = { ...searchParams.value, planId: formData.value.id } |
| | | const res = await fwDeviceMaintainRecordPageApi(params) |
| | | list.value = res?.data?.data?.records ?? [] |
| | | total.value = res?.data?.data?.total ?? 0 |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | // 打开弹框 |
| | | async function open({ mode, row } = {}) { |
| | | dialogMode.value = mode || 'add' |
| | | visible.value = true |
| | | await getDeviceList() |
| | | if (dialogMode.value === 'add') { |
| | | formData.value = initForm() |
| | | } else { |
| | | formData.value = row |
| | | async function open({ mode = 'add', row } = {}) { |
| | | dialogMode.value = mode |
| | | formData.value = dialogMode.value === 'add' ? initForm() : row |
| | | if (dialogMode.value !== 'add') { |
| | | await loadDetail() |
| | | getList() |
| | | } |
| | | } |
| | | |
| | | defineExpose({ open }) |
| | | |
| | | watch( |
| | | () => formData.value?.planCycleType, |
| | | type => { |
| | | planCycleValueOptions.value = [] |
| | | if (!type) return |
| | | if (type === '1') { |
| | | ;[...Array(12)].forEach((item, index) => { |
| | | ;[...Array(31)].forEach((item1, index1) => { |
| | | planCycleValueOptions.value.push({ value: `${index + 1}月${index1 + 1}号` }) |
| | | }) |
| | | }) |
| | | } else if (type === '2') { |
| | | ;[...Array(31)].forEach((item, index) => { |
| | | planCycleValueOptions.value.push({ value: `${index + 1}号` }) |
| | | }) |
| | | } else if (type === '3') { |
| | | ;[...Array(7)].forEach((item, index) => { |
| | | planCycleValueOptions.value.push({ value: `星期${index + 1}` }) |
| | | }) |
| | | } |
| | | } |
| | | ) |
| | | </script> |
| | |
| | | </el-form> |
| | | |
| | | <div class="gd-table-toolbar"> |
| | | <el-button :icon="Plus" color="#4C34FF" type="primary" @click="handleAdd">维护计划</el-button> |
| | | <el-button :icon="Plus" color="#4C34FF" type="primary" @click="openForm('add')">新增</el-button> |
| | | <el-button :icon="Delete" color="#4C34FF" :disabled="!selectedIds.length" @click="handleDelete()">删除</el-button> |
| | | </div> |
| | | |
| | |
| | | </el-table-column> |
| | | <el-table-column label="操作" class-name="operation-btns"> |
| | | <template v-slot="{ row }"> |
| | | <el-link @click="handleView(row)">查看</el-link> |
| | | <el-link @click="maintenance(row)">维护</el-link> |
| | | <el-link @click="openForm('view', row)">查看</el-link> |
| | | <el-link @click="openForm('edit', row)">编辑</el-link> |
| | | <el-link @click="handleDelete(row)">删除</el-link> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | </div> |
| | | </div> |
| | | |
| | | <FormDiaLog ref="dialogRef" @success="getList" /> |
| | | <MaintenanceDiaLog ref="maintenanceDialogRef" @success="getList" /> |
| | | <FormDiaLog ref="dialogRef" @success="getList" v-if="dialogVisible" v-model="dialogVisible" /> |
| | | </basic-container> |
| | | </template> |
| | | <script setup> |
| | |
| | | import { getDeptTree } from '@/api/system/dept' |
| | | import { getDictLabel } from '@ztzf/utils' |
| | | import FormDiaLog from './FormDiaLog.vue' |
| | | import MaintenanceDiaLog from '@/views/basicManage/maintainRecord/MaintenanceDiaLog.vue' |
| | | import { |
| | | fwDeviceMaintainPlanPageApi, |
| | | fwDeviceMaintainPlanRemoveApi, |
| | |
| | | const selectedIds = ref([]) // 勾选的ID列表 |
| | | const queryParamsRef = ref(null) // 查询表单实例 |
| | | const dialogRef = ref(null) // 弹框实例 |
| | | const maintenanceDialogRef = ref(null) // 弹框实例 |
| | | const dialogVisible = ref(false) |
| | | const dictObj = ref({ |
| | | deviceType: [], // 设备类型 |
| | | deviceAtt: [], // 设备属性 |
| | |
| | | getList() |
| | | } |
| | | |
| | | // 查看 |
| | | function handleView(row) { |
| | | dialogRef.value?.open({ mode: 'view', row: { ...row } }) |
| | | } |
| | | |
| | | // 维护 |
| | | function maintenance(row) { |
| | | maintenanceDialogRef.value?.open({ mode: 'edit', row: { ...row } }) |
| | | // 新增/编辑/查看 弹框 |
| | | function openForm(mode, row) { |
| | | dialogVisible.value = true |
| | | nextTick(() => { |
| | | dialogRef.value?.open({ mode, row }) |
| | | }) |
| | | } |
| | | |
| | | // 删除 |
| | |
| | | getDeptTree().then(res => { |
| | | deptTree.value = res.data.data |
| | | }) |
| | | } |
| | | |
| | | // 新增 |
| | | function handleAdd() { |
| | | dialogRef.value?.open({ mode: 'add' }) |
| | | } |
| | | |
| | | function getPlanCycleLabel(row) { |
| New file |
| | |
| | | <template> |
| | | <el-dialog |
| | | class="gd-dialog" |
| | | v-model="visible" |
| | | :title="titleEnum[dialogMode]" |
| | | @closed="visible = false" |
| | | destroy-on-close |
| | | > |
| | | <div class="detail-container" v-if="dialogReadonly"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <div class="label">标题</div> |
| | | <div class="val">{{ formData.title }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">数据名称</div> |
| | | <div class="val">{{ formData.dataName }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">提出部门</div> |
| | | <div class="val">{{ formData.proposeDeptName }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">数据提供部门</div> |
| | | <div class="val">{{ formData.dataProvideDeptName }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">评分</div> |
| | | <div class="val">{{ formData.score }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">是否解决</div> |
| | | <div class="val">{{ formData.isResolved === '1' ? '是' : '否' }}</div> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <div class="label">评价内容</div> |
| | | <div class="val">{{ formData.evaluationContent }}</div> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | |
| | | <el-form |
| | | class="dialog-form" |
| | | v-else |
| | | ref="formRef" |
| | | :model="formData" |
| | | :rules="rules" |
| | | :disabled="dialogReadonly" |
| | | label-width="80px" |
| | | > |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="标题" prop="title"> |
| | | <el-input class="gd-input" v-model="formData.title" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="数据名称" prop="dataName"> |
| | | <el-input class="gd-input" v-model="formData.dataName" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="提出部门" prop="proposeDeptId"> |
| | | <el-tree-select |
| | | class="gd-select" |
| | | popper-class="gd-tree-select-popper" |
| | | v-model="formData.proposeDeptId" |
| | | node-key="id" |
| | | :data="deptTree" |
| | | :props="treeProps" |
| | | check-strictly |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="数据提供部门" prop="dataProvideDeptId"> |
| | | <el-tree-select |
| | | class="gd-select" |
| | | popper-class="gd-tree-select-popper" |
| | | v-model="formData.dataProvideDeptId" |
| | | node-key="id" |
| | | :data="deptTree" |
| | | :props="treeProps" |
| | | check-strictly |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="评分" prop="score"> |
| | | <el-input-number |
| | | class="gd-input" |
| | | v-model="formData.score" |
| | | :min="1" |
| | | :max="10" |
| | | placeholder="请输入" |
| | | controls-position="right" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="是否解决" prop="isResolved"> |
| | | <el-select |
| | | class="gd-select" |
| | | popper-class="gd-select-popper" |
| | | v-model="formData.isResolved" |
| | | placeholder="请选择" |
| | | clearable |
| | | > |
| | | <el-option v-for="item in isResolvedOptions" :key="item.value" :label="item.label" :value="item.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="评价内容" prop="evaluationContent"> |
| | | <el-input |
| | | class="gd-input" |
| | | v-model="formData.evaluationContent" |
| | | type="textarea" |
| | | :rows="4" |
| | | placeholder="请输入" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button color="#F2F3F5" @click="visible = false">{{ dialogReadonly ? '关闭' : '取消' }}</el-button> |
| | | <el-button |
| | | class="save-btn" |
| | | color="#4C34FF" |
| | | v-if="!dialogReadonly" |
| | | :loading="submitting" |
| | | :disabled="submitting" |
| | | @click="handleSubmit" |
| | | > |
| | | 保存 |
| | | </el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { computed, ref } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import { fieldRules } from '@ztzf/utils' |
| | | import { |
| | | gdDataEvaluationDetailApi, |
| | | gdDataEvaluationSubmitApi, |
| | | } from '@/views/orderView/orderDataManage/evaluate/evaluateApi' |
| | | |
| | | // 初始化表单数据 |
| | | const initForm = () => ({ |
| | | title: '', |
| | | dataName: '', |
| | | proposeDeptId: '', |
| | | dataProvideDeptId: '', |
| | | score: null, |
| | | isResolved: '', |
| | | evaluationContent: '', |
| | | }) |
| | | |
| | | const deptTree = inject('deptTree') |
| | | const treeProps = inject('treeProps') |
| | | const isResolvedOptions = inject('isResolvedOptions') |
| | | |
| | | const emit = defineEmits(['success']) |
| | | const formRef = ref(null) // 表单实例 |
| | | const formData = ref(initForm()) // 表单数据 |
| | | const visible = defineModel() // 弹框显隐 |
| | | const dialogMode = ref('add') // 弹框模式 |
| | | const submitting = ref(false) // 提交中 |
| | | const dialogReadonly = computed(() => dialogMode.value === 'view') |
| | | const titleEnum = ref({ edit: '编辑', view: '查看', add: '新增' }) |
| | | |
| | | const rules = { |
| | | title: fieldRules(true), |
| | | dataName: fieldRules(true), |
| | | proposeDeptId: fieldRules(true), |
| | | dataProvideDeptId: fieldRules(true), |
| | | score: fieldRules(true), |
| | | isResolved: fieldRules(true), |
| | | evaluationContent: fieldRules(true), |
| | | } |
| | | |
| | | // 提交新增/编辑 |
| | | async function handleSubmit() { |
| | | const isValid = await formRef.value?.validate().catch(() => false) |
| | | if (!isValid) return |
| | | submitting.value = true |
| | | try { |
| | | await gdDataEvaluationSubmitApi(formData.value) |
| | | ElMessage.success(dialogMode.value === 'add' ? '新增成功' : '更新成功') |
| | | visible.value = false |
| | | emit('success') |
| | | } finally { |
| | | submitting.value = false |
| | | } |
| | | } |
| | | |
| | | // 加载详情 |
| | | async function loadDetail() { |
| | | if (!formData.value.id) return |
| | | const res = await gdDataEvaluationDetailApi({ id: formData.value.id }) |
| | | formData.value = res?.data?.data ?? {} |
| | | } |
| | | |
| | | // 打开弹框 |
| | | async function open({ mode = 'add', row } = {}) { |
| | | dialogMode.value = mode |
| | | formData.value = dialogMode.value === 'add' ? initForm() : row |
| | | if (dialogMode.value !== 'add') { |
| | | await loadDetail() |
| | | } |
| | | } |
| | | |
| | | defineExpose({ open }) |
| | | </script> |
| New file |
| | |
| | | import request from '@/axios' |
| | | |
| | | // 列表 |
| | | export const gdDataEvaluationPageApi = params => { |
| | | return request({ |
| | | url: `/drone-gd/orderdata/gdDataEvaluation/page`, |
| | | method: 'get', |
| | | params: { descs: 'update_time', ...params }, |
| | | }) |
| | | } |
| | | |
| | | // 新增或编辑 |
| | | export const gdDataEvaluationSubmitApi = data => { |
| | | return request({ |
| | | url: `/drone-gd/orderdata/gdDataEvaluation/submit`, |
| | | method: 'post', |
| | | data, |
| | | }) |
| | | } |
| | | |
| | | // 删除 |
| | | export const gdDataEvaluationRemoveApi = params => { |
| | | return request({ |
| | | url: `/drone-gd/orderdata/gdDataEvaluation/remove`, |
| | | method: 'post', |
| | | params, |
| | | }) |
| | | } |
| | | |
| | | // 详情 |
| | | export const gdDataEvaluationDetailApi = params => { |
| | | return request({ |
| | | url: `/drone-gd/orderdata/gdDataEvaluation/detail`, |
| | | method: 'get', |
| | | params, |
| | | }) |
| | | } |
| | |
| | | <template> |
| | | <basic-container> |
| | | 评价管理 |
| | | </basic-container> |
| | | <basic-container> |
| | | <el-form ref="queryParamsRef" :model="searchParams" class="gd-search-form"> |
| | | <el-form-item label="标题" prop="title"> |
| | | <el-input class="gd-input" v-model="searchParams.title" placeholder="请输入" clearable @clear="handleSearch" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="是否解决" prop="isResolved"> |
| | | <el-select |
| | | class="gd-select" |
| | | popper-class="gd-select-popper" |
| | | v-model="searchParams.isResolved" |
| | | placeholder="请选择" |
| | | clearable |
| | | @change="handleSearch" |
| | | > |
| | | <el-option v-for="item in isResolvedOptions" :key="item.value" :label="item.label" :value="item.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item class="gd-search-actions"> |
| | | <el-button :icon="RefreshRight" @click="resetForm"></el-button> |
| | | <el-button class="search-btn" :icon="Search" @click="handleSearch"></el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <div class="gd-table-toolbar"> |
| | | <el-button :icon="Plus" color="#4C34FF" type="primary" @click="openForm('add')">新增</el-button> |
| | | <el-button :icon="Delete" color="#4C34FF" :disabled="!selectedIds.length" @click="handleDelete()">删除</el-button> |
| | | </div> |
| | | |
| | | <div class="gd-table-container" v-loading="loading"> |
| | | <div class="gd-table-content gd-table-content-bg"> |
| | | <el-table class="gd-table" :data="list" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="46" /> |
| | | <el-table-column prop="title" show-overflow-tooltip label="标题" /> |
| | | <el-table-column prop="dataName" show-overflow-tooltip label="数据名称" /> |
| | | <el-table-column prop="proposeDeptName" show-overflow-tooltip label="提出部门" /> |
| | | <el-table-column prop="dataProvideDeptName" show-overflow-tooltip label="数据提供部门" /> |
| | | <el-table-column prop="score" show-overflow-tooltip label="评分" /> |
| | | <el-table-column prop="isResolved" show-overflow-tooltip label="是否解决"> |
| | | <template v-slot="{ row }"> |
| | | {{ row.isResolved === '1' ? '是' : '否' }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="evaluationContent" show-overflow-tooltip label="评价内容" /> |
| | | <el-table-column label="操作" class-name="operation-btns"> |
| | | <template v-slot="{ row }"> |
| | | <el-link @click="openForm('view', row)">查看</el-link> |
| | | <el-link @click="openForm('edit', row)">编辑</el-link> |
| | | <el-link @click="handleDelete(row)">删除</el-link> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | |
| | | <div class="gd-pagination-parent"> |
| | | <el-pagination |
| | | popper-class="gd-select-popper" |
| | | v-model:current-page="searchParams.current" |
| | | v-model:page-size="searchParams.size" |
| | | layout="total, prev, pager, next, sizes" |
| | | :total="total" |
| | | @change="getList" |
| | | /> |
| | | </div> |
| | | </div> |
| | | |
| | | <FormDiaLog ref="dialogRef" @success="getList" v-if="dialogVisible" v-model="dialogVisible" /> |
| | | </basic-container> |
| | | </template> |
| | | <script setup> |
| | | import { Search, RefreshRight, Plus, Delete } from '@element-plus/icons-vue' |
| | | import { onMounted, ref } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { getDeptTree } from '@/api/system/dept' |
| | | import FormDiaLog from './FormDiaLog.vue' |
| | | import { |
| | | gdDataEvaluationPageApi, |
| | | gdDataEvaluationRemoveApi, |
| | | } from '@/views/orderView/orderDataManage/evaluate/evaluateApi' |
| | | |
| | | // 初始化查询参数 |
| | | const initSearchParams = () => ({ |
| | | title: '', // 标题 |
| | | isResolved: '', // 是否解决 |
| | | current: 1, // 当前页 |
| | | size: 10, // 每页大小 |
| | | }) |
| | | const searchParams = ref(initSearchParams()) // 查询参数 |
| | | const total = ref(0) // 总条数 |
| | | const loading = ref(true) // 列表加载中 |
| | | const list = ref([]) // 列表数据 |
| | | const selectedIds = ref([]) // 勾选的ID列表 |
| | | const queryParamsRef = ref(null) // 查询表单实例 |
| | | const dialogRef = ref(null) // 弹框实例 |
| | | const dialogVisible = ref(false) |
| | | const deptTree = ref([]) // 部门树 |
| | | const treeProps = { |
| | | label: 'name', |
| | | children: 'children', |
| | | } |
| | | const isResolvedOptions = [ |
| | | { label: '否', value: '0' }, |
| | | { label: '是', value: '1' }, |
| | | ] |
| | | provide('deptTree', deptTree) |
| | | provide('treeProps', treeProps) |
| | | provide('isResolvedOptions', isResolvedOptions) |
| | | |
| | | // 获取列表 |
| | | async function getList() { |
| | | loading.value = true |
| | | try { |
| | | const res = await gdDataEvaluationPageApi(searchParams.value) |
| | | list.value = res?.data?.data?.records ?? [] |
| | | total.value = res?.data?.data?.total ?? 0 |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | // 查询 |
| | | function handleSearch() { |
| | | searchParams.value.current = 1 |
| | | getList() |
| | | } |
| | | |
| | | // 重置查询 |
| | | function resetForm() { |
| | | queryParamsRef.value?.resetFields() |
| | | searchParams.value.current = 1 |
| | | getList() |
| | | } |
| | | |
| | | // 新增/编辑/查看 弹框 |
| | | function openForm(mode, row) { |
| | | dialogVisible.value = true |
| | | nextTick(() => { |
| | | dialogRef.value?.open({ mode, row }) |
| | | }) |
| | | } |
| | | |
| | | // 删除 |
| | | async function handleDelete(row) { |
| | | const tips = row ? '该条' : '选中的项' |
| | | await ElMessageBox.confirm(`确认删除${tips}吗?`, '提示', { |
| | | type: 'warning', |
| | | customClass: 'gd-confirm-custom', |
| | | confirmButtonClass: 'gd-confirm-button', |
| | | cancelButtonClass: 'gd-confirm-cancel-button', |
| | | }) |
| | | const ids = row ? row.id : selectedIds.value.join(',') |
| | | await gdDataEvaluationRemoveApi({ ids }) |
| | | ElMessage.success('删除成功') |
| | | selectedIds.value = [] |
| | | getList() |
| | | } |
| | | |
| | | // 勾选值设置 |
| | | function handleSelectionChange(rows) { |
| | | selectedIds.value = rows.map(item => item.id) |
| | | } |
| | | |
| | | // 获取部门树 |
| | | function getDeptTreeFun() { |
| | | getDeptTree().then(res => { |
| | | deptTree.value = res.data.data |
| | | }) |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getList() |
| | | getDeptTreeFun() |
| | | }) |
| | | </script> |
| | | <style scoped lang="scss"> |
| | | </style> |
| | | <style scoped lang="scss"></style> |
| New file |
| | |
| | | <template> |
| | | <el-dialog |
| | | class="gd-dialog" |
| | | v-model="visible" |
| | | :title="titleEnum[dialogMode]" |
| | | @closed="visible = false" |
| | | destroy-on-close |
| | | > |
| | | <div class="detail-container" v-if="dialogReadonly"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <div class="label">需求名称</div> |
| | | <div class="val">{{ formData.demandName }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">需求类型</div> |
| | | <div class="val">{{ getDictLabel(formData.demandType, dictObj.requirementType) }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">需求联系人</div> |
| | | <div class="val">{{ formData.contactPerson }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">需求联系人电话</div> |
| | | <div class="val">{{ formData.contactPhone }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">需求邮箱</div> |
| | | <div class="val">{{ formData.contactEmail }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">更新周期</div> |
| | | <div class="val">{{ formData.updateCycle }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">申请依据</div> |
| | | <div class="val">{{ formData.applyBasis }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">共享类型</div> |
| | | <div class="val">{{ getDictLabel(formData.shareType, dictObj.sharedType) }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">应用场景类型</div> |
| | | <div class="val">{{ getDictLabel(formData.applicationScene, dictObj.appSceneType) }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">责任部门</div> |
| | | <div class="val">{{ formData.responsibleDeptName }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">数据来源依据</div> |
| | | <div class="val">{{ formData.dataSource }}</div> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <div class="label">需求信息项</div> |
| | | <div class="val">{{ formData.demandInfo }}</div> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | |
| | | <el-form |
| | | class="dialog-form" |
| | | v-else |
| | | ref="formRef" |
| | | :model="formData" |
| | | :rules="rules" |
| | | :disabled="dialogReadonly" |
| | | label-width="120px" |
| | | > |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="需求名称" prop="demandName"> |
| | | <el-input class="gd-input" v-model="formData.demandName" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="需求类型" prop="demandType"> |
| | | <el-select |
| | | class="gd-select" |
| | | popper-class="gd-select-popper" |
| | | v-model="formData.demandType" |
| | | placeholder="请选择" |
| | | clearable |
| | | > |
| | | <el-option |
| | | v-for="item in dictObj.requirementType" |
| | | :key="item.dictKey" |
| | | :label="item.dictValue" |
| | | :value="item.dictKey" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="需求联系人" prop="contactPerson"> |
| | | <el-input class="gd-input" v-model="formData.contactPerson" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="需求联系人电话" prop="contactPhone"> |
| | | <el-input class="gd-input" v-model="formData.contactPhone" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="需求邮箱" prop="contactEmail"> |
| | | <el-input class="gd-input" v-model="formData.contactEmail" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="更新周期" prop="updateCycle"> |
| | | <el-input class="gd-input" v-model="formData.updateCycle" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="申请依据" prop="applyBasis"> |
| | | <el-input class="gd-input" v-model="formData.applyBasis" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="共享类型" prop="shareType"> |
| | | <el-select |
| | | class="gd-select" |
| | | popper-class="gd-select-popper" |
| | | v-model="formData.shareType" |
| | | placeholder="请选择" |
| | | clearable |
| | | > |
| | | <el-option |
| | | v-for="item in dictObj.sharedType" |
| | | :key="item.dictKey" |
| | | :label="item.dictValue" |
| | | :value="item.dictKey" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="应用场景类型" prop="applicationScene"> |
| | | <el-select |
| | | class="gd-select" |
| | | popper-class="gd-select-popper" |
| | | v-model="formData.applicationScene" |
| | | placeholder="请选择" |
| | | clearable |
| | | > |
| | | <el-option |
| | | v-for="item in dictObj.appSceneType" |
| | | :key="item.dictKey" |
| | | :label="item.dictValue" |
| | | :value="item.dictKey" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="责任部门" prop="responsibleDeptId"> |
| | | <el-tree-select |
| | | class="gd-select" |
| | | popper-class="gd-tree-select-popper" |
| | | v-model="formData.responsibleDeptId" |
| | | node-key="id" |
| | | :data="deptTree" |
| | | :props="treeProps" |
| | | check-strictly |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="数据来源依据" prop="dataSource"> |
| | | <el-input class="gd-input" v-model="formData.dataSource" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="需求信息项" prop="demandInfo"> |
| | | <el-input |
| | | class="gd-input" |
| | | v-model="formData.demandInfo" |
| | | type="textarea" |
| | | :rows="4" |
| | | placeholder="请输入" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button color="#F2F3F5" @click="visible = false">{{ dialogReadonly ? '关闭' : '取消' }}</el-button> |
| | | <el-button |
| | | class="save-btn" |
| | | color="#4C34FF" |
| | | v-if="!dialogReadonly" |
| | | :loading="submitting" |
| | | :disabled="submitting" |
| | | @click="handleSubmit" |
| | | > |
| | | 保存 |
| | | </el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { computed, ref } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import { fieldRules } from '@ztzf/utils' |
| | | import { getDictLabel } from '@ztzf/utils' |
| | | import { |
| | | gdSupplyDemandDetailApi, |
| | | gdSupplyDemandSubmitApi, |
| | | } from '@/views/orderView/orderDataManage/supplyAdd/supplyAddApi' |
| | | |
| | | // 初始化表单数据 |
| | | const initForm = () => ({ |
| | | demandName: '', |
| | | demandType: '', |
| | | contactPerson: '', |
| | | contactPhone: '', |
| | | contactEmail: '', |
| | | updateCycle: '', |
| | | applyBasis: '', |
| | | shareType: '', |
| | | applicationScene: '', |
| | | responsibleDeptId: '', |
| | | dataSource: '', |
| | | demandInfo: '', |
| | | }) |
| | | |
| | | const dictObj = inject('dictObj') |
| | | const deptTree = inject('deptTree') |
| | | const treeProps = inject('treeProps') |
| | | |
| | | const emit = defineEmits(['success']) |
| | | const formRef = ref(null) // 表单实例 |
| | | const formData = ref(initForm()) // 表单数据 |
| | | const visible = defineModel() // 弹框显隐 |
| | | const dialogMode = ref('add') // 弹框模式 |
| | | const submitting = ref(false) // 提交中 |
| | | const dialogReadonly = computed(() => dialogMode.value === 'view') |
| | | const titleEnum = ref({ edit: '编辑', view: '查看', add: '新增' }) |
| | | |
| | | const rules = { |
| | | demandName: fieldRules(true), |
| | | demandType: fieldRules(true), |
| | | contactPerson: fieldRules(true), |
| | | contactPhone: fieldRules(true), |
| | | contactEmail: fieldRules(true), |
| | | updateCycle: fieldRules(true), |
| | | applyBasis: fieldRules(true), |
| | | shareType: fieldRules(true), |
| | | applicationScene: fieldRules(true), |
| | | responsibleDeptId: fieldRules(true), |
| | | dataSource: fieldRules(true), |
| | | demandInfo: fieldRules(true), |
| | | } |
| | | |
| | | // 提交新增/编辑 |
| | | async function handleSubmit() { |
| | | const isValid = await formRef.value?.validate().catch(() => false) |
| | | if (!isValid) return |
| | | submitting.value = true |
| | | try { |
| | | await gdSupplyDemandSubmitApi(formData.value) |
| | | ElMessage.success(dialogMode.value === 'add' ? '新增成功' : '更新成功') |
| | | visible.value = false |
| | | emit('success') |
| | | } finally { |
| | | submitting.value = false |
| | | } |
| | | } |
| | | |
| | | // 加载详情 |
| | | async function loadDetail() { |
| | | if (!formData.value.id) return |
| | | const res = await gdSupplyDemandDetailApi({ id: formData.value.id }) |
| | | formData.value = res?.data?.data ?? {} |
| | | } |
| | | |
| | | // 打开弹框 |
| | | async function open({ mode = 'add', row } = {}) { |
| | | dialogMode.value = mode |
| | | formData.value = dialogMode.value === 'add' ? initForm() : row |
| | | if (dialogMode.value !== 'add') { |
| | | await loadDetail() |
| | | } |
| | | } |
| | | |
| | | defineExpose({ open }) |
| | | </script> |
| | |
| | | <template> |
| | | <basic-container> |
| | | 供需填报管理 |
| | | </basic-container> |
| | | <basic-container> |
| | | <el-form ref="queryParamsRef" :model="searchParams" class="gd-search-form"> |
| | | <el-form-item label="需求名称" prop="demandName"> |
| | | <el-input |
| | | class="gd-input" |
| | | v-model="searchParams.demandName" |
| | | placeholder="请输入" |
| | | clearable |
| | | @clear="handleSearch" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="需求状态" prop="demandStatus"> |
| | | <el-select |
| | | class="gd-select" |
| | | popper-class="gd-select-popper" |
| | | v-model="searchParams.demandStatus" |
| | | placeholder="请选择" |
| | | clearable |
| | | @change="handleSearch" |
| | | > |
| | | <el-option |
| | | v-for="item in dictObj.demandStatus" |
| | | :key="item.dictKey" |
| | | :label="item.dictValue" |
| | | :value="item.dictKey" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item class="gd-search-actions"> |
| | | <el-button :icon="RefreshRight" @click="resetForm"></el-button> |
| | | <el-button class="search-btn" :icon="Search" @click="handleSearch"></el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <div class="gd-table-toolbar"> |
| | | <el-button :icon="Plus" color="#4C34FF" type="primary" @click="openForm('add')">新增</el-button> |
| | | <el-button :icon="Delete" color="#4C34FF" :disabled="!selectedIds.length" @click="handleDelete()">删除</el-button> |
| | | </div> |
| | | |
| | | <div class="gd-table-container" v-loading="loading"> |
| | | <div class="gd-table-content gd-table-content-bg"> |
| | | <el-table class="gd-table" :data="list" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="46" /> |
| | | <el-table-column prop="demandName" show-overflow-tooltip label="需求名称" /> |
| | | <el-table-column prop="demandType" show-overflow-tooltip label="需求类型"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.demandType, dictObj.requirementType) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="contactPerson" show-overflow-tooltip label="需求联系人" /> |
| | | <el-table-column prop="contactPhone" show-overflow-tooltip label="需求联系人电话" /> |
| | | <el-table-column prop="contactEmail" show-overflow-tooltip label="需求邮箱" /> |
| | | <el-table-column prop="demandStatus" show-overflow-tooltip label="需求状态"> |
| | | <!-- <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.demandStatus, dictObj.demandStatus) }} |
| | | </template> --> |
| | | </el-table-column> |
| | | <el-table-column prop="updateCycle" show-overflow-tooltip label="更新周期" /> |
| | | <el-table-column prop="applyBasis" show-overflow-tooltip label="申请依据" /> |
| | | <el-table-column prop="shareType" show-overflow-tooltip label="共享类型"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.shareType, dictObj.sharedType) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="applicationScene" show-overflow-tooltip label="应用场景类型"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.applicationScene, dictObj.appSceneType) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="responsibleDeptName" show-overflow-tooltip label="责任部门" /> |
| | | <el-table-column prop="dataSource" show-overflow-tooltip label="数据来源依据" /> |
| | | <el-table-column prop="demandInfo" show-overflow-tooltip label="需求信息项" /> |
| | | <el-table-column label="操作" class-name="operation-btns"> |
| | | <template v-slot="{ row }"> |
| | | <el-link @click="openForm('view', row)">查看</el-link> |
| | | <el-link @click="openForm('edit', row)">编辑</el-link> |
| | | <el-link @click="handleDelete(row)">删除</el-link> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | |
| | | <div class="gd-pagination-parent"> |
| | | <el-pagination |
| | | popper-class="gd-select-popper" |
| | | v-model:current-page="searchParams.current" |
| | | v-model:page-size="searchParams.size" |
| | | layout="total, prev, pager, next, sizes" |
| | | :total="total" |
| | | @change="getList" |
| | | /> |
| | | </div> |
| | | </div> |
| | | |
| | | <FormDiaLog ref="dialogRef" @success="getList" v-if="dialogVisible" v-model="dialogVisible" /> |
| | | </basic-container> |
| | | </template> |
| | | <script setup> |
| | | import { Search, RefreshRight, Plus, Delete } from '@element-plus/icons-vue' |
| | | import { onMounted, ref } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { getDictionaryByCode } from '@/api/system/dictbiz' |
| | | import { getDeptTree } from '@/api/system/dept' |
| | | import { getDictLabel } from '@ztzf/utils' |
| | | import FormDiaLog from './FormDiaLog.vue' |
| | | import { |
| | | gdSupplyDemandPageApi, |
| | | gdSupplyDemandRemoveApi, |
| | | } from '@/views/orderView/orderDataManage/supplyAdd/supplyAddApi' |
| | | |
| | | // 初始化查询参数 |
| | | const initSearchParams = () => ({ |
| | | demandName: '', // 需求名称 |
| | | demandStatus: '', // 需求状态 |
| | | current: 1, // 当前页 |
| | | size: 10, // 每页大小 |
| | | }) |
| | | const searchParams = ref(initSearchParams()) // 查询参数 |
| | | const total = ref(0) // 总条数 |
| | | const loading = ref(true) // 列表加载中 |
| | | const list = ref([]) // 列表数据 |
| | | const selectedIds = ref([]) // 勾选的ID列表 |
| | | const queryParamsRef = ref(null) // 查询表单实例 |
| | | const dialogRef = ref(null) // 弹框实例 |
| | | const dialogVisible = ref(false) |
| | | const dictObj = ref({ |
| | | requirementType: [], // 需求类型 |
| | | sharedType: [], // 共享类型 |
| | | appSceneType: [], // 应用场景类型 |
| | | }) |
| | | provide('dictObj', dictObj) |
| | | const deptTree = ref([]) // 部门树 |
| | | const treeProps = { |
| | | label: 'name', |
| | | children: 'children', |
| | | } |
| | | provide('deptTree', deptTree) |
| | | provide('treeProps', treeProps) |
| | | |
| | | // 获取列表 |
| | | async function getList() { |
| | | loading.value = true |
| | | try { |
| | | const res = await gdSupplyDemandPageApi(searchParams.value) |
| | | list.value = res?.data?.data?.records ?? [] |
| | | total.value = res?.data?.data?.total ?? 0 |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | // 查询 |
| | | function handleSearch() { |
| | | searchParams.value.current = 1 |
| | | getList() |
| | | } |
| | | |
| | | // 重置查询 |
| | | function resetForm() { |
| | | queryParamsRef.value?.resetFields() |
| | | searchParams.value.current = 1 |
| | | getList() |
| | | } |
| | | |
| | | // 新增/编辑/查看 弹框 |
| | | function openForm(mode, row) { |
| | | dialogVisible.value = true |
| | | nextTick(() => { |
| | | dialogRef.value?.open({ mode, row }) |
| | | }) |
| | | } |
| | | |
| | | // 删除 |
| | | async function handleDelete(row) { |
| | | const tips = row ? '该条' : '选中的项' |
| | | await ElMessageBox.confirm(`确认删除${tips}吗?`, '提示', { |
| | | type: 'warning', |
| | | customClass: 'gd-confirm-custom', |
| | | confirmButtonClass: 'gd-confirm-button', |
| | | cancelButtonClass: 'gd-confirm-cancel-button', |
| | | }) |
| | | const ids = row ? row.id : selectedIds.value.join(',') |
| | | await gdSupplyDemandRemoveApi({ ids }) |
| | | ElMessage.success('删除成功') |
| | | selectedIds.value = [] |
| | | getList() |
| | | } |
| | | |
| | | // 勾选值设置 |
| | | function handleSelectionChange(rows) { |
| | | selectedIds.value = rows.map(item => item.id) |
| | | } |
| | | |
| | | // 获取字典 |
| | | function getDictList() { |
| | | getDictionaryByCode('requirementType,sharedType,appSceneType').then(res => { |
| | | dictObj.value = res.data.data |
| | | }) |
| | | } |
| | | |
| | | // 获取部门树 |
| | | function getDeptTreeFun() { |
| | | getDeptTree().then(res => { |
| | | deptTree.value = res.data.data |
| | | }) |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getList() |
| | | getDictList() |
| | | getDeptTreeFun() |
| | | }) |
| | | </script> |
| | | <style scoped lang="scss"> |
| | | </style> |
| | | <style scoped lang="scss"></style> |
| New file |
| | |
| | | import request from '@/axios' |
| | | |
| | | // 获取供需需求列表 |
| | | export const gdSupplyDemandPageApi = params => { |
| | | return request({ |
| | | url: `/drone-gd/orderdata/gdSupplyDemand/page`, |
| | | method: 'get', |
| | | params: { descs: 'update_time', ...params }, |
| | | }) |
| | | } |
| | | |
| | | // 新增或编辑供需需求 |
| | | export const gdSupplyDemandSubmitApi = data => { |
| | | return request({ |
| | | url: `/drone-gd/orderdata/gdSupplyDemand/submit`, |
| | | method: 'post', |
| | | data, |
| | | }) |
| | | } |
| | | |
| | | // 删除供需需求 |
| | | export const gdSupplyDemandRemoveApi = params => { |
| | | return request({ |
| | | url: `/drone-gd/orderdata/gdSupplyDemand/remove`, |
| | | method: 'post', |
| | | params, |
| | | }) |
| | | } |
| | | |
| | | // 获取供需需求详情 |
| | | export const gdSupplyDemandDetailApi = params => { |
| | | return request({ |
| | | url: `/drone-gd/orderdata/gdSupplyDemand/detail`, |
| | | method: 'get', |
| | | params, |
| | | }) |
| | | } |
| | | |
| | | // 审核通过 |
| | | export const gdSupplyDemandAuditPassApi = data => { |
| | | return request({ |
| | | url: `/drone-gd/orderdata/gdSupplyDemand/audit-pass`, |
| | | method: 'post', |
| | | data, |
| | | }) |
| | | } |
| | | |
| | | // 拒绝申请 |
| | | export const gdSupplyDemandAuditRejectApi = data => { |
| | | return request({ |
| | | url: `/drone-gd/orderdata/gdSupplyDemand/audit-reject`, |
| | | method: 'post', |
| | | data, |
| | | }) |
| | | } |
| | |
| | | <template> |
| | | <basic-container> |
| | | 基础管理 |
| | | 基础3管理 |
| | | </basic-container> |
| | | </template> |
| | | <script setup> |
| | |
| | | <template> |
| | | <div> |
| | | |
| | | 测试 |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | </style> |
| | | </style> |
| | |
| | | <script setup> |
| | | import { onHide, onLaunch, onShow } from "@dcloudio/uni-app"; |
| | | import { useAppStore, useUserStore } from "@/store"; |
| | | import { useAppStore, useUserStore, useLocationStore } from "@/store"; |
| | | import { useGlobalWS } from "@/hooks/useGlobalWS.js"; |
| | | |
| | | const appStore = useAppStore(); |
| | | const userStore = useUserStore(); |
| | | const locationStore = useLocationStore(); |
| | | |
| | | useGlobalWS(); |
| | | |
| | | onShow(() => { |
| | | onShow(async () => { |
| | | console.log("App Show"); |
| | | // 应用从后台返回前台时,重新初始化位置服务 |
| | | if (userStore.userInfo && locationStore) { |
| | | try { |
| | | await locationStore.initLocationService(); |
| | | } catch (error) { |
| | | console.error('重新初始化位置服务失败:', error); |
| | | } |
| | | } |
| | | }); |
| | | |
| | | onHide(() => { |
| | | console.log("App Hide"); |
| | | // 应用进入后台时,停止位置监听以节省资源 |
| | | if (locationStore) { |
| | | locationStore.stopLocationWatch(); |
| | | } |
| | | }); |
| | | |
| | | onLaunch(() => { |
| | |
| | | export function useGlobalWS() { |
| | | const userStore = useUserStore(); |
| | | const appStore = useAppStore(); |
| | | const callStatus = ref(null) |
| | | |
| | | // 设置默认用户ID为3 |
| | | const defaultUserId = '3'; |
| | |
| | | console.log('🌐 全局WebSocket收到消息111111111111111111111:', payload) |
| | | // 先尝试直接处理消息(适用于mobile-web-view的voiceCallDetail页面的消息格式) |
| | | const t = (payload.type || '').toString() |
| | | const bizCode = payload.biz_code || '' |
| | | |
| | | console.log('📋 消息分析:type=' + t + ', biz_code=' + bizCode) |
| | | |
| | | // const bizCode = payload.biz_code || '' |
| | | callStatus.value = t |
| | | // console.log('📋 消息分析:type=' + t ) |
| | | // 处理语音通话请求 |
| | | if (t === 'call') { |
| | | console.log('📞 全局收到来电 call,来自', payload.from) |
| | |
| | | try { |
| | | // 优先使用uni-app的导航API(适用于同应用内跳转) |
| | | if (typeof uni !== 'undefined' && uni.navigateTo) { |
| | | console.log('使用uni-app导航API跳转到语音通话页面'); |
| | | uni.navigateTo({ |
| | | url: `/subPackages/voiceCallDetail/index?voiceparams=${encodedParams}`, |
| | | success: () => { |
| | | console.log('✅ 应用内导航成功!'); |
| | | }, |
| | | fail: (err) => { |
| | | console.error('❌ 应用内导航失败:', err); |
| | | } |
| | | }); |
| | | } else { |
| | | console.error('无法跳转到语音通话页面:当前环境不支持导航'); |
| | |
| | | } |
| | | |
| | | // 然后处理biz_code格式的消息 |
| | | switch (bizCode) { |
| | | case 'JOB_ISREFRESH': |
| | | appStore.setJobUpdateKeyAdd() |
| | | break |
| | | case 'DEVICE_ISREFRESH': |
| | | appStore.setDeviceUpdateKeyAdd() |
| | | break |
| | | case 'DOWNLOAD_PROGRESS': |
| | | break |
| | | case 'LOGOUT_USER': |
| | | userStore.setUserInfo(null) |
| | | uni.reLaunch({ |
| | | url: '/pages/login/index' |
| | | }) |
| | | break |
| | | case 'VoiceCall': |
| | | // enterRoom(payload, userId.value) |
| | | break |
| | | default: |
| | | // 记录未处理的消息 |
| | | console.log('未处理的WebSocket消息:', payload) |
| | | break; |
| | | } |
| | | // switch (bizCode) { |
| | | // case 'JOB_ISREFRESH': |
| | | // appStore.setJobUpdateKeyAdd() |
| | | // break |
| | | // case 'DEVICE_ISREFRESH': |
| | | // appStore.setDeviceUpdateKeyAdd() |
| | | // break |
| | | // case 'DOWNLOAD_PROGRESS': |
| | | // break |
| | | // case 'LOGOUT_USER': |
| | | // userStore.setUserInfo(null) |
| | | // uni.reLaunch({ |
| | | // url: '/pages/login/index' |
| | | // }) |
| | | // break |
| | | // case 'VoiceCall': |
| | | // // enterRoom(payload, userId.value) |
| | | // break |
| | | // default: |
| | | // // 记录未处理的消息 |
| | | // console.log('未处理的WebSocket消息:', payload) |
| | | // break; |
| | | // } |
| | | } |
| | | |
| | | // 初始化WebSocket连接 |
| | | function initWS() { |
| | | try { |
| | | // 检查是否已经有活跃的WebSocket连接 |
| | | if (!websocketService.getConnected()) { |
| | | // 使用默认用户ID初始化WebSocket连接 |
| | | websocketService.init(defaultUserId, WS_BASE); |
| | | console.log('🌐 全局WebSocket初始化成功,默认用户ID:', defaultUserId); |
| | | } else { |
| | | console.log('🌐 WebSocket已存在活跃连接,无需重新初始化'); |
| | | } |
| | | |
| | | // 只设置一次全局消息处理回调 |
| | | // 检查是否已经设置了回调 |
| | | if (typeof websocketService.getOnMessageCallback() !== 'function') { |
| | | // 设置全局消息处理回调 |
| | | websocketService.setOnMessageCallback(messageHandler); |
| | | console.log('✅ 全局WebSocket消息处理器已设置'); |
| | | websocketService.setOnMessageCallback(messageHandler); |
| | | |
| | | // 获取当前用户ID,优先使用store中的用户信息 |
| | | const userId = userStore.userInfo?.id || defaultUserId; |
| | | |
| | | // 检查是否已经有活跃的WebSocket连接 |
| | | if (!websocketService.getConnected() || websocketService.userId !== userId) { |
| | | // 使用用户ID初始化WebSocket连接 |
| | | websocketService.init(userId, WS_BASE); |
| | | // console.log('🌐 全局WebSocket初始化成功,用户ID:', userId); |
| | | } else { |
| | | console.log('✅ WebSocket消息处理器已存在,无需重新设置'); |
| | | websocketService.connect(); |
| | | |
| | | } |
| | | } catch (error) { |
| | | console.error('❌ 全局WebSocket初始化失败:', error); |
| | | } |
| | | } |
| | | |
| | | // 监听用户信息变化,初始化WebSocket |
| | | watch( |
| | | () => userStore.userInfo, |
| | | (newUserInfo) => { |
| | | console.log('👤 用户信息变化,尝试初始化WebSocket'); |
| | | () => callStatus.value, |
| | | (newValue) => { |
| | | if (newValue === 'accept') { |
| | | console.log('📞 通话中,跳过WebSocket初始化'); |
| | | return; |
| | | } |
| | | initWS(); |
| | | }, |
| | | { immediate: true } |
| | | { immediate: true, deep: true } |
| | | ) |
| | | } |
| | | |
| | | |
| | |
| | | import { getAssetsImage } from "@/utils/index.js"; |
| | | import md5 from "js-md5"; |
| | | import { loginByUsername } from "@/api/user/index.js"; |
| | | import { useUserStore } from "@/store/index.js"; |
| | | import { useUserStore, useLocationStore } from "@/store/index.js"; |
| | | import locationUtil from "@/utils/location.js"; |
| | | import websocketService from "@/utils/websocket.js"; |
| | | |
| | | import { HOME_PATH, LOGIN_PATH, removeQueryString } from "@/router"; |
| | |
| | | const agreed = ref(true); |
| | | |
| | | const userStore = useUserStore(); |
| | | const locationStore = useLocationStore(); |
| | | const loginForm = ref({ |
| | | username: "", |
| | | password: "", |
| | |
| | | userInfo.key, |
| | | userInfo.code |
| | | ); |
| | | userStore.setUserInfo(res.data.data); |
| | | console.log('登录成功,WebSocket连接将由全局钩子统一管理'); |
| | | userStore.setUserInfo(res.data.data); |
| | | // 请求位置权限并初始化位置服务 |
| | | try { |
| | | // 请求位置权限 |
| | | const hasPermission = await locationUtil.requestLocationPermission(); |
| | | if (hasPermission) { |
| | | console.log('获取位置权限成功'); |
| | | // 初始化位置服务 |
| | | await locationStore.initLocationService(); |
| | | } else { |
| | | console.log('获取位置权限失败'); |
| | | } |
| | | } catch (error) { |
| | | console.error('处理位置服务失败:', error); |
| | | } |
| | | |
| | | uni.reLaunch({ |
| | | url: "/pages/work/index", |
| | | }); |
| | |
| | | import useAppStore from "./modules/app" |
| | | import useUserStore from "./modules/user" |
| | | import useMapStore from "./modules/map" |
| | | import useLocationStore from "./modules/location" |
| | | |
| | | // 安装pinia状态管理插件 |
| | | function setupStore (app) { |
| | |
| | | } |
| | | |
| | | // 导出模块 |
| | | export { useAppStore, useUserStore, useMapStore } |
| | | export { useAppStore, useUserStore, useMapStore, useLocationStore } |
| | | export default setupStore |
| New file |
| | |
| | | import { defineStore } from 'pinia' |
| | | import locationUtil from '@/utils/location.js' |
| | | |
| | | const useLocationStore = defineStore('location', { |
| | | state: () => ({ |
| | | // 当前位置信息 |
| | | currentLocation: null, |
| | | // 位置权限状态 |
| | | hasPermission: false, |
| | | // 系统定位服务是否开启 |
| | | systemLocationEnabled: true, |
| | | // 位置更新间隔(毫秒) |
| | | updateInterval: 5000, |
| | | // 位置监听器ID |
| | | watcherId: null |
| | | }), |
| | | |
| | | getters: { |
| | | /** |
| | | * 获取当前位置 |
| | | * @returns {Object|null} 当前位置信息 |
| | | */ |
| | | getCurrentLocation: (state) => state.currentLocation, |
| | | |
| | | /** |
| | | * 获取位置权限状态 |
| | | * @returns {boolean} 是否有位置权限 |
| | | */ |
| | | getPermissionStatus: (state) => state.hasPermission, |
| | | |
| | | /** |
| | | * 获取系统定位服务状态 |
| | | * @returns {boolean} 系统定位服务是否开启 |
| | | */ |
| | | getSystemLocationStatus: (state) => state.systemLocationEnabled |
| | | }, |
| | | |
| | | actions: { |
| | | /** |
| | | * 初始化位置服务 |
| | | */ |
| | | async initLocationService() { |
| | | try { |
| | | // 检查系统定位服务是否开启 |
| | | this.systemLocationEnabled = await locationUtil.checkSystemLocationEnabled(); |
| | | if (!this.systemLocationEnabled) { |
| | | console.warn('系统定位服务未开启'); |
| | | } |
| | | |
| | | // 请求位置权限 |
| | | this.hasPermission = await locationUtil.requestLocationPermission(); |
| | | if (this.hasPermission) { |
| | | // 获取当前位置 |
| | | await this.updateCurrentLocation(); |
| | | // 开始位置监听 |
| | | this.startLocationWatch(); |
| | | } |
| | | } catch (error) { |
| | | console.error('初始化位置服务失败:', error); |
| | | } |
| | | }, |
| | | |
| | | /** |
| | | * 更新当前位置 |
| | | */ |
| | | async updateCurrentLocation() { |
| | | try { |
| | | const location = await locationUtil.getCurrentLocation(); |
| | | this.currentLocation = location; |
| | | console.log('位置更新:', location); |
| | | return location; |
| | | } catch (error) { |
| | | console.error('更新位置失败:', error); |
| | | return null; |
| | | } |
| | | }, |
| | | |
| | | /** |
| | | * 开始位置监听 |
| | | */ |
| | | startLocationWatch() { |
| | | if (this.watcherId) { |
| | | this.stopLocationWatch(); |
| | | } |
| | | |
| | | this.watcherId = locationUtil.startLocationWatcher((location) => { |
| | | this.currentLocation = location; |
| | | // 可以在这里添加位置信息上报逻辑 |
| | | this.reportLocation(location); |
| | | }, { |
| | | interval: this.updateInterval |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 停止位置监听 |
| | | */ |
| | | stopLocationWatch() { |
| | | if (this.watcherId) { |
| | | locationUtil.stopLocationWatcher(); |
| | | this.watcherId = null; |
| | | } |
| | | }, |
| | | |
| | | /** |
| | | * 重新请求位置权限 |
| | | */ |
| | | async reRequestPermission() { |
| | | this.hasPermission = await locationUtil.requestLocationPermission(); |
| | | if (this.hasPermission) { |
| | | await this.updateCurrentLocation(); |
| | | this.startLocationWatch(); |
| | | } |
| | | return this.hasPermission; |
| | | }, |
| | | |
| | | /** |
| | | * 位置信息上报(可根据实际需求实现) |
| | | * @param {Object} location 位置信息 |
| | | */ |
| | | reportLocation(location) { |
| | | // 这里可以添加位置信息上报到服务器的逻辑 |
| | | // 例如:api.uploadLocation(location) |
| | | // console.log('位置上报:', location); |
| | | }, |
| | | |
| | | /** |
| | | * 清理位置服务 |
| | | */ |
| | | cleanupLocationService() { |
| | | this.stopLocationWatch(); |
| | | this.currentLocation = null; |
| | | } |
| | | } |
| | | }) |
| | | |
| | | export default useLocationStore |
| | |
| | | <div>{{userInfo.deptName}}</div> |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">性别</div> |
| | | <div> |
| | | <u-radio-group v-model="userInfo.sex"> |
| | | <up-radio |
| | | v-for="(item, index) in sexList" |
| | | :key="index" |
| | | :label="item.label" |
| | | :name="item.name" |
| | | @change="radioChange" |
| | | > |
| | | </up-radio> |
| | | </u-radio-group> |
| | | </div> |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">手机号</div> |
| | | <div>{{userInfo.phone}}</div> |
| | | <!-- <u-input input-align="right" v-model="userInfo.phone" type="number" placeholder="请输入手机号" |
| | |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">邮箱</div> |
| | | <div>{{userInfo.email}}</div> |
| | | <!-- <u-input input-align="right" v-model="userInfo.email" type="email" placeholder="请输入邮箱" |
| | | class="input-item" /> --> |
| | | <!-- <div>{{userInfo.email}}</div> --> |
| | | <u-input input-align="right" v-model="userInfo.email" type="email" placeholder="请输入邮箱" |
| | | class="input-item" /> |
| | | </div> |
| | | </div> |
| | | </view> |
| | |
| | | phone: '', |
| | | email: '', |
| | | deptName: '', |
| | | sex: 2, |
| | | }); |
| | | const sexList = [ |
| | | { |
| | | label: '男', |
| | | name: '0' |
| | | }, |
| | | { |
| | | label: '女', |
| | | name: '1' |
| | | }, |
| | | { |
| | | label: '未知', |
| | | name: '2' |
| | | } |
| | | ] |
| | | // 校验手机号 |
| | | const validatePhone = () => { |
| | | const phone = userInfo.value.phone |
| | |
| | | phone: user.sysDept.phone, |
| | | email: user.sysDept.email, |
| | | deptName: user.sysDept.deptName, |
| | | sex: user.sex || 2, |
| | | }; |
| | | |
| | | }); |
| New file |
| | |
| | | /** |
| | | * 位置管理工具类 |
| | | * 用于处理位置权限请求和实时位置获取 |
| | | */ |
| | | import permission from './voiceCallByTX/TrtcCloud/permission.js' |
| | | |
| | | // 平台判断 |
| | | const isIos = () => { |
| | | // #ifdef APP-PLUS |
| | | return plus.os.name === "iOS"; |
| | | // #endif |
| | | return false; |
| | | }; |
| | | |
| | | // 位置更新回调函数 |
| | | let locationUpdateCallback = null; |
| | | // 位置监听器ID |
| | | let locationWatcherId = null; |
| | | |
| | | /** |
| | | * 请求位置权限 |
| | | * @returns {Promise<boolean>} 是否获取到权限 |
| | | */ |
| | | export const requestLocationPermission = async () => { |
| | | return new Promise(async (resolve) => { |
| | | // #ifdef APP-PLUS |
| | | if (isIos()) { |
| | | // iOS平台 |
| | | const hasPermission = permission.judgeIosPermission('location'); |
| | | if (hasPermission) { |
| | | resolve(true); |
| | | } else { |
| | | // iOS需要提示用户手动开启权限 |
| | | uni.showModal({ |
| | | title: '提示', |
| | | content: '应用需要获取位置信息权限,请在设置中开启', |
| | | confirmText: '去设置', |
| | | cancelText: '取消', |
| | | success: (res) => { |
| | | if (res.confirm) { |
| | | permission.gotoAppPermissionSetting(); |
| | | resolve(false); |
| | | } else { |
| | | resolve(false); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | } else { |
| | | // Android平台 |
| | | const result = await permission.requestAndroidPermission('android.permission.ACCESS_FINE_LOCATION'); |
| | | if (result === 1) { |
| | | resolve(true); |
| | | } else if (result === 0) { |
| | | // 拒绝本次申请 |
| | | resolve(false); |
| | | } else if (result === -1) { |
| | | // 永久拒绝 |
| | | uni.showModal({ |
| | | title: '提示', |
| | | content: '应用需要获取位置信息权限,请在设置中开启', |
| | | confirmText: '去设置', |
| | | cancelText: '取消', |
| | | success: (res) => { |
| | | if (res.confirm) { |
| | | permission.gotoAppPermissionSetting(); |
| | | resolve(false); |
| | | } else { |
| | | resolve(false); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | // #endif |
| | | // #ifdef H5 |
| | | // H5平台使用浏览器原生API请求权限 |
| | | if (navigator.geolocation) { |
| | | navigator.permissions.query({ name: 'geolocation' }).then((result) => { |
| | | if (result.state === 'granted') { |
| | | resolve(true); |
| | | } else if (result.state === 'prompt') { |
| | | // 还未请求过权限,会在getLocation时提示 |
| | | resolve(true); |
| | | } else { |
| | | resolve(false); |
| | | } |
| | | }).catch(() => { |
| | | resolve(false); |
| | | }); |
| | | } else { |
| | | resolve(false); |
| | | } |
| | | // #endif |
| | | // #ifdef MP |
| | | // 小程序平台 |
| | | uni.getSetting({ |
| | | success: (res) => { |
| | | if (res.authSetting['scope.userLocation']) { |
| | | resolve(true); |
| | | } else { |
| | | uni.authorize({ |
| | | scope: 'scope.userLocation', |
| | | success: () => { |
| | | resolve(true); |
| | | }, |
| | | fail: () => { |
| | | uni.showModal({ |
| | | title: '提示', |
| | | content: '应用需要获取位置信息权限,请在设置中开启', |
| | | confirmText: '去设置', |
| | | cancelText: '取消', |
| | | success: (res) => { |
| | | if (res.confirm) { |
| | | uni.openSetting(); |
| | | resolve(false); |
| | | } else { |
| | | resolve(false); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | }); |
| | | // #endif |
| | | }); |
| | | }; |
| | | |
| | | /** |
| | | * 获取当前位置信息 |
| | | * @returns {Promise<Object>} 位置信息对象 |
| | | */ |
| | | export const getCurrentLocation = () => { |
| | | return new Promise((resolve, reject) => { |
| | | uni.getLocation({ |
| | | type: 'gcj02', |
| | | altitude: true, |
| | | success: (res) => { |
| | | resolve({ |
| | | latitude: res.latitude, |
| | | longitude: res.longitude, |
| | | altitude: res.altitude, |
| | | accuracy: res.accuracy, |
| | | speed: res.speed, |
| | | verticalAccuracy: res.verticalAccuracy, |
| | | horizontalAccuracy: res.horizontalAccuracy |
| | | }); |
| | | }, |
| | | fail: (err) => { |
| | | console.error('获取位置失败:', err); |
| | | reject(err); |
| | | } |
| | | }); |
| | | }); |
| | | }; |
| | | |
| | | /** |
| | | * 开始实时位置监听 |
| | | * @param {Function} callback 位置更新回调函数 |
| | | * @param {Object} options 监听选项 |
| | | * @returns {number} 监听器ID |
| | | */ |
| | | export const startLocationWatcher = (callback, options = {}) => { |
| | | if (locationWatcherId) { |
| | | stopLocationWatcher(); |
| | | } |
| | | |
| | | locationUpdateCallback = callback; |
| | | |
| | | locationWatcherId = uni.startLocationUpdate({ |
| | | success: () => { |
| | | console.log('开始位置监听成功'); |
| | | }, |
| | | fail: (err) => { |
| | | console.error('开始位置监听失败:', err); |
| | | // 如果是因为权限问题,重新请求权限 |
| | | if (err.errCode === 12002) { |
| | | requestLocationPermission(); |
| | | } |
| | | } |
| | | }); |
| | | |
| | | // 监听位置更新 |
| | | uni.onLocationChange((res) => { |
| | | const locationInfo = { |
| | | latitude: res.latitude, |
| | | longitude: res.longitude, |
| | | altitude: res.altitude, |
| | | accuracy: res.accuracy, |
| | | speed: res.speed, |
| | | verticalAccuracy: res.verticalAccuracy, |
| | | horizontalAccuracy: res.horizontalAccuracy, |
| | | timestamp: res.timestamp |
| | | }; |
| | | |
| | | if (locationUpdateCallback) { |
| | | locationUpdateCallback(locationInfo); |
| | | } |
| | | }); |
| | | |
| | | return locationWatcherId; |
| | | }; |
| | | |
| | | /** |
| | | * 停止位置监听 |
| | | */ |
| | | export const stopLocationWatcher = () => { |
| | | if (locationWatcherId) { |
| | | uni.stopLocationUpdate({ |
| | | success: () => { |
| | | console.log('停止位置监听成功'); |
| | | }, |
| | | fail: (err) => { |
| | | console.error('停止位置监听失败:', err); |
| | | } |
| | | }); |
| | | locationWatcherId = null; |
| | | } |
| | | |
| | | // 移除位置更新监听 |
| | | uni.offLocationChange(); |
| | | locationUpdateCallback = null; |
| | | }; |
| | | |
| | | /** |
| | | * 检查系统定位服务是否开启 |
| | | * @returns {Promise<boolean>} 是否开启 |
| | | */ |
| | | export const checkSystemLocationEnabled = async () => { |
| | | return new Promise((resolve) => { |
| | | // #ifdef APP-PLUS |
| | | const enabled = permission.checkSystemEnableLocation(); |
| | | resolve(enabled); |
| | | // #endif |
| | | // #ifdef H5 |
| | | resolve(navigator.geolocation ? true : false); |
| | | // #endif |
| | | // #ifdef MP |
| | | uni.getSystemInfo({ |
| | | success: (res) => { |
| | | // 小程序无法直接检查系统定位服务是否开启 |
| | | resolve(true); |
| | | }, |
| | | fail: () => { |
| | | resolve(false); |
| | | } |
| | | }); |
| | | // #endif |
| | | }); |
| | | }; |
| | | |
| | | export default { |
| | | requestLocationPermission, |
| | | getCurrentLocation, |
| | | startLocationWatcher, |
| | | stopLocationWatcher, |
| | | checkSystemLocationEnabled |
| | | }; |
| | |
| | | // WebSocket服务管理 |
| | | import { useGlobalWS } from "@/hooks/useGlobalWS.js";// WebSocket服务管理 |
| | | class WebSocketService { |
| | | constructor() { |
| | | this.socketTask = null |
| | |
| | | this.socketTask = uni.connectSocket({ |
| | | url: this.url, |
| | | success: () => { |
| | | console.log('WebSocket连接已请求') |
| | | // console.log('WebSocket连接已请求') |
| | | }, |
| | | fail: (error) => { |
| | | console.error('WebSocket连接请求失败:', error) |
| | | // console.error('WebSocket连接请求失败:', error) |
| | | if (this.onErrorCallback) { |
| | | this.onErrorCallback(error) |
| | | } |
| | |
| | | // 监听连接打开 |
| | | this.socketTask.onOpen(() => { |
| | | this.connected = true |
| | | console.log('WebSocket已连接,userId:', this.userId) |
| | | // console.log('WebSocket已连接,userId:', this.userId) |
| | | this.startPing() |
| | | if (this.onOpenCallback) { |
| | | this.onOpenCallback() |
| | |
| | | // 监听连接关闭 |
| | | this.socketTask.onClose(() => { |
| | | this.connected = false |
| | | console.log('WebSocket已关闭') |
| | | // console.log('WebSocket已关闭') |
| | | this.stopPing() |
| | | if (this.onCloseCallback) { |
| | | this.onCloseCallback() |
| | |
| | | |
| | | // 监听连接错误 |
| | | this.socketTask.onError((error) => { |
| | | console.error('WebSocket错误:', error) |
| | | // console.error('WebSocket错误:', error) |
| | | this.connected = false |
| | | this.stopPing() |
| | | if (this.onErrorCallback) { |
| | |
| | | this.socketTask.onMessage((res) => { |
| | | try { |
| | | const message = JSON.parse(res.data) |
| | | console.log('收到WebSocket消息:', message) |
| | | // console.log('收到WebSocket消息:', message) |
| | | if (this.onMessageCallback) { |
| | | this.onMessageCallback(message) |
| | | } |
| | | } catch (error) { |
| | | console.error('解析WebSocket消息失败:', error) |
| | | // console.error('解析WebSocket消息失败:', error) |
| | | } |
| | | }) |
| | | } catch (error) { |
| | | console.error('WebSocket连接失败:', error) |
| | | // console.error('WebSocket连接失败:', error) |
| | | if (this.onErrorCallback) { |
| | | this.onErrorCallback(error) |
| | | } |
| | |
| | | this.socketTask.send({ |
| | | data: JSON.stringify(message), |
| | | success: () => { |
| | | console.log('WebSocket消息发送成功:', message) |
| | | // console.log('WebSocket消息发送成功:', message) |
| | | useGlobalWS(); |
| | | }, |
| | | fail: (error) => { |
| | | console.error('WebSocket消息发送失败:', error) |
| | | // console.error('WebSocket消息发送失败:', error) |
| | | } |
| | | }) |
| | | } |
| | |
| | | code: 1000, |
| | | reason: '正常关闭', |
| | | success: () => { |
| | | console.log('WebSocket已关闭') |
| | | // console.log('WebSocket已关闭') |
| | | }, |
| | | fail: (error) => { |
| | | console.error('WebSocket关闭失败:', error) |
| | | // console.error('WebSocket关闭失败:', error) |
| | | } |
| | | }) |
| | | this.socketTask = null |
| | |
| | | |
| | | // 设置消息回调 |
| | | setOnMessageCallback(callback) { |
| | | console.log('🔔 WebSocket消息回调已设置') |
| | | this.onMessageCallback = callback |
| | | } |
| | | |
| | | |
| | | // 获取当前消息回调(用于检查是否已设置) |
| | | getOnMessageCallback() { |
| | | return this.onMessageCallback |
| | |
| | | <view class="detailBox"> |
| | | <div class="detailCon"> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">姓名</div> |
| | | <div class="rowTitle">昵称</div> |
| | | <div>{{userInfo.nickName}}</div> |
| | | </div> |
| | | <!-- <div class="orderRow"> |
| | | <div class="rowTitle">所属单位</div> |
| | | <div>{{userInfo.deptName}}</div> |
| | | </div> --> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">认证状态</div> |
| | | <div>{{userInfo.status === 1 ? '已认证' : '未认证'}}</div> |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">性别</div> |
| | | <div> |
| | | <u-radio-group v-model="userInfo.sex"> |
| | | <up-radio |
| | | v-for="(item, index) in sexList" |
| | | :key="index" |
| | | :label="item.label" |
| | | :name="item.name" |
| | | @change="radioChange" |
| | | > |
| | | </up-radio> |
| | | </u-radio-group> |
| | | </div> |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">手机号</div> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { uploadFileApi } from '@/api/index' |
| | | import showDefaultHeader from "@/static/images/user/default-header.png"; |
| | | import { |
| | | getEnvObj, |
| | |
| | | phone: '', |
| | | email: '', |
| | | deptName: '', |
| | | sex: 2, |
| | | }); |
| | | const sexList = [ |
| | | { |
| | | label: '男', |
| | | name: '0' |
| | | }, |
| | | { |
| | | label: '女', |
| | | name: '1' |
| | | }, |
| | | { |
| | | label: '未知', |
| | | name: '2' |
| | | } |
| | | ] |
| | | // 校验手机号 |
| | | const validatePhone = () => { |
| | | const phone = userInfo.value.phone |
| | |
| | | const getUserInfoData = () => { |
| | | getUserInfo().then(res => { |
| | | const user = res.data.data; |
| | | console.log('user',user) |
| | | userInfo.value = { |
| | | id: user.userId, |
| | | avatar: user.avatar, |
| | | nickName: user.nickName, |
| | | // realName: user.realName, |
| | | phone: user.phonenumber, |
| | | email: user.sysDept.email, |
| | | deptName: user.sysDept.deptName, |
| | | sex: user.sex || 2, |
| | | }; |
| | | |
| | | }); |
| | |
| | | const reset = () => { |
| | | getUserInfoData(); |
| | | }; |
| | | |
| | | const { |
| | | VITE_API_BASE_URL |
| | | } = getEnvObj() |
| | | |
| | | function uploadUtil(options) { |
| | | const { |
| | | formData, |
| | | filePath, |
| | | url |
| | | } = options; |
| | | |
| | | return new Promise((resolve, reject) => { |
| | | let accessToken = useUserStore()?.$state?.userInfo?.access_token; |
| | | |
| | | uni.uploadFile({ |
| | | url: `${VITE_API_BASE_URL}${url}`, |
| | | name: 'file', |
| | | header: { |
| | | 'Blade-Auth': 'bearer ' + accessToken |
| | | }, |
| | | filePath: filePath, |
| | | formData, |
| | | success: (res) => { |
| | | const resData = JSON.parse(res.data) |
| | | if (resData.code === 200 || resData.code === 0) { |
| | | resolve(res) |
| | | } else { |
| | | showToast(resData.message) |
| | | |
| | | reject(res) |
| | | } |
| | | }, |
| | | fail: (err) => { |
| | | reject(err) |
| | | } |
| | | }); |
| | | }) |
| | | } |
| | | // 提交文件 |
| | | function afterReadFile(event) { |
| | | console.log('上传的文件:', event); |
| | | |
| | | // 准备上传参数 |
| | | const uploadParams = { |
| | | name: event.name, // 服务器端接收文件的字段名 |
| | | file: event.file, // 传入文件对象 |
| | | filePath: event.filePath, // 文件路径 |
| | | }; |
| | | |
| | | // 调用上传文件接口 |
| | | uploadFileApi(uploadParams).then(res => { |
| | | uni.hideLoading(); |
| | | |
| | | console.log('上传成功结果:', res); |
| | | |
| | | // 根据接口返回的数据结构处理结果 |
| | | if (res.data && res.data.code === 200) { |
| | | const uploadResult = res.data.data; |
| | | userInfo.value.avatar = uploadResult.fileUrl || '文件上传成功'; |
| | | |
| | | uni.showToast({ |
| | | title: '上传成功', |
| | | icon: 'success' |
| | | }); |
| | | } else { |
| | | uni.showToast({ |
| | | title: res.msg || '上传失败', |
| | | icon: 'none' |
| | | }); |
| | | } |
| | | }).catch(err => { |
| | | uni.hideLoading(); |
| | | console.error('上传失败:', err); |
| | | uni.showToast({ |
| | | title: '上传失败', |
| | | icon: 'none' |
| | | }); |
| | | }); |
| | | } |
| | | const uploadAvatar = () => { |
| | | uni.chooseImage({ |
| | | count: 1, |
| | |
| | | title: '上传中...' |
| | | }); |
| | | |
| | | // 上传文件 |
| | | uploadUtil({ |
| | | filePath: filePath, |
| | | formData: { |
| | | fileName: fileName, |
| | | sn: 'avatar_upload' |
| | | }, |
| | | url: '/blade-resource/oss/endpoint/put-file' |
| | | }).then(res => { |
| | | const resData = JSON.parse(res.data); |
| | | if (resData.code === 200 || resData.code === 0) { |
| | | // 更新头像显示 |
| | | userInfo.value.avatar = resData.data.link || resData.data.url; |
| | | uni.hideLoading(); |
| | | uni.showToast({ |
| | | title: '头像上传成功', |
| | | icon: 'success' |
| | | }); |
| | | } else { |
| | | throw new Error(resData.message || '上传失败'); |
| | | |
| | | } |
| | | }).catch(err => { |
| | | uni.hideLoading(); |
| | | uni.showToast({ |
| | | title: err.message || '上传失败', |
| | | icon: 'none' |
| | | }); |
| | | }); |
| | | afterReadFile({ |
| | | file: tempFile, |
| | | filePath: filePath, |
| | | name: fileName, |
| | | }) |
| | | } |
| | | }); |
| | | } |
| | |
| | | } |
| | | .note { |
| | | position: absolute; |
| | | bottom: 400rpx; |
| | | bottom: 300rpx; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 400; |
| | | font-size: 10px; |