From 1340da6853c649d2339825c3967c8b64854df83e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=99=E8=8F=B2?= <1622041228@qq.com> Date: Mon, 23 May 2022 10:52:21 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=AF=E7=94=A8=E6=AD=A3=E5=BC=8F=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.development | 2 +- .env.localhost | 2 +- mock/system/index.js | 14 +-- package-lock.json | 11 +++ package.json | 2 +- src/api/auth/index.js | 4 +- src/api/login/index.js | 23 ++++- src/api/post/index.js | 39 -------- src/api/system/dept/index.js | 2 +- src/api/system/index.js | 2 +- src/api/system/menu/index.js | 59 ++++++++++++ src/api/system/role/index.js | 95 +++++++++++++++++++ src/api/system/user/index.js | 14 ++- src/api/user/index.js | 10 +- src/components/DataTable/tools/toTree.js | 69 ++++++++++++++ .../DataTable/tools/useDataSource.js | 10 +- src/utils/http/interceptors.js | 64 ++++++------- src/views/system/dept/index.vue | 56 ++++++----- src/views/system/role/index.vue | 27 +++--- src/views/system/user/index.vue | 50 ++++++---- 20 files changed, 410 insertions(+), 145 deletions(-) delete mode 100644 src/api/post/index.js create mode 100644 src/api/system/menu/index.js create mode 100644 src/api/system/role/index.js create mode 100644 src/components/DataTable/tools/toTree.js diff --git a/.env.development b/.env.development index 0bb782a..b6a3143 100644 --- a/.env.development +++ b/.env.development @@ -5,7 +5,7 @@ VITE_PUBLIC_PATH = '/' VITE_APP_USE_MOCK = false # proxy -VITE_PROXY = [["/api-dev","http://127.0.0.1:8002/api"]] +VITE_PROXY = [["/api-dev","http://192.168.11.11:9070/api"]] # base api VITE_APP_GLOB_BASE_API = '/api-dev' \ No newline at end of file diff --git a/.env.localhost b/.env.localhost index 1104cf0..b919d0f 100644 --- a/.env.localhost +++ b/.env.localhost @@ -2,7 +2,7 @@ VITE_PUBLIC_PATH = '/' # 是否启用MOCK -VITE_APP_USE_MOCK = true +VITE_APP_USE_MOCK = false # proxy VITE_PROXY = [["/api-local","http://127.0.0.1:8002/api"],["/api-mock","http://127.0.0.1:8003"]] diff --git a/mock/system/index.js b/mock/system/index.js index ee8c231..365e488 100644 --- a/mock/system/index.js +++ b/mock/system/index.js @@ -174,12 +174,14 @@ export default [ timeout: 1000, method: 'get', response: config => { - // const { page = 1, limit = 10 } = config.query - // const mockList = deptList.filter(item => { - // return true - // }) - // const List = mockList.filter((item, index) => index < limit * page && index >= limit * (page - 1)) - return deptList + const { page = 1, limit = 10 } = config.query + const data = { + list: deptList, + page: Number(page), + limit: Number(limit), + total: 5 + } + return resultSuccess(data) } } ] diff --git a/package-lock.json b/package-lock.json index ad9563a..78c5eaf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "@vicons/antd": "^0.10.0", "@vicons/ionicons5": "^0.10.0", "axios": "^0.26.1", + "dayjs": "^1.11.2", "mockjs": "^1.1.0", "pinia": "^2.0.13", "vue": "^3.2.16", @@ -3533,6 +3534,11 @@ "date-fns": ">=2.0.0" } }, + "node_modules/dayjs": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.2.tgz", + "integrity": "sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw==" + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -14042,6 +14048,11 @@ "dev": true, "requires": {} }, + "dayjs": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.2.tgz", + "integrity": "sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw==" + }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", diff --git a/package.json b/package.json index 6e263dc..80b8df6 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "@vicons/antd": "^0.10.0", "@vicons/ionicons5": "^0.10.0", "axios": "^0.26.1", - "dayjs": "^1.11.0", + "dayjs": "^1.11.2", "mockjs": "^1.1.0", "pinia": "^2.0.13", "vue": "^3.2.16", diff --git a/src/api/auth/index.js b/src/api/auth/index.js index 74c6082..0e9a3f5 100644 --- a/src/api/auth/index.js +++ b/src/api/auth/index.js @@ -4,13 +4,13 @@ export const login = (data) => { return request({ url: '/auth/login', method: 'post', - data, + data }) } export const refreshToken = () => { return request({ url: '/auth/refreshToken', - method: 'post', + method: 'post' }) } diff --git a/src/api/login/index.js b/src/api/login/index.js index bbfa1bd..ad84212 100644 --- a/src/api/login/index.js +++ b/src/api/login/index.js @@ -1,5 +1,10 @@ -import { mockAxios as request } from '@/utils/http' +import { defAxios as request } from '@/utils/http' +/** + * 登录接口 + * @param {Object} 用户名以及密码 + * @returns 返回token信息 + */ export function userLogin(data = {}) { return request({ url: '/login/login', @@ -7,9 +12,25 @@ export function userLogin(data = {}) { data }) } + +/** + * 获取验证码 + * @returns 验证码图片 + */ export function userCaptcha() { return request({ url: '/login/captcha', method: 'get' }) } + +/** + * 退出登录 + * @returns + */ +export function loginOut() { + return request({ + url: '/login/logout', + method: 'GET' + }) +} diff --git a/src/api/post/index.js b/src/api/post/index.js deleted file mode 100644 index e06f12b..0000000 --- a/src/api/post/index.js +++ /dev/null @@ -1,39 +0,0 @@ -import { defAxios as request } from '@/utils/http' - -export function getPosts(data = {}) { - return request({ - url: '/posts', - method: 'get', - data, - }) -} - -export function getPostById({ id }) { - return request({ - url: `/post/${id}`, - method: 'get', - }) -} - -export function savePost(id, data = {}) { - if (id) { - return request({ - url: `/post/${id}`, - method: 'put', - data, - }) - } - - return request({ - url: '/post', - method: 'post', - data, - }) -} - -export function deletePost(id) { - return request({ - url: `/post/${id}`, - method: 'delete', - }) -} diff --git a/src/api/system/dept/index.js b/src/api/system/dept/index.js index cd74c18..1570eaf 100644 --- a/src/api/system/dept/index.js +++ b/src/api/system/dept/index.js @@ -1,4 +1,4 @@ -import { mockAxios as request } from '@/utils/http' +import { defAxios as request } from '@/utils/http' /** * 获取部门分页数据接口 * @returns 部门分页 diff --git a/src/api/system/index.js b/src/api/system/index.js index 1d4c274..964398f 100644 --- a/src/api/system/index.js +++ b/src/api/system/index.js @@ -1,4 +1,4 @@ -import { mockAxios as request } from '@/utils/http' +import { defAxios as request } from '@/utils/http' export function getMenu() { return request({ diff --git a/src/api/system/menu/index.js b/src/api/system/menu/index.js new file mode 100644 index 0000000..6854bb6 --- /dev/null +++ b/src/api/system/menu/index.js @@ -0,0 +1,59 @@ +import { defAxios as request } from '@/utils/http' +/** + * 获取菜单分页数据接口 + * @returns 菜单分页数据 + */ +export function getMenuList(params) { + return request({ + url: '/menu/index', + method: 'GET', + params + }) +} + +/** + * 获取菜单全部数据接口 + * @returns 菜单全部数据 + */ +export function getMenu(params) { + return request({ + url: '/menu/getMenuAll', + method: 'GET', + params + }) +} + +/** + * 添加菜单 + * params + */ +export function addMenu(data) { + return request({ + url: '/menu/add', + method: 'POST', + data + }) +} + +/** + * 编辑菜单 + * params + */ +export function editMenu(data) { + return request({ + url: '/menu/edit', + method: 'PUT', + data + }) +} + +/** + * 删除菜单 + * params + */ +export function deleteMenu(id) { + return request({ + url: `/menu/delete${[id]}`, + method: 'DELETE' + }) +} diff --git a/src/api/system/role/index.js b/src/api/system/role/index.js new file mode 100644 index 0000000..421e1a3 --- /dev/null +++ b/src/api/system/role/index.js @@ -0,0 +1,95 @@ +import { defAxios as request } from '@/utils/http' +/** + * 获取角色分页数据接口 + * @returns 角色分页数据 + */ +export function getRoleList(params) { + return request({ + url: '/role/index', + method: 'GET', + params + }) +} + +/** + * 获取角色全部数据接口 + * @returns 角色全部数据 + */ +export function getRoleAll(params) { + return request({ + url: '/role/getRoleList', + method: 'GET', + params + }) +} + +/** + * 添加角色 + * params + */ +export function addRole(data) { + return request({ + url: '/role/add', + method: 'POST', + data + }) +} + +/** + * 编辑角色 + * params + */ +export function editRole(data) { + return request({ + url: '/role/edit', + method: 'PUT', + data + }) +} + +/** + * 设置角色状态 + * params + */ +export function setRoleStatus(data) { + return request({ + url: '/role/status', + method: 'PUT', + data + }) +} + +/** + * 删除角色 + * params + */ +export function deleteRole(id) { + return request({ + url: `/role/delete${[id]}`, + method: 'DELETE' + }) +} + +/** + * 获取角色权限数据 + * @param 角色id + * @returns 角色全部权限数据 + */ +export function getRolePermission(id) { + return request({ + url: `/role/getPermissionList/${id}`, + method: 'GET' + }) +} + +/** + * 保存角色权限信息 + * params + */ +export function savePermission(data) { + return request({ + url: '/role/savePermission', + method: 'POST', + data + }) +} diff --git a/src/api/system/user/index.js b/src/api/system/user/index.js index d2ed140..6707513 100644 --- a/src/api/system/user/index.js +++ b/src/api/system/user/index.js @@ -1,4 +1,4 @@ -import { mockAxios as request } from '@/utils/http' +import { defAxios as request } from '@/utils/http' /** * 获取用户分页数据接口 * @returns 用户分页 @@ -57,3 +57,15 @@ export function setUserStatus(data) { data }) } + +/** + * 重置用户密码 + * params + */ +export function resetPassword(data) { + return request({ + url: '/user/resetPwd', + method: 'PUT', + data + }) +} diff --git a/src/api/user/index.js b/src/api/user/index.js index 55c7c5f..7704ca4 100644 --- a/src/api/user/index.js +++ b/src/api/user/index.js @@ -4,7 +4,7 @@ export function getUsers(data = {}) { return request({ url: '/users', method: 'get', - data, + data }) } @@ -12,12 +12,12 @@ export function getUser(id) { if (id) { return request({ url: `/user/${id}`, - method: 'get', + method: 'get' }) } return request({ url: '/user', - method: 'get', + method: 'get' }) } @@ -26,13 +26,13 @@ export function saveUser(data = {}, id) { return request({ url: '/user', method: 'put', - data, + data }) } return request({ url: `/user/${id}`, method: 'put', - data, + data }) } diff --git a/src/components/DataTable/tools/toTree.js b/src/components/DataTable/tools/toTree.js new file mode 100644 index 0000000..65888c3 --- /dev/null +++ b/src/components/DataTable/tools/toTree.js @@ -0,0 +1,69 @@ +/** + * pid形式数据转children形式 + * @param data 需要转换的数组 + * @param idKey id字段名 + * @param pidKey pid字段名 + * @param childKey 生成的children字段名 + * @param pid 顶级的pid + * @param addPIds 是否添加所有父级id的字段 + * @param parentsKey 所有父级id的字段名称,默认parentIds + * @param parentIds 所有父级id + * @returns {[]} + */ +export function toTreeData(data, idKey, pidKey, childKey, pid, addPIds, parentsKey, parentIds) { + if (typeof data === 'object' && !Array.isArray(data)) { + idKey = data.idKey + pidKey = data.pidKey + childKey = data.childKey + pid = data.pid + addPIds = data.addPIds + parentsKey = data.parentsKey + parentIds = data.parentIds + data = data.data + } + if (!childKey) { + childKey = 'children' + } + if (typeof pid === 'undefined') { + pid = [] + data.forEach((d) => { + let flag = true + for (let i = 0; i < data.length; i++) { + if (d[pidKey] === data[i][idKey]) { + flag = false + break + } + } + if (flag) { + pid.push(d[pidKey]) + } + }) + } + const result = [] + data.forEach((d) => { + if (d[idKey] === d[pidKey]) { + console.error('data error: ', d) + return + } + if (Array.isArray(pid) ? (pid.indexOf(d[pidKey]) !== -1) : (d[pidKey] === pid)) { + const children = toTreeData({ + data: data, + idKey: idKey, + pidKey: pidKey, + childKey: childKey, + pid: d[idKey], + addPIds: addPIds, + parentsKey: parentsKey, + parentIds: (parentIds || []).concat([d[idKey]]) + }) + if (children.length > 0) { + d[childKey] = children + } + if (addPIds) { + d[parentsKey || 'parentIds'] = parentIds || [] + } + result.push(d) + } + }) + return result +} diff --git a/src/components/DataTable/tools/useDataSource.js b/src/components/DataTable/tools/useDataSource.js index 9df01d8..acc77af 100644 --- a/src/components/DataTable/tools/useDataSource.js +++ b/src/components/DataTable/tools/useDataSource.js @@ -1,5 +1,6 @@ import { ref, unref, computed, onMounted } from 'vue' import { isBoolean } from '@/utils/is' +import { toTreeData } from './toTree' export function useDataSource(propsRef, { getPaginationInfo, setPagination, setLoading, tableData }, emit) { const dataSourceRef = ref([]) @@ -42,6 +43,7 @@ export function useDataSource(propsRef, { getPaginationInfo, setPagination, setL fetch(opt) } } + // 处理数据结构 const resultInfo = res[listField] ? res[listField] : [] dataSourceRef.value = dataType === 'tree' ? dealTree(resultInfo) : resultInfo setPagination({ @@ -67,8 +69,12 @@ export function useDataSource(propsRef, { getPaginationInfo, setPagination, setL } } - function dealTree() { - const tree = [] + /** + * 递归遍历数据处理成树形结构 + * @returns 返回树形结构数据 + */ + function dealTree(info) { + const tree = toTreeData(info.data, 'id', 'pid', 'children') return tree } diff --git a/src/utils/http/interceptors.js b/src/utils/http/interceptors.js index 8e3e573..4f99d12 100644 --- a/src/utils/http/interceptors.js +++ b/src/utils/http/interceptors.js @@ -1,5 +1,5 @@ import { router } from '@/router' -import { getToken } from '@/utils/token' +import { getToken, removeToken } from '@/utils/token' import { isWithoutToken } from './help' export function setupInterceptor(service) { @@ -21,7 +21,7 @@ export function setupInterceptor(service) { * * jwt token * ! 认证方案: Bearer */ - config.headers.Authorization = 'Bearer ' + token + config.headers.Authorization = token return config } @@ -43,40 +43,40 @@ export function setupInterceptor(service) { (response) => response?.data, (error) => { const { code, message } = error.response?.data - return Promise.reject({ code, message }) + // return Promise.reject({ code, message }) /** * TODO 此处可以根据后端返回的错误码自定义框架层面的错误处理 */ - // switch (code) { - // case 401: - // // 未登录(可能是token过期或者无效了) - // console.error(message) - // removeToken() - // const { currentRoute } = router - // router.replace({ - // path: '/login', - // query: { ...currentRoute.query, redirect: currentRoute.path } - // }) - // break - // case 403: - // // 没有权限 - // console.error(message) - // break - // case 404: - // // 资源不存在 - // console.error(message) - // break - // default: - // break - // } - // // 已知错误resolve,在业务代码中作提醒,未知错误reject,捕获错误统一提示接口异常(9000以上为业务类型错误,需要跟后端确定好) - // if ([401, 403, 404].includes(code) || code >= 9000) { - // return Promise.resolve({ code, message }) - // } else { - // console.error('【err】' + error) - // return Promise.reject({ message: '接口异常,请稍后重试!' }) - // } + // const { currentRoute } = router + switch (code) { + case 401: + // 未登录(可能是token过期或者无效了) + console.error(message) + removeToken() + router.replace({ + path: '/login' + // query: { ...currentRoute.query, redirect: currentRoute.path } + }) + break + case 403: + // 没有权限 + console.error(message) + break + case 404: + // 资源不存在 + console.error(message) + break + default: + break + } + // 已知错误resolve,在业务代码中作提醒,未知错误reject,捕获错误统一提示接口异常(9000以上为业务类型错误,需要跟后端确定好) + if ([401, 403, 404].includes(code) || code >= 9000) { + return Promise.resolve({ code, message }) + } else { + console.error('【err】' + error) + return Promise.reject({ message: '接口异常,请稍后重试!' }) + } } ) } diff --git a/src/views/system/dept/index.vue b/src/views/system/dept/index.vue index 4cf8c67..b1a85cb 100644 --- a/src/views/system/dept/index.vue +++ b/src/views/system/dept/index.vue @@ -1,16 +1,22 @@ @@ -18,9 +24,8 @@ import dataTable from '@/components/DataTable/index.vue' import TableAction from '@/components/DataTable/tools/Action.vue' import { getDeptList } from '@/api/system/index.js' -import { h, onMounted } from 'vue' +import { h, onMounted, unref } from 'vue' import { reactive } from 'vue' -import { toTreeData } from '@/utils/handleData.js' export default { name: 'MenuPage', components: { dataTable }, @@ -52,7 +57,6 @@ export default { title: '排序', key: 'sort', align: 'center' - }, { title: '备注', @@ -124,24 +128,30 @@ export default { limit: 10 } const res = await getDeptList(params) - const dataList = toTreeData(res.data.map(d => { - d.index = d.id - return d - }), 'id', 'pid') - data.data = dataList + data.data = res.data + } + const params = reactive({ + name: 'xiaoMa' + }) + + const loadDataTable = async(res) => { + const _params = { + ...unref(params), + ...res + } + return await getDeptList(_params) } onMounted(() => { fetchList() }) - return { data } + return { data, loadDataTable } } } - diff --git a/src/views/system/role/index.vue b/src/views/system/role/index.vue index c1d72a4..88688df 100644 --- a/src/views/system/role/index.vue +++ b/src/views/system/role/index.vue @@ -37,7 +37,8 @@ export default { { title: '用户编号', key: 'code', - align: 'center' + align: 'center', + minWidth: 80 }, { title: '头像', @@ -51,52 +52,56 @@ export default { src: row.avatar } }) - } + }, + minWidth: 80 }, { title: '用户账号', key: 'username', - align: 'center' + align: 'center', + minWidth: 80 }, { title: '用户姓名', key: 'realname', - align: 'center' + align: 'center', + minWidth: 80 }, { title: '用户类型', key: 'type', align: 'center', - width: 100 + minWidth: 80 }, { title: '角色', key: 'roles', - align: 'center' - + align: 'center', + minWidth: 100 }, { title: '状态', key: 'status', align: 'center', - width: 100 + minWidth: 80 }, { title: '部门', key: 'deptName', - align: 'center' + align: 'center', + minWidth: 120 }, { title: '创建时间', key: 'createTime', align: 'center', - width: 160 + minWidth: 160 }, { title: '更新时间', key: 'updateTime', align: 'center', - width: 160 + minWidth: 160 }, { title: '操作', diff --git a/src/views/system/user/index.vue b/src/views/system/user/index.vue index 745a9ae..10f1fda 100644 --- a/src/views/system/user/index.vue +++ b/src/views/system/user/index.vue @@ -1,16 +1,21 @@ @@ -18,8 +23,8 @@ import dataTable from '@/components/DataTable/index.vue' import TableAction from '@/components/DataTable/tools/Action.vue' import TableImage from '@/components/DataTable/tools/Image.vue' -import { getUserList } from '@/api/system/index.js' -import { h, onMounted } from 'vue' +import { getUserList } from '@/api/system/user/index.js' +import { h, onMounted, unref } from 'vue' import { reactive } from 'vue' export default { name: 'MenuPage', @@ -66,7 +71,6 @@ export default { title: '角色', key: 'roles', align: 'center' - }, { title: '状态', @@ -146,17 +150,27 @@ export default { data.data = res.data } + const params = reactive({ + name: 'xiaoMa' + }) + + const loadDataTable = async(res) => { + const _params = { + ...unref(params), + ...res + } + return await getUserList(_params) + } onMounted(() => { fetchList() }) - return { data } + return { data, loadDataTable } } } -