diff --git a/README.md b/README.md index add78b7b..48632c8a 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ If you want to write code with me, you can contact me for internal promotion. - [X] 区域管理:全国省市区的管理 - [X] 备份管理:系统数据库的备份管理 - [X] IP管理:系统用户的IP管理 - - [ ] 在线管理员:系统内在线的管理员 + - [X] 在线管理员:系统内在线的管理员 - [X] 开发配置:开发流程的相关配置 - [X] 菜单权限:整个系统内的菜单权限配置,支持拖拽排序 - [X] 数据字典:系统内常用且固定的数据的维护 diff --git a/src/api/dict/index.js b/src/api/dict/index.js index 2b4fb4b7..2bd1c874 100644 --- a/src/api/dict/index.js +++ b/src/api/dict/index.js @@ -148,10 +148,10 @@ export function subSetStatusApi(data) { * @param {*} data * @returns */ -export function subSelectListApi(params) { +export function subSelectListApi(data) { return service({ url: '/admin/dict/sub/select/list', - method: 'get', - params + method: 'post', + data }) } diff --git a/src/api/test/index.js b/src/api/test/index.js new file mode 100644 index 00000000..627b7873 --- /dev/null +++ b/src/api/test/index.js @@ -0,0 +1,90 @@ +/* + * @Description: 测试表 + * @Author: 拖孩 + * @Email: 1240235512@qq.com + * @Date: 2023-06-14 17:21:09 + */ +import service from '@/utils/request' +import { download } from '@/utils' + +/** + * @description: 分页列表 + * @param {*} + * @return {*} + */ +export function pageApi(params) { + return service({ + url: '/admin/test/page', + method: 'get', + params: params + }) +} + +/** + * @description: 信息 + * @param {*} + * @return {*} + */ +export function infoApi(params) { + return service({ + url: '/admin/test/info', + method: 'get', + params + }) +} + +/** + * @description: 新增 + * @param {*} + * @return {*} + */ +export function createApi(data) { + return service({ + url: '/admin/test/create', + method: 'post', + data + }) +} + +/** + * @description: 更新 + * @param {*} + * @return {*} + */ +export function updateApi(data) { + return service({ + url: '/admin/test/update', + method: 'post', + data + }) +} + +/** + * @description: 删除 + * @param {*} + * @return {*} + */ +export function deleteApi(data) { + return service({ + url: '/admin/test/delete', + method: 'post', + data + }) +} + +/** + * 导出 + * @returns + */ +export async function exportApi(params) { + const r = await service({ + url: '/admin/test/export', + method: 'get', + responseType: 'blob', + params + }) + if (r) { + const { blob, name } = r + download(blob, name) + } +} diff --git a/src/directive/drag-resize/index.js b/src/directive/drag-resize/index.js index a12a401f..54c88ae7 100644 --- a/src/directive/drag-resize/index.js +++ b/src/directive/drag-resize/index.js @@ -26,7 +26,17 @@ const defaultOptions = { upHandler: null } -const weakMap = new WeakMap() +// 初始化数据 +let data = { + el: null, + dom: null, + options: null, + + width: null, + downPageX: null, + height: null, + downPageY: null +} /** * 拖拽区域位置处理 @@ -70,60 +80,87 @@ const createElement = (options) => { return div } -const mouseListener = (el, div, options) => { - div.addEventListener('mousedown', (downEvent) => { - const { downHandler, moveHandler, upHandler } = options - if (typeof downHandler === 'function') { - downHandler(downEvent) +/** + * 鼠标移动监听事件 + * @param {*} event + * @returns + */ +const moveHandle = (event) => { + const { el, dom, options, width, downPageX, height, downPageY } = data + const { moveHandler, position, max, min } = options + // 事件回调 + if (typeof moveHandler === 'function') { + moveHandler(event) + } + // 设置鼠标样式 + document.documentElement.style.cursor = dom.style.cursor + // 水平方向处理 + if (horizontal.includes(position)) { + const value = position === horizontal[0] ? downPageX - event.pageX : event.pageX - downPageX + const size = width + value + if (size >= max) { + return + } + if (size <= min) { + return + } + el.style.width = size + 'px' + } + // 垂直方向处理 + if (vertical.includes(position)) { + const value = position === vertical[0] ? downPageY - event.pageY : event.pageY - downPageY + const size = height + value + if (size >= max) { + return + } + if (size <= min) { + return } - const moveController = new AbortController() - const upController = new AbortController() + el.style.height = size + 'px' + } +} +/** + * 鼠标松开监听事件 + * @param {*} event + */ +const upHandle = (event) => { + // 事件回调 + const { upHandler } = data.options + if (typeof upHandler === 'function') { + upHandler(event) + } + // 移除监听 + document.removeEventListener('mousemove', moveHandle) + document.removeEventListener('mouseup', upHandle) + // 移除鼠标样式 + document.documentElement.style.cursor = '' +} +/** + * 鼠标按下事件 + * @param {*} el 当前节点 + * @param {*} dom 可拖拽节点 + * @param {*} options 参数 + */ +const downListener = (el, dom, options) => { + dom.addEventListener('mousedown', (event) => { + // 事件回调 + const { downHandler } = options + if (typeof downHandler === 'function') { + downHandler(event) + } + // 获取水平参数 const width = el.offsetWidth - const downPageX = downEvent.pageX - + const downPageX = event.pageX + // 获取垂直参数 const height = el.offsetHeight - const downPageY = downEvent.pageY - - weakMap.set(el, { div, moveController, upController }) - - document.addEventListener('mousemove', (moveEvent) => { - if (typeof moveHandler === 'function') { - moveHandler(moveHandler) - } - document.documentElement.style.cursor = div.style.cursor - if (horizontal.includes(options.position)) { - const value = moveEvent.pageX - downPageX - const size = width + value - if (size >= options.max) { - return - } - if (size <= options.min) { - return - } - el.style.width = size + 'px' - } - if (vertical.includes(options.position)) { - const value = moveEvent.pageY - downPageY - const size = width + value - if (size >= options.max) { - return - } - if (size <= options.min) { - return - } - el.style.height = size + value + 'px' - } - }, { signal: moveController.signal }) - - document.addEventListener('mouseup', () => { - if (typeof upHandler === 'function') { - upHandler(moveHandler) - } - moveController.abort() - upController.abort() - document.documentElement.style.cursor = '' - }, { signal: upController.signal }) + const downPageY = event.pageY + // 设置数据 + data = { el, dom, options, width, downPageX, height, downPageY } + // 添加鼠标移动事件 + document.addEventListener('mousemove', moveHandle) + // 添加鼠标松开事件 + document.addEventListener('mouseup', upHandle) }) } @@ -142,20 +179,17 @@ export default { return } - const div = createElement(options) + const dom = createElement(options) - mouseListener(el, div, options) + downListener(el, dom, options) - el.appendChild(div) + el.appendChild(dom) }, - unmounted(el) { - const data = weakMap.get(el) - if (data) { - const { moveController, upController } = data - moveController.abort() - upController.abort() - document.documentElement.style.cursor = '' - } + unmounted() { + // 移除监听 + document.removeEventListener('mousemove', moveHandle) + document.removeEventListener('mouseup', upHandle) + // 移除鼠标样式 + document.documentElement.style.cursor = '' } } - diff --git a/src/hooks/dict.js b/src/hooks/dict.js index e62428c6..52ac31f1 100644 --- a/src/hooks/dict.js +++ b/src/hooks/dict.js @@ -1,3 +1,8 @@ +import { delay } from '@/utils' + +// 页面多次复用组件第一次会重复请求处理 +const pending = {} + export default function () { const dictStore = useDictStore() @@ -5,14 +10,25 @@ export default function () { const dicts = ref({}) const getDict = async (code) => { + while (pending[code] === 1) { + await delay() + } + + pending[code] = 1 const result = await dictStore.getDict(code) dict.value = result + pending[code] = 0 return result } const getDicts = async (...codes) => { + while (codes.some(code => pending[code] === 1)) { + await delay() + } + codes.forEach(code => { pending[code] = 1 }) const result = await dictStore.getDicts(...codes) dicts.value = result + codes.forEach(code => { pending[code] = 0 }) return result } diff --git a/src/router/index.js b/src/router/index.js index 821533da..b2dd48b1 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -25,7 +25,7 @@ const main = { name: 'layout', redirect: { name: 'redirect' }, component: () => import('@/views/layout/index.vue'), - meta: { title: '主入口整体布局' }, + meta: { title: '' }, children: [ // todo 动态路由未注册之前 直接跳转会报错 所以使用了个中间件 { path: '/redirect', name: 'redirect', component: defineComponent({ render: () => h('div') }), meta: {} } diff --git a/src/stores/modules/dict.js b/src/stores/modules/dict.js index df68a483..72a9e73a 100644 --- a/src/stores/modules/dict.js +++ b/src/stores/modules/dict.js @@ -1,6 +1,26 @@ -import axios from 'axios' import { subSelectListApi } from '@/api/dict' -import { SUCCESS_CODE } from '../../utils/constant' + +/** + * 处理数据 + * @param {*} data + * @returns + */ +const dictHandle = (data) => { + const result = {} + for (const key in data) { + if (Object.hasOwnProperty.call(data, key)) { + const dict = data[key] + const list = dict.map(item => { + return { + value: /^[0-9]+.?[0-9]*$/.test(item.code) ? +item.code : item.code, // 判断是否是数字 如果是数字则用数字 + label: item.name + } + }) + result[key] = list + } + } + return result +} export const useDictStore = defineStore('dict', { state: () => ({ @@ -11,23 +31,18 @@ export const useDictStore = defineStore('dict', { if (dict && JSON.stringify(dict) !== '{}') { return dict } else { - const r = await subSelectListApi({ code }) + const r = await subSelectListApi([code]) if (r) { - const list = r.data.map(item => { - return { - value: /^[0-9]+.?[0-9]*$/.test(item.code) ? +item.code : item.code, // 判断是否是数字 如果是数字则用数字 - label: item.name - } - }) - this.$state[code] = list - return list + const data = dictHandle(r.data) + this.$state[code] = data[code] + return data[code] } else { - return {} + return [] } } }, async getDicts(...codes) { - const result = {} + let result = {} const codeList = [] codes.forEach(code => { @@ -38,28 +53,14 @@ export const useDictStore = defineStore('dict', { codeList.push(code) } }) - - const requests = [] - codeList.forEach(code => { - requests.push(subSelectListApi({ code })) - }) - if (requests.length) { - const responses = await axios.all(requests) - responses.forEach((r, index) => { - if (r && SUCCESS_CODE.includes(r.code)) { - const list = r.data.map(item => { - return { - value: /^[0-9]+.?[0-9]*$/.test(item.code) ? +item.code : item.code, // 判断是否是数字 如果是数字则用数字 - label: item.name - } - }) - const code = codeList[index] - this.$state[code] = list - result[code] = list - } - }) + if (codeList.length) { + const r = await subSelectListApi(codeList) + if (r) { + const data = dictHandle(r.data) + this.$state = { ...this.$state, ...data } + result = { ...result, ...data } + } } - return result } } diff --git a/src/utils/index.js b/src/utils/index.js index 269bae5a..114b7569 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -332,3 +332,12 @@ export function blob2Json(blob) { } }) } + +/** + * 休眠函数 + * @param {Number} ms 间隔时长 + * @returns + */ +export function delay(ms = 200) { + return new Promise((resolve) => setTimeout(resolve, ms)) +} diff --git a/src/views/modules/system/adminer/index.vue b/src/views/modules/system/adminer/index.vue index 4f90e019..61db37c6 100644 --- a/src/views/modules/system/adminer/index.vue +++ b/src/views/modules/system/adminer/index.vue @@ -8,7 +8,6 @@ import { clearJson, havePermission } from '@/utils' import { Status } from '@/utils/enum' import { pageApi, deleteApi, setStatusApi, resetPasswordApi, exportApi } from '@/api/adminer' -import { h } from 'vue' const refContainerSidebar = ref() const refForm = ref() @@ -266,9 +265,14 @@ onBeforeMount(() => { + diff --git a/src/views/modules/system/dept/components/set-data-permission.vue b/src/views/modules/system/dept/components/set-data-permission.vue index 00c10e71..4c957204 100644 --- a/src/views/modules/system/dept/components/set-data-permission.vue +++ b/src/views/modules/system/dept/components/set-data-permission.vue @@ -130,7 +130,7 @@ defineExpose({ diff --git a/src/views/modules/system/dept/index.vue b/src/views/modules/system/dept/index.vue index fb47b2be..5ffaba3d 100644 --- a/src/views/modules/system/dept/index.vue +++ b/src/views/modules/system/dept/index.vue @@ -232,7 +232,7 @@ onBeforeMount(() => { prop="dataScope" width="120"> diff --git a/src/views/modules/system/role/index.vue b/src/views/modules/system/role/index.vue index a990c81a..25b6cb37 100644 --- a/src/views/modules/system/role/index.vue +++ b/src/views/modules/system/role/index.vue @@ -276,7 +276,7 @@ onBeforeMount(() => { prop="dataScope" width="120"> + + + diff --git a/src/views/modules/test/index.vue b/src/views/modules/test/index.vue new file mode 100644 index 00000000..5e59e680 --- /dev/null +++ b/src/views/modules/test/index.vue @@ -0,0 +1,226 @@ + + +