Commit f3e1fc4f9b9fb13db52ba8ebd4458ab17356ae67
Committed by
芋道源码
1 parent
35413b52
!238 新增 todo done 页面,优化redis页面
* chore: update deps * feat: add todo done pages * chore: update deps * docs: update * feat: redis dialog
Showing
12 changed files
with
466 additions
and
68 deletions
README.md
| ... | ... | @@ -193,7 +193,7 @@ ps:核心功能已经实现,正在对接微信小程序中... |
| 193 | 193 | |----------------------------------------------------------------------|------------------|--------| |
| 194 | 194 | | [Vue](https://staging-cn.vuejs.org/) | Vue 框架 | 3.2.37 | |
| 195 | 195 | | [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 3.0.3 | |
| 196 | -| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.2.9 | | |
| 196 | +| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.2.11 | | |
| 197 | 197 | | [TypeScript](https://www.typescriptlang.org/docs/) | TypeScript | 4.7.4 | |
| 198 | 198 | | [pinia](https://pinia.vuejs.org/) | Vue 存储库 替代 vuex5 | 2.0.17 | |
| 199 | 199 | | [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化 | 9.1.10 | | ... | ... |
yudao-ui-admin-vue3/README.md
| 1 | 1 | <h1>🌈 yudao-ui-admin-vue3</h1> |
| 2 | - | |
| 2 | +<p align="center"> | |
| 3 | + <img src="https://img.shields.io/badge/-Vue3.2-34495e?logo=vue.j" /> | |
| 4 | + <img src="https://img.shields.io/badge/-Vite3-646cff?logo=vite&logoColor=white" /> | |
| 5 | + <img src="https://img.shields.io/badge/-TypeScript4.7-blue?logo=typescript&logoColor=white" /> | |
| 6 | + <img src="https://img.shields.io/badge/-Pinia2-yellow?logo=picpay&logoColor=white" /> | |
| 7 | + <img src="https://img.shields.io/badge/-ESLint-4b32c3?logo=eslint&logoColor=white" /> | |
| 8 | + <img src="https://img.shields.io/badge/-pnpm7-F69220?logo=pnpm&logoColor=white" /> | |
| 9 | + <img src="https://img.shields.io/badge/-Axios-008fc7?logo=axios.js&logoColor=white" /> | |
| 10 | + <img src="https://img.shields.io/badge/-Prettier-ef9421?logo=Prettier&logoColor=white" alt="Prettier"> | |
| 11 | + <img src="https://img.shields.io/badge/-Less-1D365D?logo=less&logoColor=white" alt="Less"> | |
| 12 | + <img src="https://img.shields.io/badge/-Wind%20CSS-06B6D4?logo=Tailwind%20CSS&logoColor=white" alt="Taiwind"> | |
| 13 | + <img src="" alt=""> | |
| 14 | +</p> | |
| 3 | 15 | ## 介绍 |
| 4 | 16 | |
| 5 | 17 | - 基于 vue3.2+ ,TypeScript ,Element Plus 2.2.0+ ,Vite3 ,Pinia ,Windicss 等开发的后台管理系统 |
| ... | ... | @@ -12,19 +24,19 @@ |
| 12 | 24 | |
| 13 | 25 | ### 前端依赖 |
| 14 | 26 | |
| 15 | -| 框架 | 说明 | 版本 | | |
| 16 | -| --- | --- | --- | | |
| 27 | +| 框架 | 说明 | 版本 | | |
| 28 | +| --- | --- |--------| | |
| 17 | 29 | | [Vue](https://staging-cn.vuejs.org/) | vue 框架 | 3.2.37 | |
| 18 | -| [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 3.0.2 | | |
| 19 | -| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.2.9 | | |
| 20 | -| [TypeScript](https://www.typescriptlang.org/docs/) | JavaScript 的超集 | 4.7.4 | | |
| 21 | -| [pinia](https://pinia.vuejs.org/) | Vue 存储库 替代 vuex5 | 2.0.16 | | |
| 22 | -| [vueuse](https://vueuse.org//) | 常用工具集 | 8.9.4 | | |
| 30 | +| [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 3.0.3 | | |
| 31 | +| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.2.11 | | |
| 32 | +| [TypeScript](https://www.typescriptlang.org/docs/) | JavaScript 的超集 | 4.7.4 | | |
| 33 | +| [pinia](https://pinia.vuejs.org/) | Vue 存储库 替代 vuex5 | 2.0.17 | | |
| 34 | +| [vueuse](https://vueuse.org//) | 常用工具集 | 9.0.0 | | |
| 23 | 35 | | [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化 | 9.1.10 | |
| 24 | -| [vue-router](https://router.vuejs.org/) | vue 路由 | 4.1.2 | | |
| 25 | -| [windicss](https://cn.windicss.org/) | 下一代工具优先的 CSS 框架 | 3.5.6 | | |
| 26 | -| [iconify](https://icon-sets.iconify.design/) | 在线图标库 | 2.2.1 | | |
| 27 | -| [wangeditor](https://www.wangeditor.com/) | 富文本编辑器 | 5.1.10 | | |
| 36 | +| [vue-router](https://router.vuejs.org/) | vue 路由 | 4.1.3 | | |
| 37 | +| [windicss](https://cn.windicss.org/) | 下一代工具优先的 CSS 框架 | 3.5.6 | | |
| 38 | +| [iconify](https://icon-sets.iconify.design/) | 在线图标库 | 2.2.1 | | |
| 39 | +| [wangeditor](https://www.wangeditor.com/) | 富文本编辑器 | 5.1.14 | | |
| 28 | 40 | |
| 29 | 41 | ### 推荐 VScode 开发,插件如下 |
| 30 | 42 | ... | ... |
yudao-ui-admin-vue3/package.json
| ... | ... | @@ -56,12 +56,12 @@ |
| 56 | 56 | "devDependencies": { |
| 57 | 57 | "@commitlint/cli": "^17.0.3", |
| 58 | 58 | "@commitlint/config-conventional": "^17.0.3", |
| 59 | - "@iconify/json": "^2.1.84", | |
| 59 | + "@iconify/json": "^2.1.85", | |
| 60 | 60 | "@intlify/vite-plugin-vue-i18n": "^5.0.1", |
| 61 | 61 | "@purge-icons/generated": "^0.8.1", |
| 62 | 62 | "@types/intro.js": "^5.1.0", |
| 63 | 63 | "@types/lodash-es": "^4.17.6", |
| 64 | - "@types/node": "^18.6.1", | |
| 64 | + "@types/node": "^18.6.2", | |
| 65 | 65 | "@types/nprogress": "^0.2.0", |
| 66 | 66 | "@types/qrcode": "^1.4.2", |
| 67 | 67 | "@types/qs": "^6.9.7", |
| ... | ... | @@ -101,8 +101,7 @@ |
| 101 | 101 | "vite-plugin-svg-icons": "^2.0.1", |
| 102 | 102 | "vite-plugin-windicss": "^1.8.7", |
| 103 | 103 | "vue-tsc": "^0.39.2", |
| 104 | - "windicss": "^3.5.6", | |
| 105 | - "windicss-analysis": "^0.3.5" | |
| 104 | + "windicss": "^3.5.6" | |
| 106 | 105 | }, |
| 107 | 106 | "engines": { |
| 108 | 107 | "node": ">= 14.18.0" | ... | ... |
yudao-ui-admin-vue3/src/api/bpm/task/types.ts
| ... | ... | @@ -7,3 +7,33 @@ export type FormVO = { |
| 7 | 7 | remark: string |
| 8 | 8 | createTime: string |
| 9 | 9 | } |
| 10 | + | |
| 11 | +export type TaskProcessVO = { | |
| 12 | + id: string | |
| 13 | + name: string | |
| 14 | + startUserId: number | |
| 15 | + startUserNickname: string | |
| 16 | + processDefinitionId: string | |
| 17 | +} | |
| 18 | + | |
| 19 | +export type TaskTodoVO = { | |
| 20 | + id: string | |
| 21 | + name: string | |
| 22 | + claimTime: string | |
| 23 | + createTime: string | |
| 24 | + suspensionState: number | |
| 25 | + processInstance: TaskProcessVO | |
| 26 | +} | |
| 27 | + | |
| 28 | +export type TaskDoneVO = { | |
| 29 | + id: string | |
| 30 | + name: string | |
| 31 | + claimTime: string | |
| 32 | + createTime: string | |
| 33 | + endTime: string | |
| 34 | + durationInMillis: number | |
| 35 | + suspensionState: number | |
| 36 | + result: number | |
| 37 | + reason: string | |
| 38 | + processInstance: TaskProcessVO | |
| 39 | +} | ... | ... |
yudao-ui-admin-vue3/src/api/infra/redis/index.ts
| ... | ... | @@ -24,16 +24,16 @@ export const getKeyListApi = (keyTemplate: string) => { |
| 24 | 24 | }) |
| 25 | 25 | } |
| 26 | 26 | // 获取缓存内容 |
| 27 | -export const getKeyValue = (key: string) => { | |
| 27 | +export const getKeyValueApi = (key: string) => { | |
| 28 | 28 | return request.get({ url: '/infra/redis/get-key-value?key=' + key }) |
| 29 | 29 | } |
| 30 | 30 | |
| 31 | 31 | // 根据键名删除缓存 |
| 32 | -export const deleteKey = (key: string) => { | |
| 32 | +export const deleteKeyApi = (key: string) => { | |
| 33 | 33 | return request.delete({ url: '/infra/redis/delete-key?key=' + key }) |
| 34 | 34 | } |
| 35 | 35 | |
| 36 | -export const deleteKeys = (keyTemplate: string) => { | |
| 36 | +export const deleteKeysApi = (keyTemplate: string) => { | |
| 37 | 37 | return request.delete({ |
| 38 | 38 | url: '/infra/redis/delete-keys?', |
| 39 | 39 | params: { | ... | ... |
yudao-ui-admin-vue3/src/views/bpm/task/done/done.data.ts
0 → 100644
| 1 | +import { reactive } from 'vue' | |
| 2 | +import { useI18n } from '@/hooks/web/useI18n' | |
| 3 | +import { CrudSchema, useCrudSchemas } from '@/hooks/web/useCrudSchemas' | |
| 4 | +import { DICT_TYPE } from '@/utils/dict' | |
| 5 | +const { t } = useI18n() // 国际化 | |
| 6 | + | |
| 7 | +// CrudSchema | |
| 8 | +const crudSchemas = reactive<CrudSchema[]>([ | |
| 9 | + { | |
| 10 | + label: t('common.index'), | |
| 11 | + field: 'id', | |
| 12 | + type: 'index' | |
| 13 | + }, | |
| 14 | + { | |
| 15 | + label: '任务名称', | |
| 16 | + field: 'name', | |
| 17 | + search: { | |
| 18 | + show: true | |
| 19 | + } | |
| 20 | + }, | |
| 21 | + { | |
| 22 | + label: '所属流程', | |
| 23 | + field: 'processInstance.name' | |
| 24 | + }, | |
| 25 | + { | |
| 26 | + label: '流程发起人', | |
| 27 | + field: 'processInstance.startUserNickname' | |
| 28 | + }, | |
| 29 | + { | |
| 30 | + label: '结果', | |
| 31 | + field: 'result', | |
| 32 | + dictType: DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT | |
| 33 | + }, | |
| 34 | + { | |
| 35 | + label: '审批意见', | |
| 36 | + field: 'reason' | |
| 37 | + }, | |
| 38 | + { | |
| 39 | + label: t('common.createTime'), | |
| 40 | + field: 'createTime', | |
| 41 | + search: { | |
| 42 | + show: true, | |
| 43 | + component: 'DatePicker', | |
| 44 | + componentProps: { | |
| 45 | + type: 'datetimerange', | |
| 46 | + valueFormat: 'YYYY-MM-DD HH:mm:ss', | |
| 47 | + defaultTime: [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)], | |
| 48 | + shortcuts: [ | |
| 49 | + { | |
| 50 | + text: '近一周', | |
| 51 | + value: () => { | |
| 52 | + const end = new Date() | |
| 53 | + const start = new Date() | |
| 54 | + start.setTime(start.getTime() - 3600 * 1000 * 24 * 7) | |
| 55 | + return [start, end] | |
| 56 | + } | |
| 57 | + }, | |
| 58 | + { | |
| 59 | + text: '近一个月', | |
| 60 | + value: () => { | |
| 61 | + const end = new Date() | |
| 62 | + const start = new Date() | |
| 63 | + start.setTime(start.getTime() - 3600 * 1000 * 24 * 30) | |
| 64 | + return [start, end] | |
| 65 | + } | |
| 66 | + }, | |
| 67 | + { | |
| 68 | + text: '近三个月', | |
| 69 | + value: () => { | |
| 70 | + const end = new Date() | |
| 71 | + const start = new Date() | |
| 72 | + start.setTime(start.getTime() - 3600 * 1000 * 24 * 90) | |
| 73 | + return [start, end] | |
| 74 | + } | |
| 75 | + } | |
| 76 | + ] | |
| 77 | + } | |
| 78 | + } | |
| 79 | + }, | |
| 80 | + { | |
| 81 | + label: '审批时间', | |
| 82 | + field: 'endTime' | |
| 83 | + }, | |
| 84 | + { | |
| 85 | + label: '耗时', | |
| 86 | + field: 'durationInMillis' | |
| 87 | + }, | |
| 88 | + { | |
| 89 | + label: t('table.action'), | |
| 90 | + field: 'action', | |
| 91 | + width: '100px' | |
| 92 | + } | |
| 93 | +]) | |
| 94 | +export const { allSchemas } = useCrudSchemas(crudSchemas) | ... | ... |
yudao-ui-admin-vue3/src/views/bpm/task/done/index.vue
| 1 | -<script setup lang="ts"></script> | |
| 1 | +<script setup lang="ts"> | |
| 2 | +import dayjs from 'dayjs' | |
| 3 | +import duration from 'dayjs/plugin/duration' | |
| 4 | +import { DICT_TYPE } from '@/utils/dict' | |
| 5 | +import { useTable } from '@/hooks/web/useTable' | |
| 6 | +import { useI18n } from '@/hooks/web/useI18n' | |
| 7 | +import type { TaskDoneVO } from '@/api/bpm/task/types' | |
| 8 | +import { allSchemas } from './done.data' | |
| 9 | +import * as TaskDoneApi from '@/api/bpm/task' | |
| 10 | +import { useRouter } from 'vue-router' | |
| 11 | +dayjs.extend(duration) | |
| 12 | +const { t } = useI18n() // 国际化 | |
| 13 | +const { push } = useRouter() | |
| 14 | +// ========== 列表相关 ========== | |
| 15 | +const { register, tableObject, methods } = useTable<TaskDoneVO>({ | |
| 16 | + getListApi: TaskDoneApi.getDoneTaskPage | |
| 17 | +}) | |
| 18 | +const { getList, setSearchParams } = methods | |
| 19 | + | |
| 20 | +// 审批操作 | |
| 21 | +const handleAudit = async (row: TaskDoneVO) => { | |
| 22 | + push('/bpm/process-instance/detail?id=' + row.processInstance.id) | |
| 23 | +} | |
| 24 | + | |
| 25 | +// ========== 初始化 ========== | |
| 26 | +getList() | |
| 27 | +</script> | |
| 2 | 28 | |
| 3 | 29 | <template> |
| 4 | - <div>index</div> | |
| 30 | + <!-- 搜索工作区 --> | |
| 31 | + <ContentWrap> | |
| 32 | + <Search :schema="allSchemas.searchSchema" @search="setSearchParams" @reset="setSearchParams" /> | |
| 33 | + </ContentWrap> | |
| 34 | + <ContentWrap> | |
| 35 | + <!-- 列表 --> | |
| 36 | + <Table | |
| 37 | + :columns="allSchemas.tableColumns" | |
| 38 | + :selection="false" | |
| 39 | + :data="tableObject.tableList" | |
| 40 | + :loading="tableObject.loading" | |
| 41 | + :pagination="{ | |
| 42 | + total: tableObject.total | |
| 43 | + }" | |
| 44 | + v-model:pageSize="tableObject.pageSize" | |
| 45 | + v-model:currentPage="tableObject.currentPage" | |
| 46 | + @register="register" | |
| 47 | + > | |
| 48 | + <template #status="{ row }"> | |
| 49 | + <DictTag :type="DICT_TYPE.COMMON_STATUS" :value="row.status" /> | |
| 50 | + </template> | |
| 51 | + <template #createTime="{ row }"> | |
| 52 | + <span>{{ dayjs(row.createTime).format('YYYY-MM-DD HH:mm:ss') }}</span> | |
| 53 | + </template> | |
| 54 | + <template #endTime="{ row }"> | |
| 55 | + <span>{{ dayjs(row.endTime).format('YYYY-MM-DD HH:mm:ss') }}</span> | |
| 56 | + </template> | |
| 57 | + <template #durationInMillis="{ row }"> | |
| 58 | + <span>{{ dayjs.duration(row.durationInMillis).asMilliseconds() }}</span> | |
| 59 | + </template> | |
| 60 | + <template #action="{ row }"> | |
| 61 | + <el-button link type="primary" v-hasPermi="['bpm:task:query']" @click="handleAudit(row)"> | |
| 62 | + <Icon icon="ep:view" class="mr-1px" /> {{ t('action.detail') }} | |
| 63 | + </el-button> | |
| 64 | + </template> | |
| 65 | + </Table> | |
| 66 | + </ContentWrap> | |
| 5 | 67 | </template> |
| 6 | - | |
| 7 | -<style scoped></style> | ... | ... |
yudao-ui-admin-vue3/src/views/bpm/task/todo/done.data.ts
0 → 100644
| 1 | +import { reactive } from 'vue' | |
| 2 | +import { useI18n } from '@/hooks/web/useI18n' | |
| 3 | +import { CrudSchema, useCrudSchemas } from '@/hooks/web/useCrudSchemas' | |
| 4 | +const { t } = useI18n() // 国际化 | |
| 5 | + | |
| 6 | +// CrudSchema | |
| 7 | +const crudSchemas = reactive<CrudSchema[]>([ | |
| 8 | + { | |
| 9 | + label: t('common.index'), | |
| 10 | + field: 'id', | |
| 11 | + type: 'index' | |
| 12 | + }, | |
| 13 | + { | |
| 14 | + label: '任务名称', | |
| 15 | + field: 'name', | |
| 16 | + search: { | |
| 17 | + show: true | |
| 18 | + } | |
| 19 | + }, | |
| 20 | + { | |
| 21 | + label: '所属流程', | |
| 22 | + field: 'processInstance.name' | |
| 23 | + }, | |
| 24 | + { | |
| 25 | + label: '流程发起人', | |
| 26 | + field: 'processInstance.startUserNickname' | |
| 27 | + }, | |
| 28 | + { | |
| 29 | + label: t('common.createTime'), | |
| 30 | + field: 'createTime', | |
| 31 | + search: { | |
| 32 | + show: true, | |
| 33 | + component: 'DatePicker', | |
| 34 | + componentProps: { | |
| 35 | + type: 'datetimerange', | |
| 36 | + valueFormat: 'YYYY-MM-DD HH:mm:ss', | |
| 37 | + defaultTime: [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)], | |
| 38 | + shortcuts: [ | |
| 39 | + { | |
| 40 | + text: '近一周', | |
| 41 | + value: () => { | |
| 42 | + const end = new Date() | |
| 43 | + const start = new Date() | |
| 44 | + start.setTime(start.getTime() - 3600 * 1000 * 24 * 7) | |
| 45 | + return [start, end] | |
| 46 | + } | |
| 47 | + }, | |
| 48 | + { | |
| 49 | + text: '近一个月', | |
| 50 | + value: () => { | |
| 51 | + const end = new Date() | |
| 52 | + const start = new Date() | |
| 53 | + start.setTime(start.getTime() - 3600 * 1000 * 24 * 30) | |
| 54 | + return [start, end] | |
| 55 | + } | |
| 56 | + }, | |
| 57 | + { | |
| 58 | + text: '近三个月', | |
| 59 | + value: () => { | |
| 60 | + const end = new Date() | |
| 61 | + const start = new Date() | |
| 62 | + start.setTime(start.getTime() - 3600 * 1000 * 24 * 90) | |
| 63 | + return [start, end] | |
| 64 | + } | |
| 65 | + } | |
| 66 | + ] | |
| 67 | + } | |
| 68 | + } | |
| 69 | + }, | |
| 70 | + { | |
| 71 | + label: t('table.action'), | |
| 72 | + field: 'action', | |
| 73 | + width: '100px' | |
| 74 | + } | |
| 75 | +]) | |
| 76 | +export const { allSchemas } = useCrudSchemas(crudSchemas) | ... | ... |
yudao-ui-admin-vue3/src/views/bpm/task/todo/index.vue
| 1 | -<script setup lang="ts"></script> | |
| 1 | +<script setup lang="ts"> | |
| 2 | +import dayjs from 'dayjs' | |
| 3 | +import { DICT_TYPE } from '@/utils/dict' | |
| 4 | +import { useTable } from '@/hooks/web/useTable' | |
| 5 | +import type { TaskTodoVO } from '@/api/bpm/task/types' | |
| 6 | +import { allSchemas } from './done.data' | |
| 7 | +import * as TaskTodoApi from '@/api/bpm/task' | |
| 8 | +import { useRouter } from 'vue-router' | |
| 9 | +const { push } = useRouter() | |
| 10 | +// ========== 列表相关 ========== | |
| 11 | +const { register, tableObject, methods } = useTable<TaskTodoVO>({ | |
| 12 | + getListApi: TaskTodoApi.getTodoTaskPage | |
| 13 | +}) | |
| 14 | +const { getList, setSearchParams } = methods | |
| 15 | + | |
| 16 | +// 审批操作 | |
| 17 | +const handleAudit = async (row: TaskTodoVO) => { | |
| 18 | + push('/bpm/process-instance/detail?id=' + row.processInstance.id) | |
| 19 | +} | |
| 20 | + | |
| 21 | +// ========== 初始化 ========== | |
| 22 | +getList() | |
| 23 | +</script> | |
| 2 | 24 | |
| 3 | 25 | <template> |
| 4 | - <div>index</div> | |
| 26 | + <!-- 搜索工作区 --> | |
| 27 | + <ContentWrap> | |
| 28 | + <Search :schema="allSchemas.searchSchema" @search="setSearchParams" @reset="setSearchParams" /> | |
| 29 | + </ContentWrap> | |
| 30 | + <ContentWrap> | |
| 31 | + <!-- 列表 --> | |
| 32 | + <Table | |
| 33 | + :columns="allSchemas.tableColumns" | |
| 34 | + :selection="false" | |
| 35 | + :data="tableObject.tableList" | |
| 36 | + :loading="tableObject.loading" | |
| 37 | + :pagination="{ | |
| 38 | + total: tableObject.total | |
| 39 | + }" | |
| 40 | + v-model:pageSize="tableObject.pageSize" | |
| 41 | + v-model:currentPage="tableObject.currentPage" | |
| 42 | + @register="register" | |
| 43 | + > | |
| 44 | + <template #status="{ row }"> | |
| 45 | + <DictTag :type="DICT_TYPE.COMMON_STATUS" :value="row.status" /> | |
| 46 | + </template> | |
| 47 | + <template #createTime="{ row }"> | |
| 48 | + <span>{{ dayjs(row.createTime).format('YYYY-MM-DD HH:mm:ss') }}</span> | |
| 49 | + </template> | |
| 50 | + <template #action="{ row }"> | |
| 51 | + <el-button link type="primary" v-hasPermi="['bpm:task:update']" @click="handleAudit(row)"> | |
| 52 | + <Icon icon="ep:edit" class="mr-1px" /> 审批 | |
| 53 | + </el-button> | |
| 54 | + </template> | |
| 55 | + </Table> | |
| 56 | + </ContentWrap> | |
| 5 | 57 | </template> |
| 6 | - | |
| 7 | -<style scoped></style> | ... | ... |
yudao-ui-admin-vue3/src/views/infra/redis/index.vue
| ... | ... | @@ -13,7 +13,8 @@ import { |
| 13 | 13 | ElTableColumn, |
| 14 | 14 | ElScrollbar, |
| 15 | 15 | ElDescriptions, |
| 16 | - ElDescriptionsItem | |
| 16 | + ElDescriptionsItem, | |
| 17 | + ElMessage | |
| 17 | 18 | } from 'element-plus' |
| 18 | 19 | const cache = ref<RedisMonitorInfoVO>() |
| 19 | 20 | const keyListLoad = ref(true) |
| ... | ... | @@ -121,7 +122,33 @@ const loadEchartOptions = (stats) => { |
| 121 | 122 | ] |
| 122 | 123 | }) |
| 123 | 124 | } |
| 124 | - | |
| 125 | +const dialogVisible = ref(false) | |
| 126 | +const keyTemplate = ref('') | |
| 127 | +const cacheKeys = ref() | |
| 128 | +const cacheForm = ref<{ | |
| 129 | + key: string | |
| 130 | + value: string | |
| 131 | +}>({ | |
| 132 | + key: '', | |
| 133 | + value: '' | |
| 134 | +}) | |
| 135 | +const openKeyTemplate = async (row: RedisKeyInfo) => { | |
| 136 | + keyTemplate.value = row.keyTemplate | |
| 137 | + cacheKeys.value = await RedisApi.getKeyListApi(row.keyTemplate) | |
| 138 | + dialogVisible.value = true | |
| 139 | +} | |
| 140 | +const handleDeleteKey = async (row) => { | |
| 141 | + RedisApi.deleteKeyApi(row) | |
| 142 | + ElMessage.success('删除成功') | |
| 143 | +} | |
| 144 | +const handleDeleteKeys = async (row) => { | |
| 145 | + RedisApi.deleteKeysApi(row) | |
| 146 | + ElMessage.success('删除成功') | |
| 147 | +} | |
| 148 | +const handleKeyValue = async (row) => { | |
| 149 | + const res = await RedisApi.getKeyValueApi(row) | |
| 150 | + cacheForm.value = res | |
| 151 | +} | |
| 125 | 152 | onBeforeMount(() => { |
| 126 | 153 | readRedisInfo() |
| 127 | 154 | }) |
| ... | ... | @@ -186,7 +213,12 @@ onBeforeMount(() => { |
| 186 | 213 | <el-row style="margin-top: 10px"> |
| 187 | 214 | <el-col :span="24" class="card-box" shadow="hover"> |
| 188 | 215 | <el-card> |
| 189 | - <el-table v-loading="keyListLoad" :data="keyList" row-key="id"> | |
| 216 | + <el-table | |
| 217 | + v-loading="keyListLoad" | |
| 218 | + :data="keyList" | |
| 219 | + row-key="id" | |
| 220 | + @row-click="openKeyTemplate" | |
| 221 | + > | |
| 190 | 222 | <el-table-column prop="keyTemplate" label="Key 模板" width="200" /> |
| 191 | 223 | <el-table-column prop="keyType" label="Key 类型" width="100" /> |
| 192 | 224 | <el-table-column prop="valueType" label="Value 类型" /> |
| ... | ... | @@ -202,4 +234,58 @@ onBeforeMount(() => { |
| 202 | 234 | </el-col> |
| 203 | 235 | </el-row> |
| 204 | 236 | </el-scrollbar> |
| 237 | + <Dialog v-model="dialogVisible" :title="keyTemplate + ' 模板'" width="60%" maxHeight="800px"> | |
| 238 | + <el-row> | |
| 239 | + <el-col :span="14" style="margin-top: 10px"> | |
| 240 | + <el-card shadow="always"> | |
| 241 | + <template #header> | |
| 242 | + <div class="card-header"> | |
| 243 | + <span>键名列表</span> | |
| 244 | + </div> | |
| 245 | + </template> | |
| 246 | + <el-table :data="cacheKeys" style="width: 100%" @row-click="handleKeyValue"> | |
| 247 | + <el-table-column label="缓存键名" align="center" :show-overflow-tooltip="true"> | |
| 248 | + <template #default="{ row }"> | |
| 249 | + {{ row }} | |
| 250 | + </template> | |
| 251 | + </el-table-column> | |
| 252 | + <el-table-column label="操作" align="right" width="60"> | |
| 253 | + <template #default="{ row }"> | |
| 254 | + <el-button link type="primary" @click="handleDeleteKey(row)"> | |
| 255 | + <Icon icon="ep:delete" /> | |
| 256 | + </el-button> | |
| 257 | + </template> | |
| 258 | + </el-table-column> | |
| 259 | + </el-table> | |
| 260 | + </el-card> | |
| 261 | + </el-col> | |
| 262 | + <el-col :span="10" style="margin-top: 10px"> | |
| 263 | + <el-card shadow="always"> | |
| 264 | + <template #header> | |
| 265 | + <div class="card-header"> | |
| 266 | + <span>缓存内容</span> | |
| 267 | + <el-button | |
| 268 | + link | |
| 269 | + type="primary" | |
| 270 | + @click="handleDeleteKeys(keyTemplate)" | |
| 271 | + style="float: right; padding: 3px 0" | |
| 272 | + > | |
| 273 | + <Icon icon="ep:refresh" />清理全部 | |
| 274 | + </el-button> | |
| 275 | + </div> | |
| 276 | + </template> | |
| 277 | + <el-descriptions :column="1"> | |
| 278 | + <el-descriptions-item label="缓存键名:">{{ cacheForm.key }}</el-descriptions-item> | |
| 279 | + <el-descriptions-item label="缓存内容:">{{ cacheForm.value }}</el-descriptions-item> | |
| 280 | + </el-descriptions> | |
| 281 | + </el-card> | |
| 282 | + </el-col> | |
| 283 | + </el-row> | |
| 284 | + </Dialog> | |
| 205 | 285 | </template> |
| 286 | +<style scoped> | |
| 287 | +.redis { | |
| 288 | + height: 600px; | |
| 289 | + max-height: 860px; | |
| 290 | +} | |
| 291 | +</style> | ... | ... |
yudao-ui-admin-vue3/src/views/system/role/index.vue
| 1 | 1 | <script setup lang="ts"> |
| 2 | -import { reactive, ref, unref } from 'vue' | |
| 2 | +import { onMounted, reactive, ref, unref } from 'vue' | |
| 3 | 3 | import dayjs from 'dayjs' |
| 4 | 4 | import { DICT_TYPE, getDictOptions } from '@/utils/dict' |
| 5 | 5 | import { useTable } from '@/hooks/web/useTable' |
| ... | ... | @@ -18,7 +18,7 @@ import { |
| 18 | 18 | ElMessage, |
| 19 | 19 | ElTree, |
| 20 | 20 | ElCard, |
| 21 | - ElCheckbox | |
| 21 | + ElSwitch | |
| 22 | 22 | } from 'element-plus' |
| 23 | 23 | import { listSimpleMenusApi } from '@/api/system/menu' |
| 24 | 24 | import { listSimpleDeptApi } from '@/api/system/dept' |
| ... | ... | @@ -98,7 +98,6 @@ const dataScopeForm = reactive({ |
| 98 | 98 | name: '', |
| 99 | 99 | code: '', |
| 100 | 100 | dataScope: 0, |
| 101 | - checkStrictly: true, | |
| 102 | 101 | checkList: [] |
| 103 | 102 | }) |
| 104 | 103 | const defaultProps = { |
| ... | ... | @@ -113,15 +112,18 @@ const dialogScopeTitle = ref('数据权限') |
| 113 | 112 | const actionScopeType = ref('') |
| 114 | 113 | const dataScopeDictDatas = ref() |
| 115 | 114 | // 选项 |
| 115 | +const checkStrictly = ref(true) | |
| 116 | 116 | const treeNodeAll = ref(false) |
| 117 | 117 | // 权限操作 |
| 118 | 118 | const handleScope = async (type: string, row: RoleVO) => { |
| 119 | + checkStrictly.value = true | |
| 120 | + treeNodeAll.value = false | |
| 121 | + dataScopeForm.dataScope = 0 | |
| 119 | 122 | dataScopeForm.name = row.name |
| 120 | 123 | dataScopeForm.code = row.code |
| 121 | 124 | if (type === 'menu') { |
| 122 | 125 | const menuRes = await listSimpleMenusApi() |
| 123 | 126 | treeOptions.value = handleTree(menuRes) |
| 124 | - dataScopeDictDatas.value = getDictOptions(DICT_TYPE.SYSTEM_DATA_SCOPE) | |
| 125 | 127 | } else if (type === 'dept') { |
| 126 | 128 | const deptRes = await listSimpleDeptApi() |
| 127 | 129 | treeOptions.value = handleTree(deptRes) |
| ... | ... | @@ -129,20 +131,22 @@ const handleScope = async (type: string, row: RoleVO) => { |
| 129 | 131 | actionScopeType.value = type |
| 130 | 132 | dialogScopeVisible.value = true |
| 131 | 133 | } |
| 132 | -// 树权限(父子联动) | |
| 133 | -const handleCheckedTreeConnect = (value) => { | |
| 134 | - dataScopeForm.checkStrictly = value ? true : false | |
| 135 | -} | |
| 136 | 134 | // 全选/全不选 |
| 137 | -const handleCheckedTreeNodeAll = (value) => { | |
| 138 | - treeRef.value?.setCheckedNodes(value ? dataScopeForm.checkList : []) | |
| 135 | +const handleCheckedTreeNodeAll = () => { | |
| 136 | + treeRef.value?.setCheckedNodes(treeNodeAll.value ? treeOptions.value : []) | |
| 139 | 137 | } |
| 140 | 138 | // TODO:保存 |
| 141 | 139 | const submitScope = () => { |
| 142 | 140 | console.info() |
| 143 | 141 | } |
| 142 | +const init = () => { | |
| 143 | + dataScopeDictDatas.value = getDictOptions(DICT_TYPE.SYSTEM_DATA_SCOPE) | |
| 144 | +} | |
| 144 | 145 | // ========== 初始化 ========== |
| 145 | -getList() | |
| 146 | +onMounted(() => { | |
| 147 | + getList() | |
| 148 | + init() | |
| 149 | +}) | |
| 146 | 150 | </script> |
| 147 | 151 | |
| 148 | 152 | <template> |
| ... | ... | @@ -261,7 +265,7 @@ getList() |
| 261 | 265 | <el-button @click="dialogVisible = false">{{ t('dialog.close') }}</el-button> |
| 262 | 266 | </template> |
| 263 | 267 | </Dialog> |
| 264 | - <Dialog v-model="dialogScopeVisible" :title="dialogScopeTitle"> | |
| 268 | + <Dialog v-model="dialogScopeVisible" :title="dialogScopeTitle" max-height="600px"> | |
| 265 | 269 | <el-form :model="dataScopeForm"> |
| 266 | 270 | <el-form-item label="角色名称"> |
| 267 | 271 | <el-input v-model="dataScopeForm.name" :disabled="true" /> |
| ... | ... | @@ -289,21 +293,23 @@ getList() |
| 289 | 293 | > |
| 290 | 294 | <el-card class="box-card"> |
| 291 | 295 | <template #header> |
| 292 | - <el-checkbox | |
| 293 | - :checked="!dataScopeForm.checkStrictly" | |
| 294 | - @change="handleCheckedTreeConnect($event)" | |
| 295 | - >父子联动(选中父节点,自动选择子节点) | |
| 296 | - </el-checkbox> | |
| 297 | - <el-checkbox v-model="treeNodeAll" @change="handleCheckedTreeNodeAll($event)"> | |
| 298 | - 全选/全不选 | |
| 299 | - </el-checkbox> | |
| 296 | + 父子联动(选中父节点,自动选择子节点): | |
| 297 | + <el-switch v-model="checkStrictly" inline-prompt active-text="是" inactive-text="否" /> | |
| 298 | + 全选/全不选: | |
| 299 | + <el-switch | |
| 300 | + v-model="treeNodeAll" | |
| 301 | + inline-prompt | |
| 302 | + active-text="是" | |
| 303 | + inactive-text="否" | |
| 304 | + @change="handleCheckedTreeNodeAll()" | |
| 305 | + /> | |
| 300 | 306 | </template> |
| 301 | 307 | <el-tree |
| 302 | 308 | ref="treeRef" |
| 303 | 309 | node-key="id" |
| 304 | 310 | show-checkbox |
| 305 | 311 | default-expand-all |
| 306 | - :check-strictly="dataScopeForm.checkStrictly" | |
| 312 | + :check-strictly="!checkStrictly" | |
| 307 | 313 | :props="defaultProps" |
| 308 | 314 | :data="treeOptions" |
| 309 | 315 | empty-text="加载中,请稍后" | ... | ... |
yudao-ui-admin-vue3/windi.config.ts
| 1 | -import { defineConfig } from 'windicss/helpers' | |
| 1 | +import { defineConfig } from 'vite-plugin-windicss' | |
| 2 | 2 | import plugin from 'windicss/plugin' |
| 3 | 3 | |
| 4 | 4 | function range(size, startAt = 1) { |
| ... | ... | @@ -18,22 +18,7 @@ export default defineConfig({ |
| 18 | 18 | // 暗黑背景色 |
| 19 | 19 | 'v-dark': 'var(--dark-bg-color)' |
| 20 | 20 | } |
| 21 | - // screens: { | |
| 22 | - // sm: '768px', | |
| 23 | - // md: '992px', | |
| 24 | - // lg: '1200px', | |
| 25 | - // xl: '1920px' | |
| 26 | - // } | |
| 27 | 21 | } |
| 28 | - // height: { | |
| 29 | - // ...range(50).map((i) => `h-${i}px`) | |
| 30 | - // }, | |
| 31 | - // margin: { | |
| 32 | - // // ...range(50).map((i) => `mt-${i}px`), | |
| 33 | - // // ...range(50).map((i) => `mr-${i}px`), | |
| 34 | - // // ...range(50).map((i) => `mb-${i}px`), | |
| 35 | - // // ...range(50).map((i) => `ml-${i}px`) | |
| 36 | - // } | |
| 37 | 22 | }, |
| 38 | 23 | plugins: [ |
| 39 | 24 | plugin(({ addComponents }) => { | ... | ... |