Commit 79d55aa3e91242c30bfcb9e90b3acf95e3df0288
Committed by
Gitee
!245 优化表单校验和查询参数,增加 vue3 简单使用说明
Merge pull request !245 from xingyu/master
Showing
30 changed files
with
310 additions
and
96 deletions
README.md
| @@ -192,14 +192,14 @@ ps:核心功能已经实现,正在对接微信小程序中... | @@ -192,14 +192,14 @@ ps:核心功能已经实现,正在对接微信小程序中... | ||
| 192 | | [JUnit](https://junit.org/junit5/) | Java 单元测试框架 | 5.8.2 | - | | 192 | | [JUnit](https://junit.org/junit5/) | Java 单元测试框架 | 5.8.2 | - | |
| 193 | | [Mockito](https://github.com/mockito/mockito) | Java Mock 框架 | 4.0.0 | - | | 193 | | [Mockito](https://github.com/mockito/mockito) | Java Mock 框架 | 4.0.0 | - | |
| 194 | 194 | ||
| 195 | -### Vue2 前端 | 195 | +### [Vue2 前端](./yudao-ui-admin) |
| 196 | 196 | ||
| 197 | | 框架 | 说明 | 版本 | | 197 | | 框架 | 说明 | 版本 | |
| 198 | |------------------------------------------------------------------------------|---------------|--------| | 198 | |------------------------------------------------------------------------------|---------------|--------| |
| 199 | | [Vue](https://cn.vuejs.org/index.html) | JavaScript 框架 | 2.6.12 | | 199 | | [Vue](https://cn.vuejs.org/index.html) | JavaScript 框架 | 2.6.12 | |
| 200 | | [Vue Element Admin](https://panjiachen.github.io/vue-element-admin-site/zh/) | 后台前端解决方案 | - | | 200 | | [Vue Element Admin](https://panjiachen.github.io/vue-element-admin-site/zh/) | 后台前端解决方案 | - | |
| 201 | 201 | ||
| 202 | -### Vue3 前端 | 202 | +### [Vue3 前端](./yudao-ui-admin-vue3) |
| 203 | 203 | ||
| 204 | | 框架 | 说明 | 版本 | | 204 | | 框架 | 说明 | 版本 | |
| 205 | |----------------------------------------------------------------------|------------------|--------| | 205 | |----------------------------------------------------------------------|------------------|--------| |
yudao-ui-admin-vue3/README.md
| @@ -22,6 +22,8 @@ | @@ -22,6 +22,8 @@ | ||
| 22 | - node >=14.18.0(建议使用 16 版本) ,pnpm >=7 | 22 | - node >=14.18.0(建议使用 16 版本) ,pnpm >=7 |
| 23 | - 开发建议使用 [谷歌浏览器-开发者版](https://www.google.cn/intl/zh-CN/chrome/dev/) 不支持 IE\QQ 等浏览器 | 23 | - 开发建议使用 [谷歌浏览器-开发者版](https://www.google.cn/intl/zh-CN/chrome/dev/) 不支持 IE\QQ 等浏览器 |
| 24 | 24 | ||
| 25 | +### 点击查看[使用说明](./use.md) | ||
| 26 | + | ||
| 25 | ### 前端依赖 | 27 | ### 前端依赖 |
| 26 | 28 | ||
| 27 | | 框架 | 说明 | 版本 | | 29 | | 框架 | 说明 | 版本 | |
yudao-ui-admin-vue3/package.json
| @@ -65,8 +65,8 @@ | @@ -65,8 +65,8 @@ | ||
| 65 | "@types/nprogress": "^0.2.0", | 65 | "@types/nprogress": "^0.2.0", |
| 66 | "@types/qrcode": "^1.4.2", | 66 | "@types/qrcode": "^1.4.2", |
| 67 | "@types/qs": "^6.9.7", | 67 | "@types/qs": "^6.9.7", |
| 68 | - "@typescript-eslint/eslint-plugin": "^5.31.0", | ||
| 69 | - "@typescript-eslint/parser": "^5.31.0", | 68 | + "@typescript-eslint/eslint-plugin": "^5.32.0", |
| 69 | + "@typescript-eslint/parser": "^5.32.0", | ||
| 70 | "@vitejs/plugin-vue": "^3.0.1", | 70 | "@vitejs/plugin-vue": "^3.0.1", |
| 71 | "@vitejs/plugin-vue-jsx": "^2.0.0", | 71 | "@vitejs/plugin-vue-jsx": "^2.0.0", |
| 72 | "autoprefixer": "^10.4.8", | 72 | "autoprefixer": "^10.4.8", |
| @@ -91,7 +91,7 @@ | @@ -91,7 +91,7 @@ | ||
| 91 | "stylelint-config-standard": "^26.0.0", | 91 | "stylelint-config-standard": "^26.0.0", |
| 92 | "stylelint-order": "^5.0.0", | 92 | "stylelint-order": "^5.0.0", |
| 93 | "typescript": "4.7.4", | 93 | "typescript": "4.7.4", |
| 94 | - "unplugin-vue-define-options": "^0.6.2", | 94 | + "unplugin-vue-define-options": "^0.7.1", |
| 95 | "vite": "3.0.4", | 95 | "vite": "3.0.4", |
| 96 | "vite-plugin-compression": "^0.5.1", | 96 | "vite-plugin-compression": "^0.5.1", |
| 97 | "vite-plugin-eslint": "^1.7.0", | 97 | "vite-plugin-eslint": "^1.7.0", |
yudao-ui-admin-vue3/src/api/system/dept/types.ts
| 1 | export type DeptVO = { | 1 | export type DeptVO = { |
| 2 | id: number | 2 | id: number |
| 3 | name: string | 3 | name: string |
| 4 | - status: number | ||
| 5 | parentId: number | 4 | parentId: number |
| 6 | - createTime: string | 5 | + status: number |
| 6 | + sort: number | ||
| 7 | + leaderUserId: number | ||
| 8 | + phone: string | ||
| 9 | + email: string | ||
| 7 | } | 10 | } |
| 8 | 11 | ||
| 9 | export type DeptListReqVO = { | 12 | export type DeptListReqVO = { |
yudao-ui-admin-vue3/src/config/axios/index.ts
| 1 | import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios' | 1 | import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios' |
| 2 | -import { ElMessage, ElMessageBox, ElNotification } from 'element-plus' | 2 | +import { ElMessage, ElNotification } from 'element-plus' |
| 3 | import qs from 'qs' | 3 | import qs from 'qs' |
| 4 | import { config } from '@/config/axios/config' | 4 | import { config } from '@/config/axios/config' |
| 5 | -import { getAccessToken, getRefreshToken, getTenantId } from '@/utils/auth' | 5 | +import { getAccessToken, getTenantId, removeToken } from '@/utils/auth' |
| 6 | import errorCode from './errorCode' | 6 | import errorCode from './errorCode' |
| 7 | import { useI18n } from '@/hooks/web/useI18n' | 7 | import { useI18n } from '@/hooks/web/useI18n' |
| 8 | 8 | ||
| @@ -22,7 +22,7 @@ export const isRelogin = { show: false } | @@ -22,7 +22,7 @@ export const isRelogin = { show: false } | ||
| 22 | // 请求队列 | 22 | // 请求队列 |
| 23 | // const requestList = [] | 23 | // const requestList = [] |
| 24 | // 是否正在刷新中 | 24 | // 是否正在刷新中 |
| 25 | -let isRefreshToken = false | 25 | +// const isRefreshToken = false |
| 26 | 26 | ||
| 27 | export const PATH_URL = base_url[import.meta.env.VITE_API_BASEPATH] | 27 | export const PATH_URL = base_url[import.meta.env.VITE_API_BASEPATH] |
| 28 | 28 | ||
| @@ -55,18 +55,26 @@ service.interceptors.request.use( | @@ -55,18 +55,26 @@ service.interceptors.request.use( | ||
| 55 | config.data = qs.stringify(data) | 55 | config.data = qs.stringify(data) |
| 56 | } | 56 | } |
| 57 | // get参数编码 | 57 | // get参数编码 |
| 58 | - if (config.method?.toUpperCase() === 'GET' && config.params) { | ||
| 59 | - let url = config.url as string | 58 | + if (config.method?.toUpperCase() === 'GET' && params) { |
| 59 | + let url = config.url + '?' | ||
| 60 | + for (const propName of Object.keys(params)) { | ||
| 61 | + const value = params[propName] | ||
| 62 | + if (value !== void 0 && value !== null && typeof value !== 'undefined') { | ||
| 63 | + if (typeof value === 'object') { | ||
| 64 | + for (const val of Object.keys(value)) { | ||
| 65 | + const params = propName + '[' + val + ']' | ||
| 66 | + const subPart = encodeURIComponent(params) + '=' | ||
| 67 | + url += subPart + encodeURIComponent(value[val]) + '&' | ||
| 68 | + } | ||
| 69 | + } else { | ||
| 70 | + url += `${propName}=${encodeURIComponent(value)}&` | ||
| 71 | + } | ||
| 72 | + } | ||
| 73 | + } | ||
| 60 | // 给 get 请求加上时间戳参数,避免从缓存中拿数据 | 74 | // 给 get 请求加上时间戳参数,避免从缓存中拿数据 |
| 61 | // const now = new Date().getTime() | 75 | // const now = new Date().getTime() |
| 62 | // params = params.substring(0, url.length - 1) + `?_t=${now}` | 76 | // params = params.substring(0, url.length - 1) + `?_t=${now}` |
| 63 | - url += '?' | ||
| 64 | - const keys = Object.keys(params) | ||
| 65 | - for (const key of keys) { | ||
| 66 | - if (params[key] !== void 0 && params[key] !== null) { | ||
| 67 | - url += `${key}=${encodeURIComponent(params[key])}&` | ||
| 68 | - } | ||
| 69 | - } | 77 | + url = url.slice(0, -1) |
| 70 | config.params = {} | 78 | config.params = {} |
| 71 | config.url = url | 79 | config.url = url |
| 72 | } | 80 | } |
| @@ -90,6 +98,13 @@ service.interceptors.response.use( | @@ -90,6 +98,13 @@ service.interceptors.response.use( | ||
| 90 | const { t } = useI18n() | 98 | const { t } = useI18n() |
| 91 | // 未设置状态码则默认成功状态 | 99 | // 未设置状态码则默认成功状态 |
| 92 | const code = data.code || result_code | 100 | const code = data.code || result_code |
| 101 | + // 二进制数据则直接返回 | ||
| 102 | + if ( | ||
| 103 | + response.request.responseType === 'blob' || | ||
| 104 | + response.request.responseType === 'arraybuffer' | ||
| 105 | + ) { | ||
| 106 | + return response.data | ||
| 107 | + } | ||
| 93 | // 获取错误信息 | 108 | // 获取错误信息 |
| 94 | const msg = data.msg || errorCode[code] || errorCode['default'] | 109 | const msg = data.msg || errorCode[code] || errorCode['default'] |
| 95 | if (ignoreMsgs.indexOf(msg) !== -1) { | 110 | if (ignoreMsgs.indexOf(msg) !== -1) { |
| @@ -97,15 +112,16 @@ service.interceptors.response.use( | @@ -97,15 +112,16 @@ service.interceptors.response.use( | ||
| 97 | return Promise.reject(msg) | 112 | return Promise.reject(msg) |
| 98 | } else if (code === 401) { | 113 | } else if (code === 401) { |
| 99 | // 如果未认证,并且未进行刷新令牌,说明可能是访问令牌过期了 | 114 | // 如果未认证,并且未进行刷新令牌,说明可能是访问令牌过期了 |
| 100 | - if (!isRefreshToken) { | ||
| 101 | - isRefreshToken = true | ||
| 102 | - // 1. 如果获取不到刷新令牌,则只能执行登出操作 | ||
| 103 | - if (!getRefreshToken()) { | ||
| 104 | - return handleAuthorized() | ||
| 105 | - } | ||
| 106 | - // 2. 进行刷新访问令牌 | ||
| 107 | - // TODO: 引入refreshToken会循环依赖报错 | ||
| 108 | - } | 115 | + return handleAuthorized() |
| 116 | + // if (!isRefreshToken) { | ||
| 117 | + // isRefreshToken = true | ||
| 118 | + // // 1. 如果获取不到刷新令牌,则只能执行登出操作 | ||
| 119 | + // if (!getRefreshToken()) { | ||
| 120 | + // return handleAuthorized() | ||
| 121 | + // } | ||
| 122 | + // // 2. 进行刷新访问令牌 | ||
| 123 | + // // TODO: 引入refreshToken会循环依赖报错 | ||
| 124 | + // } | ||
| 109 | } else if (code === 500) { | 125 | } else if (code === 500) { |
| 110 | ElMessage.error(t('sys.api.errMsg500')) | 126 | ElMessage.error(t('sys.api.errMsg500')) |
| 111 | return Promise.reject(new Error(msg)) | 127 | return Promise.reject(new Error(msg)) |
| @@ -149,21 +165,12 @@ service.interceptors.response.use( | @@ -149,21 +165,12 @@ service.interceptors.response.use( | ||
| 149 | return Promise.reject(error) | 165 | return Promise.reject(error) |
| 150 | } | 166 | } |
| 151 | ) | 167 | ) |
| 152 | -function handleAuthorized() { | 168 | +const handleAuthorized = () => { |
| 153 | const { t } = useI18n() | 169 | const { t } = useI18n() |
| 154 | if (!isRelogin.show) { | 170 | if (!isRelogin.show) { |
| 171 | + removeToken() | ||
| 155 | isRelogin.show = true | 172 | isRelogin.show = true |
| 156 | - ElMessageBox.confirm(t('sys.api.timeoutMessage'), t('common.confirmTitle'), { | ||
| 157 | - confirmButtonText: t('login.relogin'), | ||
| 158 | - cancelButtonText: t('common.cancel'), | ||
| 159 | - type: 'warning' | ||
| 160 | - }) | ||
| 161 | - .then(() => { | ||
| 162 | - isRelogin.show = false | ||
| 163 | - }) | ||
| 164 | - .catch(() => { | ||
| 165 | - isRelogin.show = false | ||
| 166 | - }) | 173 | + ElNotification.error(t('sys.api.timeoutMessage')) |
| 167 | } | 174 | } |
| 168 | return Promise.reject(t('sys.api.timeoutMessage')) | 175 | return Promise.reject(t('sys.api.timeoutMessage')) |
| 169 | } | 176 | } |
yudao-ui-admin-vue3/src/utils/tree.ts
| @@ -213,7 +213,7 @@ export const eachTree = (treeDatas: any[], callBack: Fn, parentNode = {}) => { | @@ -213,7 +213,7 @@ export const eachTree = (treeDatas: any[], callBack: Fn, parentNode = {}) => { | ||
| 213 | * @param {*} parentId 父节点字段 默认 'parentId' | 213 | * @param {*} parentId 父节点字段 默认 'parentId' |
| 214 | * @param {*} children 孩子节点字段 默认 'children' | 214 | * @param {*} children 孩子节点字段 默认 'children' |
| 215 | */ | 215 | */ |
| 216 | -export const handleTree = (data, id?: string, parentId?: string, children?: string) => { | 216 | +export const handleTree = (data: any[], id?: string, parentId?: string, children?: string) => { |
| 217 | const config = { | 217 | const config = { |
| 218 | id: id || 'id', | 218 | id: id || 'id', |
| 219 | parentId: parentId || 'parentId', | 219 | parentId: parentId || 'parentId', |
| @@ -222,7 +222,7 @@ export const handleTree = (data, id?: string, parentId?: string, children?: stri | @@ -222,7 +222,7 @@ export const handleTree = (data, id?: string, parentId?: string, children?: stri | ||
| 222 | 222 | ||
| 223 | const childrenListMap = {} | 223 | const childrenListMap = {} |
| 224 | const nodeIds = {} | 224 | const nodeIds = {} |
| 225 | - const tree = [] | 225 | + const tree: any[] = [] |
| 226 | 226 | ||
| 227 | for (const d of data) { | 227 | for (const d of data) { |
| 228 | const parentId = d[config.parentId] | 228 | const parentId = d[config.parentId] |
yudao-ui-admin-vue3/src/views/infra/apiAccessLog/apiAccessLog.data.ts
| @@ -50,7 +50,16 @@ const crudSchemas = reactive<CrudSchema[]>([ | @@ -50,7 +50,16 @@ const crudSchemas = reactive<CrudSchema[]>([ | ||
| 50 | }, | 50 | }, |
| 51 | { | 51 | { |
| 52 | label: '请求时间', | 52 | label: '请求时间', |
| 53 | - field: 'beginTime' | 53 | + field: 'beginTime', |
| 54 | + search: { | ||
| 55 | + show: true, | ||
| 56 | + component: 'DatePicker', | ||
| 57 | + componentProps: { | ||
| 58 | + type: 'datetimerange', | ||
| 59 | + valueFormat: 'YYYY-MM-DD HH:mm:ss', | ||
| 60 | + defaultTime: [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)] | ||
| 61 | + } | ||
| 62 | + } | ||
| 54 | }, | 63 | }, |
| 55 | { | 64 | { |
| 56 | label: '执行时长', | 65 | label: '执行时长', |
yudao-ui-admin-vue3/src/views/infra/apiErrorLog/apiErrorLog.data.ts
| @@ -50,7 +50,16 @@ const crudSchemas = reactive<CrudSchema[]>([ | @@ -50,7 +50,16 @@ const crudSchemas = reactive<CrudSchema[]>([ | ||
| 50 | }, | 50 | }, |
| 51 | { | 51 | { |
| 52 | label: '异常发生时间', | 52 | label: '异常发生时间', |
| 53 | - field: 'exceptionTime' | 53 | + field: 'exceptionTime', |
| 54 | + search: { | ||
| 55 | + show: true, | ||
| 56 | + component: 'DatePicker', | ||
| 57 | + componentProps: { | ||
| 58 | + type: 'datetimerange', | ||
| 59 | + valueFormat: 'YYYY-MM-DD HH:mm:ss', | ||
| 60 | + defaultTime: [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)] | ||
| 61 | + } | ||
| 62 | + } | ||
| 54 | }, | 63 | }, |
| 55 | { | 64 | { |
| 56 | label: '异常名', | 65 | label: '异常名', |
yudao-ui-admin-vue3/src/views/infra/codegen/codegen.data.ts
| @@ -50,6 +50,15 @@ const crudSchemas = reactive<CrudSchema[]>([ | @@ -50,6 +50,15 @@ const crudSchemas = reactive<CrudSchema[]>([ | ||
| 50 | field: 'createTime', | 50 | field: 'createTime', |
| 51 | form: { | 51 | form: { |
| 52 | show: false | 52 | show: false |
| 53 | + }, | ||
| 54 | + search: { | ||
| 55 | + show: true, | ||
| 56 | + component: 'DatePicker', | ||
| 57 | + componentProps: { | ||
| 58 | + type: 'datetimerange', | ||
| 59 | + valueFormat: 'YYYY-MM-DD HH:mm:ss', | ||
| 60 | + defaultTime: [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)] | ||
| 61 | + } | ||
| 53 | } | 62 | } |
| 54 | }, | 63 | }, |
| 55 | { | 64 | { |
yudao-ui-admin-vue3/src/views/infra/config/config.data.ts
| @@ -91,6 +91,15 @@ const crudSchemas = reactive<CrudSchema[]>([ | @@ -91,6 +91,15 @@ const crudSchemas = reactive<CrudSchema[]>([ | ||
| 91 | field: 'createTime', | 91 | field: 'createTime', |
| 92 | form: { | 92 | form: { |
| 93 | show: false | 93 | show: false |
| 94 | + }, | ||
| 95 | + search: { | ||
| 96 | + show: true, | ||
| 97 | + component: 'DatePicker', | ||
| 98 | + componentProps: { | ||
| 99 | + type: 'datetimerange', | ||
| 100 | + valueFormat: 'YYYY-MM-DD HH:mm:ss', | ||
| 101 | + defaultTime: [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)] | ||
| 102 | + } | ||
| 94 | } | 103 | } |
| 95 | }, | 104 | }, |
| 96 | { | 105 | { |
yudao-ui-admin-vue3/src/views/infra/dataSourceConfig/dataSourceConfig.data.ts
| @@ -58,6 +58,15 @@ const crudSchemas = reactive<CrudSchema[]>([ | @@ -58,6 +58,15 @@ const crudSchemas = reactive<CrudSchema[]>([ | ||
| 58 | field: 'createTime', | 58 | field: 'createTime', |
| 59 | form: { | 59 | form: { |
| 60 | show: false | 60 | show: false |
| 61 | + }, | ||
| 62 | + search: { | ||
| 63 | + show: true, | ||
| 64 | + component: 'DatePicker', | ||
| 65 | + componentProps: { | ||
| 66 | + type: 'datetimerange', | ||
| 67 | + valueFormat: 'YYYY-MM-DD HH:mm:ss', | ||
| 68 | + defaultTime: [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)] | ||
| 69 | + } | ||
| 61 | } | 70 | } |
| 62 | }, | 71 | }, |
| 63 | { | 72 | { |
yudao-ui-admin-vue3/src/views/infra/fileConfig/fileConfig.data.ts
| @@ -76,6 +76,15 @@ const crudSchemas = reactive<CrudSchema[]>([ | @@ -76,6 +76,15 @@ const crudSchemas = reactive<CrudSchema[]>([ | ||
| 76 | field: 'createTime', | 76 | field: 'createTime', |
| 77 | form: { | 77 | form: { |
| 78 | show: false | 78 | show: false |
| 79 | + }, | ||
| 80 | + search: { | ||
| 81 | + show: true, | ||
| 82 | + component: 'DatePicker', | ||
| 83 | + componentProps: { | ||
| 84 | + type: 'datetimerange', | ||
| 85 | + valueFormat: 'YYYY-MM-DD HH:mm:ss', | ||
| 86 | + defaultTime: [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)] | ||
| 87 | + } | ||
| 79 | } | 88 | } |
| 80 | }, | 89 | }, |
| 81 | { | 90 | { |
yudao-ui-admin-vue3/src/views/infra/fileList/fileList.data.ts
| @@ -36,6 +36,15 @@ const crudSchemas = reactive<CrudSchema[]>([ | @@ -36,6 +36,15 @@ const crudSchemas = reactive<CrudSchema[]>([ | ||
| 36 | field: 'createTime', | 36 | field: 'createTime', |
| 37 | form: { | 37 | form: { |
| 38 | show: false | 38 | show: false |
| 39 | + }, | ||
| 40 | + search: { | ||
| 41 | + show: true, | ||
| 42 | + component: 'DatePicker', | ||
| 43 | + componentProps: { | ||
| 44 | + type: 'datetimerange', | ||
| 45 | + valueFormat: 'YYYY-MM-DD HH:mm:ss', | ||
| 46 | + defaultTime: [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)] | ||
| 47 | + } | ||
| 39 | } | 48 | } |
| 40 | }, | 49 | }, |
| 41 | { | 50 | { |
yudao-ui-admin-vue3/src/views/pay/app/app.data.ts
| @@ -8,9 +8,10 @@ const { t } = useI18n() // 国际化 | @@ -8,9 +8,10 @@ const { t } = useI18n() // 国际化 | ||
| 8 | // 表单校验 | 8 | // 表单校验 |
| 9 | export const rules = reactive({ | 9 | export const rules = reactive({ |
| 10 | name: [required], | 10 | name: [required], |
| 11 | - code: [required], | ||
| 12 | - sort: [required], | ||
| 13 | - status: [required] | 11 | + status: [required], |
| 12 | + payNotifyUrl: [required], | ||
| 13 | + refundNotifyUrl: [required], | ||
| 14 | + merchantId: [required] | ||
| 14 | }) | 15 | }) |
| 15 | 16 | ||
| 16 | // CrudSchema | 17 | // CrudSchema |
| @@ -53,6 +54,15 @@ const crudSchemas = reactive<CrudSchema[]>([ | @@ -53,6 +54,15 @@ const crudSchemas = reactive<CrudSchema[]>([ | ||
| 53 | field: 'createTime', | 54 | field: 'createTime', |
| 54 | form: { | 55 | form: { |
| 55 | show: false | 56 | show: false |
| 57 | + }, | ||
| 58 | + search: { | ||
| 59 | + show: true, | ||
| 60 | + component: 'DatePicker', | ||
| 61 | + componentProps: { | ||
| 62 | + type: 'datetimerange', | ||
| 63 | + valueFormat: 'YYYY-MM-DD HH:mm:ss', | ||
| 64 | + defaultTime: [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)] | ||
| 65 | + } | ||
| 56 | } | 66 | } |
| 57 | }, | 67 | }, |
| 58 | { | 68 | { |
yudao-ui-admin-vue3/src/views/pay/merchant/merchant.data.ts
| @@ -7,9 +7,9 @@ const { t } = useI18n() // 国际化 | @@ -7,9 +7,9 @@ const { t } = useI18n() // 国际化 | ||
| 7 | 7 | ||
| 8 | // 表单校验 | 8 | // 表单校验 |
| 9 | export const rules = reactive({ | 9 | export const rules = reactive({ |
| 10 | + no: [required], | ||
| 10 | name: [required], | 11 | name: [required], |
| 11 | - code: [required], | ||
| 12 | - sort: [required], | 12 | + shortName: [required], |
| 13 | status: [required] | 13 | status: [required] |
| 14 | }) | 14 | }) |
| 15 | 15 | ||
| @@ -77,6 +77,15 @@ const crudSchemas = reactive<CrudSchema[]>([ | @@ -77,6 +77,15 @@ const crudSchemas = reactive<CrudSchema[]>([ | ||
| 77 | field: 'createTime', | 77 | field: 'createTime', |
| 78 | form: { | 78 | form: { |
| 79 | show: false | 79 | show: false |
| 80 | + }, | ||
| 81 | + search: { | ||
| 82 | + show: true, | ||
| 83 | + component: 'DatePicker', | ||
| 84 | + componentProps: { | ||
| 85 | + type: 'datetimerange', | ||
| 86 | + valueFormat: 'YYYY-MM-DD HH:mm:ss', | ||
| 87 | + defaultTime: [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)] | ||
| 88 | + } | ||
| 80 | } | 89 | } |
| 81 | }, | 90 | }, |
| 82 | { | 91 | { |
yudao-ui-admin-vue3/src/views/pay/order/order.data.ts
| @@ -158,6 +158,22 @@ const crudSchemas = reactive<CrudSchema[]>([ | @@ -158,6 +158,22 @@ const crudSchemas = reactive<CrudSchema[]>([ | ||
| 158 | field: 'channelOrderNo' | 158 | field: 'channelOrderNo' |
| 159 | }, | 159 | }, |
| 160 | { | 160 | { |
| 161 | + label: t('common.createTime'), | ||
| 162 | + field: 'createTime', | ||
| 163 | + form: { | ||
| 164 | + show: false | ||
| 165 | + }, | ||
| 166 | + search: { | ||
| 167 | + show: true, | ||
| 168 | + component: 'DatePicker', | ||
| 169 | + componentProps: { | ||
| 170 | + type: 'datetimerange', | ||
| 171 | + valueFormat: 'YYYY-MM-DD HH:mm:ss', | ||
| 172 | + defaultTime: [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)] | ||
| 173 | + } | ||
| 174 | + } | ||
| 175 | + }, | ||
| 176 | + { | ||
| 161 | label: t('table.action'), | 177 | label: t('table.action'), |
| 162 | field: 'action', | 178 | field: 'action', |
| 163 | width: '270px', | 179 | width: '270px', |
yudao-ui-admin-vue3/src/views/pay/refund/refund.data.ts
| @@ -84,6 +84,15 @@ const crudSchemas = reactive<CrudSchema[]>([ | @@ -84,6 +84,15 @@ const crudSchemas = reactive<CrudSchema[]>([ | ||
| 84 | field: 'createTime', | 84 | field: 'createTime', |
| 85 | form: { | 85 | form: { |
| 86 | show: false | 86 | show: false |
| 87 | + }, | ||
| 88 | + search: { | ||
| 89 | + show: true, | ||
| 90 | + component: 'DatePicker', | ||
| 91 | + componentProps: { | ||
| 92 | + type: 'datetimerange', | ||
| 93 | + valueFormat: 'YYYY-MM-DD HH:mm:ss', | ||
| 94 | + defaultTime: [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)] | ||
| 95 | + } | ||
| 87 | } | 96 | } |
| 88 | }, | 97 | }, |
| 89 | { | 98 | { |
yudao-ui-admin-vue3/src/views/system/dept/dept.data.ts
| 1 | import { required } from '@/utils/formRules' | 1 | import { required } from '@/utils/formRules' |
| 2 | import { reactive } from 'vue' | 2 | import { reactive } from 'vue' |
| 3 | +// 表单校验 | ||
| 4 | +export const rules = reactive({ | ||
| 5 | + name: [required], | ||
| 6 | + sort: [required], | ||
| 7 | + email: [required], | ||
| 8 | + phone: [ | ||
| 9 | + { | ||
| 10 | + pattern: | ||
| 11 | + /^(?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[189]))\d{8}$/, | ||
| 12 | + trigger: 'blur', | ||
| 13 | + message: '请输入正确的手机号码' | ||
| 14 | + } | ||
| 15 | + ] | ||
| 16 | +}) | ||
| 3 | 17 | ||
| 4 | export const modelSchema = reactive<FormSchema[]>([ | 18 | export const modelSchema = reactive<FormSchema[]>([ |
| 5 | { | 19 | { |
| @@ -17,7 +31,7 @@ export const modelSchema = reactive<FormSchema[]>([ | @@ -17,7 +31,7 @@ export const modelSchema = reactive<FormSchema[]>([ | ||
| 17 | }, | 31 | }, |
| 18 | { | 32 | { |
| 19 | label: '负责人', | 33 | label: '负责人', |
| 20 | - field: 'email', | 34 | + field: 'leaderUserId', |
| 21 | component: 'Input' | 35 | component: 'Input' |
| 22 | }, | 36 | }, |
| 23 | { | 37 | { |
| @@ -33,7 +47,7 @@ export const modelSchema = reactive<FormSchema[]>([ | @@ -33,7 +47,7 @@ export const modelSchema = reactive<FormSchema[]>([ | ||
| 33 | { | 47 | { |
| 34 | label: '显示排序', | 48 | label: '显示排序', |
| 35 | field: 'sort', | 49 | field: 'sort', |
| 36 | - component: 'Input' | 50 | + component: 'InputNumber' |
| 37 | }, | 51 | }, |
| 38 | { | 52 | { |
| 39 | label: '状态', | 53 | label: '状态', |
yudao-ui-admin-vue3/src/views/system/dept/index.vue
| 1 | <script setup lang="ts"> | 1 | <script setup lang="ts"> |
| 2 | import { useI18n } from '@/hooks/web/useI18n' | 2 | import { useI18n } from '@/hooks/web/useI18n' |
| 3 | -import { ElInput, ElCard, ElTree, ElTreeSelect } from 'element-plus' | 3 | +import { ElInput, ElCard, ElTree, ElTreeSelect, ElSelect, ElOption } from 'element-plus' |
| 4 | import { handleTree } from '@/utils/tree' | 4 | import { handleTree } from '@/utils/tree' |
| 5 | import { onMounted, ref, unref, watch } from 'vue' | 5 | import { onMounted, ref, unref, watch } from 'vue' |
| 6 | import * as DeptApi from '@/api/system/dept' | 6 | import * as DeptApi from '@/api/system/dept' |
| 7 | import { Form, FormExpose } from '@/components/Form' | 7 | import { Form, FormExpose } from '@/components/Form' |
| 8 | -import { modelSchema } from './dept.data' | 8 | +import { modelSchema, rules } from './dept.data' |
| 9 | import { DeptVO } from '@/api/system/dept/types' | 9 | import { DeptVO } from '@/api/system/dept/types' |
| 10 | import { useMessage } from '@/hooks/web/useMessage' | 10 | import { useMessage } from '@/hooks/web/useMessage' |
| 11 | +import { getListSimpleUsersApi } from '@/api/system/user' | ||
| 11 | const message = useMessage() | 12 | const message = useMessage() |
| 12 | interface Tree { | 13 | interface Tree { |
| 13 | id: number | 14 | id: number |
| @@ -34,7 +35,7 @@ const filterText = ref('') | @@ -34,7 +35,7 @@ const filterText = ref('') | ||
| 34 | const deptOptions = ref() // 树形结构 | 35 | const deptOptions = ref() // 树形结构 |
| 35 | const treeRef = ref<InstanceType<typeof ElTree>>() | 36 | const treeRef = ref<InstanceType<typeof ElTree>>() |
| 36 | const getTree = async () => { | 37 | const getTree = async () => { |
| 37 | - const res = await DeptApi.getDeptPageApi(null) | 38 | + const res = await DeptApi.listSimpleDeptApi() |
| 38 | deptOptions.value = handleTree(res) | 39 | deptOptions.value = handleTree(res) |
| 39 | } | 40 | } |
| 40 | const filterNode = (value: string, data: Tree) => { | 41 | const filterNode = (value: string, data: Tree) => { |
| @@ -44,6 +45,13 @@ const filterNode = (value: string, data: Tree) => { | @@ -44,6 +45,13 @@ const filterNode = (value: string, data: Tree) => { | ||
| 44 | watch(filterText, (val) => { | 45 | watch(filterText, (val) => { |
| 45 | treeRef.value!.filter(val) | 46 | treeRef.value!.filter(val) |
| 46 | }) | 47 | }) |
| 48 | +// 用户列表 | ||
| 49 | +const userOption = ref() | ||
| 50 | +const leaderUserId = ref() | ||
| 51 | +const getUserList = async () => { | ||
| 52 | + const res = await getListSimpleUsersApi() | ||
| 53 | + userOption.value = res | ||
| 54 | +} | ||
| 47 | // 新增 | 55 | // 新增 |
| 48 | const handleAdd = (data: { id: number }) => { | 56 | const handleAdd = (data: { id: number }) => { |
| 49 | // 重置表单 | 57 | // 重置表单 |
| @@ -54,11 +62,12 @@ const handleAdd = (data: { id: number }) => { | @@ -54,11 +62,12 @@ const handleAdd = (data: { id: number }) => { | ||
| 54 | } | 62 | } |
| 55 | // 编辑 | 63 | // 编辑 |
| 56 | const handleUpdate = async (data: { id: number }) => { | 64 | const handleUpdate = async (data: { id: number }) => { |
| 57 | - showForm.value = true | ||
| 58 | const res = await DeptApi.getDeptApi(data.id) | 65 | const res = await DeptApi.getDeptApi(data.id) |
| 59 | formTitle.value = '修改- ' + res?.name | 66 | formTitle.value = '修改- ' + res?.name |
| 60 | deptParentId.value = res.parentId | 67 | deptParentId.value = res.parentId |
| 68 | + leaderUserId.value = res.leaderUserId | ||
| 61 | unref(formRef)?.setValues(res) | 69 | unref(formRef)?.setValues(res) |
| 70 | + showForm.value = true | ||
| 62 | } | 71 | } |
| 63 | // 删除 | 72 | // 删除 |
| 64 | const handleDelete = async (data: { id: number }) => { | 73 | const handleDelete = async (data: { id: number }) => { |
| @@ -78,7 +87,7 @@ const submitForm = async () => { | @@ -78,7 +87,7 @@ const submitForm = async () => { | ||
| 78 | try { | 87 | try { |
| 79 | const data = unref(formRef)?.formModel as DeptVO | 88 | const data = unref(formRef)?.formModel as DeptVO |
| 80 | data.parentId = deptParentId.value | 89 | data.parentId = deptParentId.value |
| 81 | - // TODO: 表单提交待完善 | 90 | + data.leaderUserId = leaderUserId.value |
| 82 | if (formTitle.value.startsWith('新增')) { | 91 | if (formTitle.value.startsWith('新增')) { |
| 83 | await DeptApi.createDeptApi(data) | 92 | await DeptApi.createDeptApi(data) |
| 84 | } else if (formTitle.value.startsWith('修改')) { | 93 | } else if (formTitle.value.startsWith('修改')) { |
| @@ -92,6 +101,7 @@ const submitForm = async () => { | @@ -92,6 +101,7 @@ const submitForm = async () => { | ||
| 92 | } | 101 | } |
| 93 | onMounted(async () => { | 102 | onMounted(async () => { |
| 94 | await getTree() | 103 | await getTree() |
| 104 | + await getUserList() | ||
| 95 | }) | 105 | }) |
| 96 | </script> | 106 | </script> |
| 97 | <template> | 107 | <template> |
| @@ -123,14 +133,29 @@ onMounted(async () => { | @@ -123,14 +133,29 @@ onMounted(async () => { | ||
| 123 | <span class="custom-tree-node"> | 133 | <span class="custom-tree-node"> |
| 124 | <span>{{ node.label }}</span> | 134 | <span>{{ node.label }}</span> |
| 125 | <span> | 135 | <span> |
| 126 | - <el-button link v-hasPermi="['system:dept:create']" @click="handleAdd(data)"> | ||
| 127 | - <Icon icon="ep:plus" class="mr-1px" /> | 136 | + <el-button |
| 137 | + link | ||
| 138 | + type="primary" | ||
| 139 | + v-hasPermi="['system:dept:create']" | ||
| 140 | + @click="handleAdd(data)" | ||
| 141 | + > | ||
| 142 | + <Icon icon="ep:zoom-in" class="mr-5px" /> {{ t('action.add') }} | ||
| 128 | </el-button> | 143 | </el-button> |
| 129 | - <el-button link v-hasPermi="['system:dept:update']" @click="handleUpdate(data)"> | ||
| 130 | - <Icon icon="ep:edit" class="mr-1px" /> | 144 | + <el-button |
| 145 | + link | ||
| 146 | + type="primary" | ||
| 147 | + v-hasPermi="['system:dept:update']" | ||
| 148 | + @click="handleUpdate(data)" | ||
| 149 | + > | ||
| 150 | + <Icon icon="ep:edit" class="mr-1px" /> {{ t('action.edit') }} | ||
| 131 | </el-button> | 151 | </el-button> |
| 132 | - <el-button link v-hasPermi="['system:dept:delete']" @click="handleDelete(data)"> | ||
| 133 | - <Icon icon="ep:delete" class="mr-1px" /> | 152 | + <el-button |
| 153 | + link | ||
| 154 | + type="primary" | ||
| 155 | + v-hasPermi="['system:dept:delete']" | ||
| 156 | + @click="handleDelete(data)" | ||
| 157 | + > | ||
| 158 | + <Icon icon="ep:delete" class="mr-1px" /> {{ t('action.del') }} | ||
| 134 | </el-button> | 159 | </el-button> |
| 135 | </span> | 160 | </span> |
| 136 | </span> | 161 | </span> |
| @@ -149,7 +174,7 @@ onMounted(async () => { | @@ -149,7 +174,7 @@ onMounted(async () => { | ||
| 149 | </div> | 174 | </div> |
| 150 | <div v-if="showForm"> | 175 | <div v-if="showForm"> |
| 151 | <!-- 操作工具栏 --> | 176 | <!-- 操作工具栏 --> |
| 152 | - <Form :schema="modelSchema" ref="formRef"> | 177 | + <Form ref="formRef" :schema="modelSchema" :rules="rules"> |
| 153 | <template #parentId> | 178 | <template #parentId> |
| 154 | <el-tree-select | 179 | <el-tree-select |
| 155 | node-key="id" | 180 | node-key="id" |
| @@ -159,6 +184,16 @@ onMounted(async () => { | @@ -159,6 +184,16 @@ onMounted(async () => { | ||
| 159 | check-strictly | 184 | check-strictly |
| 160 | /> | 185 | /> |
| 161 | </template> | 186 | </template> |
| 187 | + <template #leaderUserId> | ||
| 188 | + <el-select v-model="leaderUserId"> | ||
| 189 | + <el-option | ||
| 190 | + v-for="item in userOption" | ||
| 191 | + :key="parseInt(item.id)" | ||
| 192 | + :label="item.nickname" | ||
| 193 | + :value="parseInt(item.id)" | ||
| 194 | + /> | ||
| 195 | + </el-select> | ||
| 196 | + </template> | ||
| 162 | </Form> | 197 | </Form> |
| 163 | <!-- 操作按钮 --> | 198 | <!-- 操作按钮 --> |
| 164 | <el-button | 199 | <el-button |
yudao-ui-admin-vue3/src/views/system/dict/dict.data.ts
| @@ -7,9 +7,9 @@ import { CrudSchema, useCrudSchemas } from '@/hooks/web/useCrudSchemas' | @@ -7,9 +7,9 @@ import { CrudSchema, useCrudSchemas } from '@/hooks/web/useCrudSchemas' | ||
| 7 | const { t } = useI18n() | 7 | const { t } = useI18n() |
| 8 | // 表单校验 | 8 | // 表单校验 |
| 9 | export const dictDataRules = reactive({ | 9 | export const dictDataRules = reactive({ |
| 10 | - dictType: [required], | ||
| 11 | label: [required], | 10 | label: [required], |
| 12 | - value: [required] | 11 | + value: [required], |
| 12 | + sort: [required] | ||
| 13 | }) | 13 | }) |
| 14 | // crudSchemas | 14 | // crudSchemas |
| 15 | export const crudSchemas = reactive<CrudSchema[]>([ | 15 | export const crudSchemas = reactive<CrudSchema[]>([ |
| @@ -29,6 +29,9 @@ export const crudSchemas = reactive<CrudSchema[]>([ | @@ -29,6 +29,9 @@ export const crudSchemas = reactive<CrudSchema[]>([ | ||
| 29 | field: 'dictType', | 29 | field: 'dictType', |
| 30 | table: { | 30 | table: { |
| 31 | show: false | 31 | show: false |
| 32 | + }, | ||
| 33 | + form: { | ||
| 34 | + show: false | ||
| 32 | } | 35 | } |
| 33 | }, | 36 | }, |
| 34 | { | 37 | { |
yudao-ui-admin-vue3/src/views/system/menu/index.vue
| @@ -25,11 +25,12 @@ import { MenuVO } from '@/api/system/menu/types' | @@ -25,11 +25,12 @@ import { MenuVO } from '@/api/system/menu/types' | ||
| 25 | import { SystemMenuTypeEnum, CommonStatusEnum } from '@/utils/constants' | 25 | import { SystemMenuTypeEnum, CommonStatusEnum } from '@/utils/constants' |
| 26 | import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' | 26 | import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' |
| 27 | import { useMessage } from '@/hooks/web/useMessage' | 27 | import { useMessage } from '@/hooks/web/useMessage' |
| 28 | +import { required } from '@/utils/formRules.js' | ||
| 28 | const message = useMessage() | 29 | const message = useMessage() |
| 29 | const { t } = useI18n() // 国际化 | 30 | const { t } = useI18n() // 国际化 |
| 30 | // ========== 创建菜单树结构 ========== | 31 | // ========== 创建菜单树结构 ========== |
| 31 | const loading = ref(true) | 32 | const loading = ref(true) |
| 32 | -const menuData = ref([]) // 树形结构 | 33 | +const menuData = ref<any[]>([]) // 树形结构 |
| 33 | const getList = async () => { | 34 | const getList = async () => { |
| 34 | const res = await MenuApi.getMenuListApi(queryParams) | 35 | const res = await MenuApi.getMenuListApi(queryParams) |
| 35 | menuData.value = handleTree(res) | 36 | menuData.value = handleTree(res) |
| @@ -44,7 +45,7 @@ const menuProps = { | @@ -44,7 +45,7 @@ const menuProps = { | ||
| 44 | const menuOptions = ref() // 树形结构 | 45 | const menuOptions = ref() // 树形结构 |
| 45 | const getTree = async () => { | 46 | const getTree = async () => { |
| 46 | const res = await MenuApi.listSimpleMenusApi() | 47 | const res = await MenuApi.listSimpleMenusApi() |
| 47 | - const menu = { id: 0, name: '主类目', children: [] } | 48 | + const menu = { id: 0, name: '主类目', children: [] as any[] } |
| 48 | menu.children = handleTree(res) | 49 | menu.children = handleTree(res) |
| 49 | console.info(menu) | 50 | console.info(menu) |
| 50 | menuOptions.value = menu | 51 | menuOptions.value = menu |
| @@ -85,12 +86,12 @@ const menuForm = ref<MenuVO>({ | @@ -85,12 +86,12 @@ const menuForm = ref<MenuVO>({ | ||
| 85 | createTime: '' | 86 | createTime: '' |
| 86 | }) | 87 | }) |
| 87 | // 表单校验 | 88 | // 表单校验 |
| 88 | -const rules = { | ||
| 89 | - name: [{ required: true, message: '菜单名称不能为空', trigger: 'blur' }], | ||
| 90 | - sort: [{ required: true, message: '菜单顺序不能为空', trigger: 'blur' }], | ||
| 91 | - path: [{ required: true, message: '路由地址不能为空', trigger: 'blur' }], | ||
| 92 | - status: [{ required: true, message: '状态不能为空', trigger: 'blur' }] | ||
| 93 | -} | 89 | +const rules = reactive({ |
| 90 | + name: [required], | ||
| 91 | + sort: [required], | ||
| 92 | + path: [required], | ||
| 93 | + status: [required] | ||
| 94 | +}) | ||
| 94 | // 设置标题 | 95 | // 设置标题 |
| 95 | const setDialogTile = (type: string) => { | 96 | const setDialogTile = (type: string) => { |
| 96 | dialogTitle.value = t('action.' + type) | 97 | dialogTitle.value = t('action.' + type) |
yudao-ui-admin-vue3/src/views/system/notice/notice.data.ts
| @@ -8,8 +8,7 @@ const { t } = useI18n() // 国际化 | @@ -8,8 +8,7 @@ const { t } = useI18n() // 国际化 | ||
| 8 | // 表单校验 | 8 | // 表单校验 |
| 9 | export const rules = reactive({ | 9 | export const rules = reactive({ |
| 10 | title: [required], | 10 | title: [required], |
| 11 | - type: [required], | ||
| 12 | - status: [required] | 11 | + type: [required] |
| 13 | }) | 12 | }) |
| 14 | 13 | ||
| 15 | // CrudSchema | 14 | // CrudSchema |
yudao-ui-admin-vue3/src/views/system/post/post.data.ts
| @@ -9,8 +9,7 @@ const { t } = useI18n() // 国际化 | @@ -9,8 +9,7 @@ const { t } = useI18n() // 国际化 | ||
| 9 | export const rules = reactive({ | 9 | export const rules = reactive({ |
| 10 | name: [required], | 10 | name: [required], |
| 11 | code: [required], | 11 | code: [required], |
| 12 | - sort: [required], | ||
| 13 | - status: [required] | 12 | + sort: [required] |
| 14 | }) | 13 | }) |
| 15 | 14 | ||
| 16 | // CrudSchema | 15 | // CrudSchema |
yudao-ui-admin-vue3/src/views/system/sms/smsTemplate/sms.template.data.ts
| @@ -8,13 +8,12 @@ const { t } = useI18n() // 国际化 | @@ -8,13 +8,12 @@ const { t } = useI18n() // 国际化 | ||
| 8 | // 表单校验 | 8 | // 表单校验 |
| 9 | export const rules = reactive({ | 9 | export const rules = reactive({ |
| 10 | type: [required], | 10 | type: [required], |
| 11 | + status: [required], | ||
| 12 | + code: [required], | ||
| 11 | name: [required], | 13 | name: [required], |
| 12 | content: [required], | 14 | content: [required], |
| 13 | apiTemplateId: [required], | 15 | apiTemplateId: [required], |
| 14 | - channelId: [required], | ||
| 15 | - code: [required], | ||
| 16 | - sort: [required], | ||
| 17 | - status: [required] | 16 | + channelId: [required] |
| 18 | }) | 17 | }) |
| 19 | 18 | ||
| 20 | // CrudSchema | 19 | // CrudSchema |
yudao-ui-admin-vue3/src/views/system/user/index.vue
| @@ -9,6 +9,7 @@ import { | @@ -9,6 +9,7 @@ import { | ||
| 9 | ElTreeSelect, | 9 | ElTreeSelect, |
| 10 | ElSelect, | 10 | ElSelect, |
| 11 | ElOption, | 11 | ElOption, |
| 12 | + ElTransfer, | ||
| 12 | ElForm, | 13 | ElForm, |
| 13 | ElFormItem, | 14 | ElFormItem, |
| 14 | ElUpload, | 15 | ElUpload, |
| @@ -62,7 +63,7 @@ const { getList, setSearchParams, delList, exportList } = methods | @@ -62,7 +63,7 @@ const { getList, setSearchParams, delList, exportList } = methods | ||
| 62 | 63 | ||
| 63 | // ========== 创建部门树结构 ========== | 64 | // ========== 创建部门树结构 ========== |
| 64 | const filterText = ref('') | 65 | const filterText = ref('') |
| 65 | -const deptOptions = ref([]) // 树形结构 | 66 | +const deptOptions = ref<any[]>([]) // 树形结构 |
| 66 | const searchForm = ref<FormExpose>() | 67 | const searchForm = ref<FormExpose>() |
| 67 | const treeRef = ref<InstanceType<typeof ElTree>>() | 68 | const treeRef = ref<InstanceType<typeof ElTree>>() |
| 68 | const getTree = async () => { | 69 | const getTree = async () => { |
| @@ -268,6 +269,7 @@ const handleFileSuccess = (response: any): void => { | @@ -268,6 +269,7 @@ const handleFileSuccess = (response: any): void => { | ||
| 268 | text += '< ' + username + ': ' + data.failureUsernames[username] + ' >' | 269 | text += '< ' + username + ': ' + data.failureUsernames[username] + ' >' |
| 269 | } | 270 | } |
| 270 | message.alert(text) | 271 | message.alert(text) |
| 272 | + getList() | ||
| 271 | } | 273 | } |
| 272 | // 文件数超出提示 | 274 | // 文件数超出提示 |
| 273 | const handleExceed = (): void => { | 275 | const handleExceed = (): void => { |
| @@ -281,8 +283,8 @@ const excelUploadError = (): void => { | @@ -281,8 +283,8 @@ const excelUploadError = (): void => { | ||
| 281 | onMounted(async () => { | 283 | onMounted(async () => { |
| 282 | await getTree() | 284 | await getTree() |
| 283 | await getPostOptions() | 285 | await getPostOptions() |
| 286 | + await getList() | ||
| 284 | }) | 287 | }) |
| 285 | -getList() | ||
| 286 | </script> | 288 | </script> |
| 287 | 289 | ||
| 288 | <template> | 290 | <template> |
| @@ -482,7 +484,7 @@ getList() | @@ -482,7 +484,7 @@ getList() | ||
| 482 | </template> | 484 | </template> |
| 483 | </Dialog> | 485 | </Dialog> |
| 484 | <!-- 分配用户角色 --> | 486 | <!-- 分配用户角色 --> |
| 485 | - <Dialog v-model="roleDialogVisible" title="分配角色"> | 487 | + <Dialog v-model="roleDialogVisible" title="分配角色" maxHeight="450px"> |
| 486 | <el-form :model="userRole" label-width="80px"> | 488 | <el-form :model="userRole" label-width="80px"> |
| 487 | <el-form-item label="用户名称"> | 489 | <el-form-item label="用户名称"> |
| 488 | <el-input v-model="userRole.username" :disabled="true" /> | 490 | <el-input v-model="userRole.username" :disabled="true" /> |
| @@ -491,14 +493,15 @@ getList() | @@ -491,14 +493,15 @@ getList() | ||
| 491 | <el-input v-model="userRole.nickname" :disabled="true" /> | 493 | <el-input v-model="userRole.nickname" :disabled="true" /> |
| 492 | </el-form-item> | 494 | </el-form-item> |
| 493 | <el-form-item label="角色"> | 495 | <el-form-item label="角色"> |
| 494 | - <el-select v-model="userRole.roleIds" multiple> | ||
| 495 | - <el-option | ||
| 496 | - v-for="item in roleOptions" | ||
| 497 | - :key="parseInt(item.id)" | ||
| 498 | - :label="item.name" | ||
| 499 | - :value="parseInt(item.id)" | ||
| 500 | - /> | ||
| 501 | - </el-select> | 496 | + <el-transfer |
| 497 | + v-model="userRole.roleIds" | ||
| 498 | + :titles="['角色列表', '已选择']" | ||
| 499 | + :props="{ | ||
| 500 | + key: 'id', | ||
| 501 | + label: 'name' | ||
| 502 | + }" | ||
| 503 | + :data="roleOptions" | ||
| 504 | + /> | ||
| 502 | </el-form-item> | 505 | </el-form-item> |
| 503 | </el-form> | 506 | </el-form> |
| 504 | <!-- 操作按钮 --> | 507 | <!-- 操作按钮 --> |
yudao-ui-admin-vue3/src/views/system/user/user.data.ts
| @@ -7,8 +7,18 @@ import { CrudSchema, useCrudSchemas } from '@/hooks/web/useCrudSchemas' | @@ -7,8 +7,18 @@ import { CrudSchema, useCrudSchemas } from '@/hooks/web/useCrudSchemas' | ||
| 7 | const { t } = useI18n() | 7 | const { t } = useI18n() |
| 8 | // 表单校验 | 8 | // 表单校验 |
| 9 | export const rules = reactive({ | 9 | export const rules = reactive({ |
| 10 | + username: [required], | ||
| 10 | nickname: [required], | 11 | nickname: [required], |
| 11 | - status: [required] | 12 | + email: [required], |
| 13 | + status: [required], | ||
| 14 | + mobile: [ | ||
| 15 | + { | ||
| 16 | + pattern: | ||
| 17 | + /^(?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[189]))\d{8}$/, | ||
| 18 | + trigger: 'blur', | ||
| 19 | + message: '请输入正确的手机号码' | ||
| 20 | + } | ||
| 21 | + ] | ||
| 12 | }) | 22 | }) |
| 13 | // crudSchemas | 23 | // crudSchemas |
| 14 | const crudSchemas = reactive<CrudSchema[]>([ | 24 | const crudSchemas = reactive<CrudSchema[]>([ |
yudao-ui-admin-vue3/use.md
0 → 100644
| 1 | +# 注意事项 | ||
| 2 | + | ||
| 3 | +- 项目路径请不要使用中文命名!!!会造成解析乱码!!!请使用全英文路径!!!全英文路径!!!全英文路径!!! | ||
| 4 | +- node >=16 , pnpm >=7,非node16+ pnpm 7+ 安装问题不予解决、不适配 | ||
| 5 | +- 开发建议使用 [谷歌浏览器-开发者版](https://www.google.cn/intl/zh-CN/chrome/dev/) 不支持 IE\QQ 等浏览器 | ||
| 6 | +- 本框架使用 TypeScript ,简称ts,和java的类型差不多,为了简化没过多使用 type | ||
| 7 | +- 本框架使用 Vue3.2 + setup语法糖,请自行学习相关内容 | ||
| 8 | +- [点击查看:为什么Vue3.2,什么是setup,Vite为什么第一次加载速度慢](https://www.baidu.com) | ||
| 9 | +- idea 怎么开发? 不知道。 | ||
| 10 | +- 启动方式详见[README.md](./README.md) | ||
| 11 | + | ||
| 12 | +## 简单使用 | ||
| 13 | + | ||
| 14 | +- 目录结构与 vue2 版本基本保持一致 | ||
| 15 | +- 一个页面(以post为例)由4部分组成 | ||
| 16 | + | ||
| 17 | +```bash | ||
| 18 | +/src/api/system/post/ [index.ts | types.ts] | ||
| 19 | +/src/views/system/post/ [index.vue | post.data.ts] | ||
| 20 | +``` | ||
| 21 | + | ||
| 22 | +- 其中api内index.ts 与 vue2 基本一致,只不过axios封装了get post put delete upload download 等方法,不用写method: 'get' 了 | ||
| 23 | +- api内types.ts,是接口中的类型声明,与java中vo等保持一致, java中long int => ts 中 number | ||
| 24 | +- views中,index.vue 与 vue2 基本一致,本框架封装了Search Table Form Descriptions等组件,也可以按照vue2方式去写,参考menu | ||
| 25 | +- post.data.ts 中主要是表单校验 rules 和表单 crudSchemas ,通过修改crudSchemas 就可以控制增删改查的字段、输入框还是下拉框等等 | ||
| 26 | +- 本框架集成了国际化,不需要可以自己想办法移除,后期不会提供删减版 使用方式 | ||
| 27 | + | ||
| 28 | +```bash | ||
| 29 | +import { useI18n } from '@/hooks/web/useI18n' | ||
| 30 | +const { t } = useI18n() | ||
| 31 | +t('common.createTime') | ||
| 32 | +对应翻译文档在 src/locales | ||
| 33 | +``` |
yudao-ui-admin-vue3/vite.config.ts
| @@ -138,6 +138,7 @@ export default ({ command, mode }: ConfigEnv): UserConfig => { | @@ -138,6 +138,7 @@ export default ({ command, mode }: ConfigEnv): UserConfig => { | ||
| 138 | 'vue-router', | 138 | 'vue-router', |
| 139 | 'vue-types', | 139 | 'vue-types', |
| 140 | 'vue-i18n', | 140 | 'vue-i18n', |
| 141 | + 'element-plus/es', | ||
| 141 | 'element-plus/es/locale/lang/zh-cn', | 142 | 'element-plus/es/locale/lang/zh-cn', |
| 142 | 'element-plus/es/locale/lang/en', | 143 | 'element-plus/es/locale/lang/en', |
| 143 | '@iconify/iconify', | 144 | '@iconify/iconify', |
yudao-ui-admin/src/views/system/dept/index.vue
| @@ -167,7 +167,7 @@ export default { | @@ -167,7 +167,7 @@ export default { | ||
| 167 | ], | 167 | ], |
| 168 | phone: [ | 168 | phone: [ |
| 169 | { | 169 | { |
| 170 | - pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, | 170 | + pattern: /^(?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[189]))\d{8}$/, |
| 171 | message: "请输入正确的手机号码", | 171 | message: "请输入正确的手机号码", |
| 172 | trigger: "blur" | 172 | trigger: "blur" |
| 173 | } | 173 | } |
yudao-ui-admin/src/views/system/tenant/index.vue
| @@ -183,8 +183,6 @@ export default { | @@ -183,8 +183,6 @@ export default { | ||
| 183 | accountCount: [{ required: true, message: "账号额度不能为空", trigger: "blur" }], | 183 | accountCount: [{ required: true, message: "账号额度不能为空", trigger: "blur" }], |
| 184 | expireTime: [{ required: true, message: "过期时间不能为空", trigger: "blur" }], | 184 | expireTime: [{ required: true, message: "过期时间不能为空", trigger: "blur" }], |
| 185 | domain: [{ required: true, message: "绑定域名不能为空", trigger: "blur" }], | 185 | domain: [{ required: true, message: "绑定域名不能为空", trigger: "blur" }], |
| 186 | - username: [{ required: true, message: "用户名称不能为空", trigger: "blur" }], | ||
| 187 | - password: [{ required: true, message: "用户密码不能为空", trigger: "blur" }], | ||
| 188 | } | 186 | } |
| 189 | }; | 187 | }; |
| 190 | }, | 188 | }, |