完成部门

main
expressgy 3 months ago
parent e0ca17a4b7
commit ee4759268b
  1. 2
      .env
  2. 98
      src/api/Auth/AuthDept/index.js
  3. 3
      src/api/index.js
  4. 4
      src/components/AntDesignVue/CustomAntDesignVue/TableColumChoose/index.vue
  5. 5
      src/components/AntDesignVue/index.js
  6. 9
      src/router/index.js
  7. 81
      src/stores/baseData.js
  8. 221
      src/views/Auth/Dept/DataModal.js
  9. 113
      src/views/Auth/Dept/DeptForm.vue
  10. 259
      src/views/Auth/Dept/DeptPage.vue
  11. 90
      src/views/Auth/Dept/DeptTable.vue
  12. 34
      src/views/Auth/Dept/DeptTree.vue
  13. 3
      src/views/Auth/Menu/MenuPage.vue
  14. 14
      src/views/Auth/Role/RolePage.vue

@ -1,4 +1,4 @@
VITE_HOME_REDIRECT = '/menu' # 默认路由
VITE_HOME_REDIRECT = '/dept' # 默认路由
VITE_TITLE = '星撰玉衡' # 项目名称
VITE_BASE_URL = '/api' # 请求默认前缀
VITE_HTTP_TIMEOUT = 30000

@ -0,0 +1,98 @@
// | ------------------------------------------------------------
// | @版本: version 0.1
// | @创建人: 【Nie-x7129】
// | @E-mail: x71291@outlook.com
// | @所在项目: hoto-auth-vue3
// | @文件描述: index.js -
// | @创建时间: 2024-07-12 10:45
// | @更新时间: 2024-07-12 10:45
// | @修改记录:
// | -*-*-*- (时间--修改人--修改说明) -*-*-*-
// | =
// | ------------------------------------------------------------
import HTTP from '@/api/http.js';
import { PageData } from '@utils/DefaultData.js';
export const AuthDept = {
/**
* Name: createDept
* Desc: 新增组织部门
* Time: 2024-07-12 10:47:05 -
* */
createDept: async (data) => {
return HTTP({
method: 'post',
url: '/authDept',
data,
});
},
/**
* Name: getDept
* Desc: 获取组织部门的分页或列表
* Time: 2024-07-02 22:45:11 -
* */
getDept: async (
params = {
...PageData,
},
) => {
return HTTP({
method: 'get',
url: '/authDept',
params,
});
},
/**
* Name: getDeptMore
* Desc: 获取组织部门详情
* Time: 2024-07-02 22:45:11 -
* */
getDeptMore: async (deptId) => {
return HTTP({
method: 'get',
url: `/authDept/${deptId}`,
});
},
/**
* Name: getDeptTree
* Desc: 获取组织部门树
* Time: 2024-07-02 22:45:11 -
* */
getDeptTree: async (deptId = 0) => {
return HTTP({
method: 'get',
url: `/authDept/tree/${deptId}`,
});
},
/**
* Name: removeDept
* Desc: 删除组织部门
* Time: 2024-07-02 22:45:06 -
* */
removeDept: async (deptId) => {
return HTTP({
method: 'delete',
url: `/authDept/${deptId}`,
});
},
/**
* Name: updateDept
* Desc: 编辑组织部门
* Time: 2024-07-02 22:45:03 -
* */
updateDept: async (deptId, data) => {
return HTTP({
method: 'patch',
url: `/authDept/${deptId}`,
data,
});
},
};

@ -16,5 +16,6 @@ import { CoreService } from '@/api/Core/CoreService/index.js';
import { CoreDict } from '@/api/Core/CoreDict/index.js';
import { CoreEnv } from '@/api/Core/CoreEnv/index.js';
import { CoreMenu } from '@/api/Core/CoreMenu/index.js';
import { AuthDept } from '@/api/Auth/AuthDept/index.js';
export { Sign, DefaultSign, CoreService, CoreDict, CoreEnv, CoreMenu };
export { Sign, DefaultSign, CoreService, CoreDict, CoreEnv, CoreMenu, AuthDept };

