@@ -21,6 +21,7 @@ function deepClone(source) { | |||
const menuList = [] | |||
const userList = [] | |||
// const deptList = [] | |||
const count = 100 | |||
for (let i = 0; i < count; i++) { | |||
@@ -48,7 +49,84 @@ for (let i = 0; i < count; i++) { | |||
createTime: '@datetime', | |||
updateTime: '@datetime' | |||
})) | |||
// deptList.push(Mock.mock({ | |||
// code: '', | |||
// id: 1, | |||
// name: '@name', | |||
// fullname: '@cname', | |||
// 'pid|1': [1, 2, 3, 4, 5], | |||
// 'sort|+1': 0, | |||
// type: 1, | |||
// 'note|1-8': '好', | |||
// createTime: '@datetime', | |||
// updateTime: '@datetime' | |||
// })) | |||
} | |||
const deptList = Mock.mock({ | |||
code: 0, | |||
message: '获取成功', | |||
type: 'success', | |||
data: [{ | |||
code: 'XH212313', | |||
id: 1, | |||
name: '@name', | |||
fullname: '@cname', | |||
pid: 0, | |||
sort: 0, | |||
type: 1, | |||
'note|1-8': '好', | |||
createTime: '@datetime', | |||
updateTime: '@datetime' | |||
}, | |||
{ | |||
code: 'XH212312', | |||
id: 2, | |||
name: '@name', | |||
fullname: '@cname', | |||
pid: 1, | |||
sort: 0, | |||
type: 2, | |||
'note|1-8': '好', | |||
createTime: '@datetime', | |||
updateTime: '@datetime' | |||
}, | |||
{ | |||
code: 'XH212323', | |||
id: 3, | |||
name: '@name', | |||
fullname: '@cname', | |||
pid: 2, | |||
sort: 0, | |||
type: 2, | |||
'note|1-8': '好', | |||
createTime: '@datetime', | |||
updateTime: '@datetime' | |||
}, | |||
{ | |||
code: 'XH212319', | |||
id: 4, | |||
name: '@name', | |||
fullname: '@cname', | |||
pid: 0, | |||
sort: 1, | |||
type: 1, | |||
'note|1-8': '好', | |||
createTime: '@datetime', | |||
updateTime: '@datetime' | |||
}, | |||
{ | |||
code: 'XH212398', | |||
id: 5, | |||
name: '@name', | |||
fullname: '@cname', | |||
pid: 0, | |||
sort: 2, | |||
type: 2, | |||
'note|1-8': '好', | |||
createTime: '@datetime', | |||
updateTime: '@datetime' | |||
}] | |||
}) | |||
export default [ | |||
{ | |||
@@ -84,5 +162,18 @@ export default [ | |||
const List = mockList.filter((item, index) => index < limit * page && index >= limit * (page - 1)) | |||
return resultSuccess(List) | |||
} | |||
}, | |||
{ | |||
url: '/api-mock/dept/apiIndex', | |||
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 | |||
} | |||
} | |||
] |
@@ -31,6 +31,14 @@ const asyncRoutes = [ | |||
meta: { | |||
title: '角色管理' | |||
} | |||
}, | |||
{ | |||
path: 'dept', | |||
component: 'views/system/dept/index', | |||
name: 'SystemDept', | |||
meta: { | |||
title: '部门管理' | |||
} | |||
} | |||
] | |||
} |
@@ -0,0 +1,59 @@ | |||
import { mockAxios as request } from '@/utils/http' | |||
/** | |||
* 获取部门分页数据接口 | |||
* @returns 部门分页 | |||
*/ | |||
export function getDeptList(params) { | |||
return request({ | |||
url: '/dept/index', | |||
method: 'GET', | |||
params | |||
}) | |||
} | |||
/** | |||
* 获取部门全部数据接口 | |||
* @returns 部门全部数据 | |||
*/ | |||
export function getDeptAll(params) { | |||
return request({ | |||
url: '/dept/getDeptList', | |||
method: 'GET', | |||
params | |||
}) | |||
} | |||
/** | |||
* 添加部门 | |||
* params | |||
*/ | |||
export function addDept(data) { | |||
return request({ | |||
url: '/dept/add', | |||
method: 'POST', | |||
data | |||
}) | |||
} | |||
/** | |||
* 编辑部门 | |||
* params | |||
*/ | |||
export function editDept(data) { | |||
return request({ | |||
url: '/dept/edit', | |||
method: 'PUT', | |||
data | |||
}) | |||
} | |||
/** | |||
* 删除部门 | |||
* params | |||
*/ | |||
export function deleteDept(id) { | |||
return request({ | |||
url: `/dept/delete${[id]}`, | |||
method: 'DELETE' | |||
}) | |||
} |
@@ -21,3 +21,11 @@ export function getUserList(params) { | |||
params | |||
}) | |||
} | |||
export function getDeptList(params) { | |||
return request({ | |||
url: '/dept/apiIndex', | |||
method: 'GET', | |||
params | |||
}) | |||
} |
@@ -0,0 +1,59 @@ | |||
import { mockAxios as request } from '@/utils/http' | |||
/** | |||
* 获取用户分页数据接口 | |||
* @returns 用户分页 | |||
*/ | |||
export function getUserList(params) { | |||
return request({ | |||
url: '/user/index', | |||
method: 'GET', | |||
params | |||
}) | |||
} | |||
/** | |||
* 添加用户 | |||
* params | |||
*/ | |||
export function addUser(data) { | |||
return request({ | |||
url: '/user/add', | |||
method: 'POST', | |||
data | |||
}) | |||
} | |||
/** | |||
* 编辑部门 | |||
* params | |||
*/ | |||
export function editUser(data) { | |||
return request({ | |||
url: '/user/edit', | |||
method: 'PUT', | |||
data | |||
}) | |||
} | |||
/** | |||
* 删除用户 | |||
* params | |||
*/ | |||
export function deleteUser(id) { | |||
return request({ | |||
url: `/user/delete${[id]}`, | |||
method: 'DELETE' | |||
}) | |||
} | |||
/** | |||
* 设置用户状态 | |||
* params | |||
*/ | |||
export function setUserStatus(data) { | |||
return request({ | |||
url: '/user/status', | |||
method: 'PUT', | |||
data | |||
}) | |||
} |
@@ -31,7 +31,6 @@ export default { | |||
...unref(props) | |||
} | |||
}) | |||
console.log(getBindProps) | |||
return { | |||
getBindProps | |||
} |
@@ -0,0 +1,109 @@ | |||
/** | |||
* 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 | |||
} | |||
/** | |||
* 遍历children形式数据 | |||
* @param data 需要遍历的数组 | |||
* @param callback 回调 | |||
* @param childKey children字段名 | |||
*/ | |||
export function eachTreeData(data, callback, childKey = 'children') { | |||
if (!data || !data.length) { | |||
return | |||
} | |||
data.forEach((d) => { | |||
if (callback(d) !== false && d[childKey]) { | |||
eachTreeData(d[childKey], callback, childKey) | |||
} | |||
}) | |||
} | |||
/** | |||
* 处理树形数据 | |||
* @param data 需要处理的数据 | |||
* @param formatter 处理器 | |||
* @param childKey children字段名 | |||
* @returns {[]} 处理后的数据 | |||
*/ | |||
export function formatTreeData(data, formatter, childKey = 'children') { | |||
const result = [] | |||
if (data && data.length) { | |||
data.forEach((d) => { | |||
const item = formatter(d) | |||
if (item !== false) { | |||
if (item[childKey]) { | |||
item[childKey] = formatTreeData(item[childKey], formatter, childKey) | |||
} | |||
result.push(item) | |||
} | |||
}) | |||
} | |||
return result | |||
} |
@@ -1,5 +1,5 @@ | |||
import { router } from '@/router' | |||
import { getToken, removeToken } from '@/utils/token' | |||
import { getToken } from '@/utils/token' | |||
import { isWithoutToken } from './help' | |||
export function setupInterceptor(service) { | |||
@@ -48,35 +48,35 @@ export function setupInterceptor(service) { | |||
/** | |||
* 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: '接口异常,请稍后重试!' }) | |||
} | |||
// 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: '接口异常,请稍后重试!' }) | |||
// } | |||
} | |||
) | |||
} |
@@ -0,0 +1,147 @@ | |||
<template> | |||
<div> | |||
<data-table :columns="data.columns" :data="data.data" :pagination="data.pagination" size="large" scroll-x="1200"> | |||
<template #tableTitle> | |||
<n-button type="primary"> | |||
新建 | |||
</n-button> | |||
<n-button type="primary"> | |||
删除 | |||
</n-button> | |||
</template> | |||
</data-table> | |||
</div> | |||
</template> | |||
<script> | |||
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 { reactive } from 'vue' | |||
import { toTreeData } from '@/utils/handleData.js' | |||
export default { | |||
name: 'MenuPage', | |||
components: { dataTable }, | |||
setup() { | |||
const data = reactive({ | |||
columns: [ | |||
{ | |||
title: '部门编号', | |||
key: 'code', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '部门名称', | |||
key: 'name', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '部门全称', | |||
key: 'fullname', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '部门类型', | |||
key: 'type', | |||
align: 'center', | |||
width: 100 | |||
}, | |||
{ | |||
title: '排序', | |||
key: 'sort', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '备注', | |||
key: 'note', | |||
align: 'center', | |||
width: 100 | |||
}, | |||
{ | |||
title: '创建时间', | |||
key: 'createTime', | |||
align: 'center', | |||
width: 160 | |||
}, | |||
{ | |||
title: '更新时间', | |||
key: 'updateTime', | |||
align: 'center', | |||
width: 160 | |||
}, | |||
{ | |||
title: '操作', | |||
align: 'center', | |||
width: 150, | |||
fixed: 'right', | |||
render(row) { | |||
return h(TableAction, { | |||
actions: [ | |||
{ | |||
label: '添加', | |||
type: 'button', | |||
props: { | |||
type: 'primary', | |||
onClick: play.bind(null, row) | |||
}, | |||
auth: 'basic_list' | |||
}, | |||
{ | |||
label: '修改', | |||
auth: 'basic_list' | |||
}, | |||
{ | |||
label: '删除', | |||
type: 'popconfirm', | |||
auth: 'basic_list' | |||
} | |||
], | |||
align: 'center' | |||
}) | |||
} | |||
} | |||
], | |||
data: [], | |||
pagination: { | |||
pageSize: 10 | |||
} | |||
}) | |||
function play(row) { | |||
console.log(row) | |||
} | |||
/** | |||
* @description: 获取部门数据并做树形结构处理 | |||
* @return {*} | |||
*/ | |||
async function fetchList() { | |||
const params = { | |||
page: 1, | |||
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 | |||
} | |||
onMounted(() => { | |||
fetchList() | |||
}) | |||
return { data } | |||
} | |||
} | |||
</script> | |||
<style scoped lang='scss'> | |||
.n-button+.n-button{ | |||
margin-left: 10px; | |||
} | |||
</style> |