@ -42,12 +42,12 @@ function chooseAll() {
<template>
<div>
<AButton shape="circle" :icon="h(BgColorsOutlined)" @click="status = true" />
<a-drawer v-model:open="status" title="表格列选择" placement="right" :fieldNames="{ title: 'name' }" @close="handleClose">
<ADrawer v-model:open="status" title="表格列选择" placement="right">
<AButton @click="chooseAll">全选</AButton>
<ADivider />
<a-tree class="draggable-tree" draggable block-node checkable v-model:checkedKeys="checkedKeys" :tree-data="props.columnList" @drop="onDrop" />
<!-- @dragenter="onDragEnter"-->
</a-drawer>
</ADrawer>
</div>
</template>

@ -40,6 +40,8 @@ import {
CheckboxGroup,
Popconfirm,
Divider,
List,
ListItem, ListItemMeta,
} from 'ant-design-vue';
import 'ant-design-vue/dist/reset.css';
@ -85,6 +87,9 @@ export function setupCustomAntDesignVueComponents(app) {
CheckboxGroup,
Popconfirm, // ! 气泡确认框
Divider, // ! 分割线
List, // ! 列表
ListItem, // ! 列表子项
ListItemMeta, // ! 列表子项详细信息
];
for (let component of componentList) {
app.component(component.name, component);

@ -56,6 +56,15 @@ export default function createRoutering() {
},
component: () => import('@/views/Auth/Env/EnvPage.vue')
},
{
path: '/dept',
name: 'Dept',
meta:{
title: '部门管理',
icon: ''
},
component: () => import('@/views/Auth/Dept/DeptPage.vue')
},
{
path: '/about',
name: 'about',

@ -13,7 +13,7 @@
import { defineStore } from 'pinia';
import { computed, reactive } from 'vue';
import { CoreDict, CoreEnv, CoreMenu, CoreService } from '@/api/index.js';
import { AuthDept, CoreDict, CoreEnv, CoreMenu, CoreService } from '@/api/index.js';
export const useBaseDataStore = defineStore('baseData', () => {
const state = reactive({
@ -46,6 +46,14 @@ export const useBaseDataStore = defineStore('baseData', () => {
menuTypeList: [],
// ! 菜单类型树
menuTypeTree: [],
// ! 部门列表
deptList: [],
// ! 部门树
deptTree: [],
// ! 部门类型列表
deptTypeList: [],
// ! 部门类型树
deptTypeTree: [],
// ! 防抖
// 防抖获取服务列表
@ -58,6 +66,10 @@ export const useBaseDataStore = defineStore('baseData', () => {
canGetMenuList: true,
// 防抖获取菜单Menu类型列表
canGetMenuTypeList: true,
// 防抖获取部门Dept列表
canGetDeptList: true,
// 防抖获取部门Dept类型列表
canGetDeptTypeList: true,
});
// ! 获取服务列表
@ -146,6 +158,46 @@ export const useBaseDataStore = defineStore('baseData', () => {
const [list] = getDictTree(resd);
state.menuTypeTree = Array.isArray(list) && list.length > 0 ? list[0].children : [];
};
// ! 获取部门列表
const getDeptList = async () => {
if (!state.canGetDeptList) return;
state.canGetDeptList = false;
setTimeout(() => {
state.canGetDeptList = true;
}, 2000);
const resd = await AuthDept.getDeptTree(0);
state.deptList = resd;
const [list, otherList] = getDeptTree(resd);
list.push({
meta: {},
label: '其他部门',
value: '-1',
id: '-1',
disabled: true,
children: otherList,
});
state.deptTree = list;
};
// ! 获取部门类型
const getDeptTypeList = async () => {
if (!state.canGetDeptTypeList) return;
state.canGetDeptTypeList = false;
setTimeout(() => {
state.canGetDeptTypeList = true;
}, 2000);
// ! todo DeptType时固定字段,初始字典
const resd = await CoreDict.getDictTree({
dictKey: 'DeptType',
isTree: true,
});
state.deptTypeList = resd;
const [list] = getDictTree(resd);
state.deptTypeTree = Array.isArray(list) && list.length > 0 ? list[0].children : [];
};
return {
state,
getServiceList,
@ -153,6 +205,8 @@ export const useBaseDataStore = defineStore('baseData', () => {
getEnvList,
getMenuList,
getMenuTypeList,
getDeptList,
getDeptTypeList
};
});
@ -230,3 +284,28 @@ function getMenuTree(list, pid = 0) {
}
return [newList, noList];
}
// ! 格式化Dept树
function getDeptTree(list, pid = 0) {
const newList = [];
let noList = [];
for (let i in list) {
const obj = list[i];
if (obj.pid == pid) {
newList.push({
meta: { ...obj },
label: obj.deptName,
value: obj.deptId,
id: obj.deptId,
});
} else {
noList.push(obj);
}
}
for (let obj of newList) {
const [children, ls] = getDeptTree(noList, obj.id);
obj.children = children;
noList = ls;
}
return [newList, noList];
}

@ -0,0 +1,221 @@
// | ------------------------------------------------------------
// | @版本: version 0.1
// | @创建人: 【Nie-x7129】
// | @E-mail: x71291@outlook.com
// | @所在项目: hoto-auth-vue3
// | @文件描述: DataModal.js -
// | @创建时间: 2024-07-12 10:53
// | @更新时间: 2024-07-12 10:53
// | @修改记录:
// | -*-*-*- (时间--修改人--修改说明) -*-*-*-
// | =
// | ------------------------------------------------------------
import { h } from 'vue';
// 表单数据
export class DeptFormType {
constructor() {
return new Object({
// 上级部门Id
pid: undefined,
// 部门名称
deptName: '',
// 部门描述
deptDesc: '',
// 部门类型
deptType: undefined,
// 部门负责人 todo 等账户添加
deptLeader: undefined,
// 默认角色 todo 等角色添加
defaultRole: undefined,
// 排序
orderNum: 0,
});
}
}
// 查询数据
export class DeptSearchType {
constructor() {
return new Object({
// 每页数量
pageSize: 10,
// 页码
pageNumber: 1,
// 是否是列表
isList: false,
// 排序方式
isAsc: false,
// 部门信息
deptInfo: undefined,
// 部门类型
deptType: undefined,
// 状态
status: undefined,
// 根据pid查
hierarchy: [],
});
}
}
// 表单规则
export class DeptFormRulesType {
constructor() {
// todo
return new Object({});
}
}
// Dept表格列数据
export class DeptTableColumnType {
constructor() {
return new Object({
index: {
title: '序号',
key: 'index',
width: 70, // 你可以根据需要设置列宽
customRender: ({ text, record, index, column }) => `${index + 1}`, // 使用索引 + 1 来显示序号
},
deptName: {
title: '名称',
dataIndex: 'deptName',
key: 'deptName',
link: 'details',
},
deptTypeName: {
title: '类型',
dataIndex: 'deptTypeName',
key: 'deptTypeName',
},
deptLeaderName: {
title: '负责人',
dataIndex: 'deptLeaderName',
key: 'deptLeaderName',
},
defaultRoleName: {
title: '默认角色',
dataIndex: 'defaultRoleName',
key: 'defaultRoleName',
},
grade: {
title: '级别',
dataIndex: 'grade',
key: 'grade',
},
haveChildren: {
title: '子项',
dataIndex: 'haveChildren',
key: 'haveChildren',
width: '50px',
},
createtime: {
title: '创建时间',
dataIndex: 'createtime',
key: 'createtime',
width: '140px',
sorter: true,
},
createName: {
title: '创建人',
dataIndex: 'createName',
key: 'createName',
},
updatetime: {
title: '更新时间',
dataIndex: 'updatetime',
key: 'updatetime',
maxWidth: '140px',
minWidth: '140px',
},
updateName: {
title: '更新人',
dataIndex: 'updateName',
key: 'updateName',
},
action: {
title: '操作',
dataIndex: 'action',
key: 'action',
width: 100,
align: 'center',
},
});
}
}
// Dept可选表格列
export class DeptTableColumnChooseType {
constructor() {
const excludeColumn = ['updateName', 'updatetime', 'createName'];
const tableColumn = new DeptTableColumnType();
return Object.keys(tableColumn).map((i) => ({
title: tableColumn[i].title,
key: tableColumn[i].key,
status: excludeColumn.includes(i) ? false : true,
}));
}
}
// Dept详细信息列表
export class DeptDetailsType {
constructor() {
return new Array(
{
title: '部门名称',
key: 'deptName',
},
{
title: '类型',
key: 'deptTypeName',
},
{
title: '部门等级',
key: 'grade',
},
{
title: '子部门数量',
key: 'haveChildren',
},
{
title: '部门人员数量',
key: 'userCount',
},
{
title: '部门负责人',
key: 'deptLeaderName',
},
{
title: '部门默认分配角色',
key: 'defaultRoleName',
},
{
title: '部门描述',
key: 'deptDesc',
},
{
title: '部门状态',
key: 'status',
},
{
title: '排序',
key: 'orderNum',
},
{
title: '创建人',
key: 'createName',
},
{
title: '创建时间',
key: 'createtime',
},
{
title: '修改人',
key: 'updateName',
},
{
title: '修改时间',
key: 'updatetime',
},
);
}
}

@ -0,0 +1,113 @@
<script setup name="DeptForm">
import { h, onMounted, ref, watch } from 'vue';
import { useBaseDataStore } from '@/stores/index.js';
import { ReloadOutlined, SettingOutlined } from '@ant-design/icons-vue';
import { DeptFormRulesType, DeptFormType } from '@/views/Auth/Dept/DataModal.js';
const baseDataStore = useBaseDataStore();
defineOptions({
name: 'DeptForm',
});
//
const props = defineProps({
data: {
type: Object,
required: true,
default: () => ({
//
status: false,
//
formData: new DeptFormType(),
//
handleAck: (data) => data,
//
handleCancel: (data) => data,
}),
},
});
// ! ref
const formRef = ref(null);
// !
const rules = new DeptFormRulesType();
// !
const handleAck = () => {
formRef.value
.validate()
.then((value) => {
const data = { ...value };
if (Array.isArray(value.pid) && value.pid.length > 0) {
data.pid = value.pid.slice(-1)[0];
}
if (Array.isArray(value.deptType) && value.deptType.length > 0) {
data.deptType = value.deptType.slice(-1)[0];
}
props.data.handleAck(data).catch((e) => e);
})
.catch((err) => {
formRef.value.scrollToField(err?.errorFields[0]?.name);
});
};
onMounted(() => {
window.pino.info('@3 DeptForm Mounted!');
// ! Dept
if (baseDataStore.state.deptList.length == 0) {
baseDataStore.getDeptList();
}
// !
if (baseDataStore.state.deptTypeList?.length == 0) {
baseDataStore.getDeptTypeList();
}
});
</script>
<template>
<AntdModalTemplate>
<AForm ref="formRef" :model="props.data.formData" :rules="rules" name="DictForm" :label-col="{ span: 8 }" layout="vertical">
<AFormItem label="上级部门" name="pid">
<AFlex gap="small">
<ACascader
flex="1"
:disabled="props.data.isUpdate"
allowClear
showSearch
v-model:value="props.data.formData.pid"
:options="baseDataStore.state.deptTree"
:multiple="false"
placeholder="请选择上级部门"
change-on-select
/>
<AButton flex="0" :icon="h(ReloadOutlined)" @click="baseDataStore.getDeptList()" shape="circle" />
</AFlex>
</AFormItem>
<AFormItem label="部门名称" name="deptName">
<AInput style="width: 100%" v-model:value="props.data.formData.deptName" placeholder="请输入部门名称" :maxlength="32" showCount />
</AFormItem>
<AFormItem label="部门类型" name="deptType">
<AFlex gap="small">
<ASelect placeholder="请选择部门类型" v-model:value="props.data.formData.deptType" :options="baseDataStore.state.deptTypeTree" />
<AButton flex="0" :icon="h(ReloadOutlined)" @click="baseDataStore.getDeptTypeList()" shape="circle" />
</AFlex>
</AFormItem>
<AFormItem label="部门描述" name="deptDesc">
<ATextarea style="width: 100%" v-model:value="props.data.formData.deptDesc" :rows="3" placeholder="请输入部门描述" :maxlength="255" />
</AFormItem>
<AFormItem label="排序" name="orderNum">
<AInputNumber v-model:value="props.data.formData.orderNum">
<template #addonAfter><SettingOutlined /></template>
</AInputNumber>
</AFormItem>
</AForm>
<template #footer>
<AButton type="dashed" @click="props.data.handleCancel">取消</AButton>
<AckCreateAntdButton @click="handleAck" />
</template>
</AntdModalTemplate>
</template>
<style scoped></style>

@ -0,0 +1,259 @@
<script setup name="DeptPage">
import { onMounted, reactive, watch } from 'vue';
import { useMessage } from 'naive-ui';
import { useBaseDataStore } from '@/stores/baseData.js';
import { AuthDept } from '@/api/index.js';
import { DeptDetailsType, DeptFormType, DeptSearchType, DeptTableColumnChooseType } from './DataModal.js';
import DeptForm from './DeptForm.vue';
import DeptTable from './DeptTable.vue';
import DeptTree from './DeptTree.vue';
const baseDataStore = useBaseDataStore();
const Message = useMessage();
defineOptions({
name: 'DeptPage',
});
//
let searchCount = 0;
// !
const formData = reactive({
//
modelName: '创建部门',
//
status: false,
//
isUpdate: false,
// ID
deptId: undefined,
formData: new DeptFormType(),
//
handleAck: handleCreateAck,
//
handleCancel: clearFormData,
});
// !
const tableData = reactive({
dataSource: [],
pageInfo: new DeptSearchType(),
total: 0,
methods: {
handleTableChange,
handleRemoveAck,
handleUpdate,
handleDetails,
},
handlePageChange,
columnList: new DeptTableColumnChooseType(),
});
// !
const detailsData = reactive({
status: false,
data: {},
list:[]
});
// @1
async function handleCreateAck(data) {
await AuthDept.createDept(data);
Message.success('添加部门成功!');
clearSearchData();
clearFormData();
getPage();
baseDataStore.getDeptList();
}
// @2
async function handleRemoveAck(data) {
await AuthDept.removeDept(data.deptId);
Message.success('删除部门成功!');
detailsData.status = false;
if (tableData.dataSource.length == 1 && tableData.pageInfo.pageNumber > 1) {
tableData.pageInfo.pageNumber--;
}
getPage();
baseDataStore.getDeptList();
}
// @3 todo
async function handleUpdate(data) {
formData.modelName = '更新部门';
formData.status = true;
formData.isUpdate = true;
formData.deptId = data.deptId;
formData.handleAck = handleUpdateAck;
Object.keys(formData.formData).forEach((key) => {
formData.formData[key] = data[key];
});
}
// @4 todo
async function handleUpdateAck(data) {
if (!data.pid) {
data.pid = 0;
}
await AuthDept.updateDept(formData.deptId, data);
Message.success('更新部门成功!');
clearFormData();
getPage();
baseDataStore.getDeptList();
}
// @5 todo
watch(tableData.pageInfo, () => {
getPage();
});
// @6
async function getPage() {
if (searchCount === 0) {
searchCount++;
setTimeout(() => {
searchCount = 0;
}, 500);
} else {
searchCount++;
return;
}
const pageInfo = { ...tableData.pageInfo };
pageInfo.hierarchy = pageInfo.hierarchy.length > 0 ? pageInfo.hierarchy[0] : undefined;
const resd = await AuthDept.getDept(pageInfo);
tableData.dataSource = resd.rowData;
tableData.total = Number(resd.total);
}
// @7
function handlePageChange(page, pageSize) {
tableData.pageInfo.pageSize = pageSize;
tableData.pageInfo.pageNumber = page;
}
// @7
function handleTableChange(page, filter, sorter) {
if (sorter.order == 'ascend') {
tableData.pageInfo.isAsc = true;
} else if (sorter.order == 'descend') {
tableData.pageInfo.isAsc = false;
} else {
tableData.pageInfo.isAsc = undefined;
}
}
// @8
function clearSearchData() {
const newPageInfo = new DeptSearchType();
Object.keys(tableData.pageInfo).forEach((key) => {
tableData.pageInfo[key] = newPageInfo[key];
});
}
// @9
function clearFormData() {
formData.modelName = '创建部门';
formData.isUpdate = false;
formData.status = false;
formData.deptId = undefined;
formData.handleAck = handleCreateAck;
const newFormData = new DeptFormType();
Object.keys(formData.formData).forEach((key) => {
formData.formData[key] = newFormData[key];
});
}
// @10
async function handleDetails(data){
detailsData.status = true;
const resd = await AuthDept.getDeptMore(data.deptId);
detailsData.data = resd;
detailsData.list = (new DeptDetailsType()).map(item => {
item.data = resd[item.key];
return item;
});
}
// @11
function handleDetailsClose(){
detailsData.data = {};
detailsData.list = [];
}
onMounted(() => {
window.pino.deb('@1 DeptPage Mounted!');
getPage();
// !
if (baseDataStore.state.menuTypeList?.length == 0) {
baseDataStore.getMenuTypeList();
}
});
</script>
<template>
<WorkContainer>
<template #header>
<ASpace>
<CreateAntdButton name="部门" @click="formData.status = true" />
<TableColumChoose v-model:columnList="tableData.columnList" />
<AInputSearch v-model:value="tableData.pageInfo.deptInfo" placeholder="部门组织信息" style="width: 200px" @search="getPage" />
<ASelect style="width: 150px" placeholder="请选择部门类型" allowClear v-model:value="tableData.pageInfo.deptType" :options="baseDataStore.state.deptTypeList" />
</ASpace>
</template>
<template #main>
<div class="deptBody">
<div class="tree"><DeptTree v-model:selectedKeys="tableData.pageInfo.hierarchy" /></div>
<div class="table"><DeptTable :tableData="tableData" /></div>
</div>
</template>
<template #footer>
<TablePagination :data="tableData" />
</template>
<template #modal>
<AModal
v-model:open="formData.status"
:title="formData.modelName"
:centered="true"
style="height: 600px"
:maskClosable="false"
:destroyOnClose="true"
:onCancel="clearFormData"
>
<DeptForm :data="formData" />
<template #footer></template>
</AModal>
<ADrawer v-model:open="detailsData.status" title="部门详细信息" placement="right" size="large" @close="handleDetailsClose">
<template #extra>
<ASpace>
<TableRemoveButton :ackDelete="() => tableData.methods.handleRemoveAck(detailsData.data)" />
<TableUpdateButton @click="tableData.methods.handleUpdate(detailsData.data)" />
</ASpace>
</template>
<AList :data-source="detailsData.list">
<template #renderItem="{ item }">
<AListItem>
<AListItemMeta :description="item.title">
<!-- <template #title>{{item.title}}</template>-->
</AListItemMeta>
{{item.data === '' ? '暂无数据' : item.data}}
</AListItem>
</template>
</AList>
</ADrawer>
</template>
</WorkContainer>
</template>
<style scoped lang="scss">
.deptBody {
position: relative;
height: 100%;
width: 100%;
display: flex;
& > div.tree {
position: relative;
flex-shrink: 0;
max-height: 100%;
width: 300px;
border-right: 1px solid #cdcdcd;
padding-right: 5px;
}
& > div.table {
position: relative;
flex: 1;
max-height: 100%;
padding-left: 5px;
overflow: hidden;
}
}
.detailsContent{
font-weight: bold;
color: #666;
}
</style>

@ -0,0 +1,90 @@
<script setup name="DeptTable">
import { computed, onMounted, ref, h } from 'vue';
import { DeptTableColumnType } from '@/views/Auth/Dept/DataModal.js';
import { Button } from 'ant-design-vue';
defineOptions({
name: 'DeptTable',
});
const props = defineProps({
tableData: {
type: Object,
required: true,
},
});
const isLoading = ref(true);
// !
const tableColumnObject = new DeptTableColumnType();
tableColumnObject.deptName.customRender = ({ text, record, index, column }) => {
return h(
Button,
{
type: 'link',
onClick: () => {
props.tableData.methods.handleDetails(record);
},
},
{ default: () => text },
);
};
const tableColumns = computed(() => {
// !
setTableAuto();
if (props.tableData.columnList && props.tableData.columnList.length > 0) {
// !
const existColumn = props.tableData.columnList.filter((i) => i.status === true);
if (existColumn.length == 0) {
// !
return Object.keys(tableColumnObject).map((column) => tableColumnObject[column]);
} else {
// !
return existColumn.map((column) => tableColumnObject[column.key]);
}
} else {
//
return Object.keys(tableColumnObject).map((column) => tableColumnObject[column]);
}
});
function setTableAuto() {
isLoading.value = false;
setTimeout(() => {
isLoading.value = true;
}, 100);
}
function handleResizeColumn(w, col) {
col.width = w;
}
onMounted(() => {
window.pino.deb('@2 DeptTable Mounted!');
});
</script>
<template>
<PacmanLoading v-if="!isLoading" loading="1" />
<ATable
v-if="isLoading"
style="height: 100%"
:dataSource="props.tableData.dataSource"
:columns="tableColumns"
@change="props.tableData.methods.handleTableChange"
:pagination="false"
sticky
tableLayout="auto"
@resizeColumn="handleResizeColumn"
:row-class-name="(_record, index) => (index % 2 === 1 ? 'table-striped' : null)"
:scroll="{ scrollToFirstRowOnChange: true }"
>
<template #bodyCell="{ column, record }">
<template v-if="column?.key === 'action'">
<ASpace>
<TableRemoveButton :ackDelete="() => props.tableData.methods.handleRemoveAck(record)" />
<TableUpdateButton @click="props.tableData.methods.handleUpdate(record)" />
</ASpace>
</template>
</template>
</ATable>
</template>
<style scoped></style>

@ -0,0 +1,34 @@
<script setup name="DeptTree">
defineOptions({
name: 'DeptTree',
});
import { useBaseDataStore } from '@/stores/baseData.js';
import { onMounted, reactive } from 'vue';
const baseDataStore = useBaseDataStore();
// !
const fieldNames = reactive({
children:'children', title:'label', key:'id'
});
//
onMounted(() => {
window.pino.info('@4 DeptTree Mounted');
// !
if (baseDataStore.state.menuList?.length == 0) {
baseDataStore.getDeptList();
}
});
</script>
<template>
<ATree
:treeData="baseDataStore.state.deptTree"
:show-line="true"
show-icon
:fieldNames="fieldNames"
/>
</template>
<style scoped></style>

@ -37,9 +37,6 @@ const formData = reactive({
const tableData = reactive({
dataSource: [],
pageInfo: new MenuSearchType(),
searchBase:{
menuType: []
},
total: 0,
methods: {
handleTableChange,

@ -0,0 +1,14 @@
<script setup name="RolePage">
defineOptions({
name: 'RolePage',
});
</script>
<template>
</template>
<style scoped>
</style>
Loading…
Cancel
Save