feat: 设置->合同设置->合同文档模板设置

This commit is contained in:
Zzz1zz
2025-08-26 23:13:34 +08:00
parent ddb35b10f1
commit fc07ed06d5
16 changed files with 1348 additions and 95 deletions
@@ -0,0 +1,230 @@
<template>
<a-card title="合同文档模板设置">
<template #extra>
<a-button type="primary" @click="handleAddContractNumber"
><icon-plus />新增</a-button
>
</template>
<DataTable
:data="renderData"
:columns="projectColumn"
:loading="loading"
:total="total"
:current="current"
:page-size="pageSize"
pagination
@page-change="onPageChange"
@page-size-change="onPageSizeChange"
>
<template #realname="{ record }">
<span>{{ record.realname }}</span>
<icon-idcard v-if="record.isManager === 1" />
</template>
<template #status="{ record }">
<a-tag :color="record.status == 1 ? 'green' : 'red'">
{{ record.status == 1 ? $t('enable') : $t('disable') }}</a-tag
>
</template>
<template #operate="{ record }">
<a-space>
<a-button type="primary" @click="handleEditContractNumber(record.id)">
{{ $t('edit') }}</a-button
>
<a-popover trigger="click" position="bottom">
<a-button>{{ $t('more') }}</a-button>
<template #content>
<a-space direction="vertical">
<a-button @click="handleToggleStatus(record.id, record.status)">
{{ record.status == 1 ? $t('disable') : $t('enable') }}
</a-button>
<a-button status="danger" @click="handleDel(record.id)">
{{ $t('delete') }}
</a-button>
</a-space>
</template>
</a-popover>
</a-space>
</template>
</DataTable>
<contractFileForm
v-model:visible="showModal"
:department-list-data="departmentListData"
:is-edit="isEdit"
@submitted="getWordSettingListData"
/>
</a-card>
</template>
<script lang="ts" setup>
import { ref, onMounted } from 'vue';
import type { TableColumnData } from '@arco-design/web-vue';
import { Message } from '@arco-design/web-vue';
import useDataTable from '@/composables/useDataTable';
import {
getWordSettingFromId,
delWordSetting,
getWordSettingList,
disableWordSetting,
getDepartmentList,
} from '@/api/setting';
import { ContractWordItem, DepartmentItem } from '@/types/setting';
import { UserStatus } from '@/types/comm';
import { camelToSnake } from '@/utils/caseConvert';
// import contractNumberFormDrawer from './drawer/contract-number-form-drawer.vue';
import contractFileForm from './modal/contract-file-form.vue';
const {
data: renderData,
columns: projectColumn,
loading,
total,
current,
pageSize,
setData,
setColumns,
setLoading,
setTotal,
setCurrent,
setPageSize,
} = useDataTable({
initialPage: 1,
initialPageSize: 10,
pageSizeOptions: [10, 20, 50, 100],
});
const contractWordList = ref<ContractWordItem[]>([]);
const departmentListData = ref<DepartmentItem[]>([]);
const showModal = ref<boolean>(false);
const isEdit = ref<boolean>(false);
const currentNumberInfo = ref<any>(null);
// 列配置
const columns: TableColumnData[] = [
{
title: '模板名称',
dataIndex: 'name',
key: 'name',
width: 120,
ellipsis: true,
},
{
title: '适用范围',
dataIndex: 'departmentName',
key: 'departmentName',
render: ({ record }) => record.departmentName || '-',
},
{
title: '适用项目',
dataIndex: 'projectName',
key: 'projectName',
render: ({ record }) => record.projectName || '-',
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
slotName: 'status',
},
{
title: '操作',
key: 'operate',
slotName: 'operate',
width: 200,
},
];
// 获取列表数据
const getWordSettingListData = async () => {
const params = {
page: current.value,
page_size: pageSize.value,
};
setLoading(true);
const { code, data } = await getWordSettingList(params);
if (code === 200 && data) {
const { contractWordSetting, page } = data;
contractWordList.value = Array.isArray(contractWordSetting)
? contractWordSetting
: [];
setData(contractWordList.value);
if (page?.total) setTotal(page?.total);
}
setLoading(false);
};
// 部门列表
const getDepartmentListData = async () => {
try {
const { code, data } = await getDepartmentList();
if (code === 200) {
departmentListData.value = data.departmentList;
}
} catch (error) {
// console.error('获取部门列表失败:', error);
}
};
// 分页事件处理
const onPageChange = (page: number) => {
setCurrent(page);
current.value = page;
getWordSettingListData();
};
const onPageSizeChange = (size: number) => {
setPageSize(size);
pageSize.value = size;
getWordSettingListData();
};
const handleToggleStatus = async (id: number, currentStatus: UserStatus) => {
try {
const status: UserStatus = currentStatus === 1 ? 2 : 1;
const param = { id, status };
const { code, message } = await disableWordSetting(param);
if (code === 200) {
Message.success(message);
getWordSettingListData();
} else {
Message.error(message);
}
} catch (error) {
// 处理错误
}
};
const handleDel = async (id: number) => {
try {
const { code, message } = await delWordSetting(id);
if (code === 200) {
Message.success(message);
getWordSettingListData();
} else {
Message.error(message);
}
} catch (error) {
// 处理错误
}
};
const getWordSettingFromIdData = async (id: number) => {
const { code, data } = await getWordSettingFromId(id);
if (code === 200 && data) {
const { contractCodeSetting } = data;
currentNumberInfo.value = contractCodeSetting || null;
currentNumberInfo.value.arrange = camelToSnake(
currentNumberInfo.value.arrange
);
}
};
const handleAddContractNumber = () => {
// currentNumberInfo.value = null;
isEdit.value = false;
showModal.value = true;
};
const handleEditContractNumber = async (id: number) => {
await getWordSettingFromIdData(id);
isEdit.value = true;
// currentNumberInfo.value = info
showModal.value = true;
};
// 初始化数据
onMounted(() => {
setColumns(columns);
getWordSettingListData();
getDepartmentListData();
});
</script>
@@ -1,3 +1,231 @@
<template>
<div>123</div>
<a-card title="创建合同模板设置">
<template #extra>
<a-button type="primary" @click="handleAddContractNumber"
><icon-plus />新增</a-button
>
</template>
<DataTable
:data="renderData"
:columns="projectColumn"
:loading="loading"
:total="total"
:current="current"
:page-size="pageSize"
pagination
@page-change="onPageChange"
@page-size-change="onPageSizeChange"
>
<template #realname="{ record }">
<span>{{ record.realname }}</span>
<icon-idcard v-if="record.isManager === 1" />
</template>
<template #status="{ record }">
<a-tag :color="record.status == 1 ? 'green' : 'red'">
{{ record.status == 1 ? $t('enable') : $t('disable') }}</a-tag
>
</template>
<template #operate="{ record }">
<a-space>
<a-button type="primary" @click="handleEditContractNumber(record.id)">
{{ $t('edit') }}</a-button
>
<a-popover trigger="click" position="bottom">
<a-button>{{ $t('more') }}</a-button>
<template #content>
<a-space direction="vertical">
<a-button @click="handleToggleStatus(record.id, record.status)">
{{ record.status == 1 ? $t('disable') : $t('enable') }}
</a-button>
<a-button status="danger" @click="handleDel(record.id)">
{{ $t('delete') }}
</a-button>
</a-space>
</template>
</a-popover>
</a-space>
</template>
</DataTable>
<contractTemplateForm
v-model:visible="showModal"
:department-list-data="departmentListData"
:is-edit="isEdit"
@submitted="getTemplateSettingListData"
/>
</a-card>
</template>
<script lang="ts" setup>
import { ref, onMounted } from 'vue';
import type { TableColumnData } from '@arco-design/web-vue';
import { Message } from '@arco-design/web-vue';
import useDataTable from '@/composables/useDataTable';
import {
getTemplateSettingFromId,
delTemplateSetting,
getTemplateSettingList,
getDepartmentList,
disableTemplateSetting,
} from '@/api/setting';
import { ContractTemplateSettingItem, DepartmentItem } from '@/types/setting';
import { UserStatus } from '@/types/comm';
import { camelToSnake } from '@/utils/caseConvert';
// import contractNumberFormDrawer from './drawer/contract-number-form-drawer.vue';
import contractTemplateForm from './modal/contract-template-form.vue';
const {
data: renderData,
columns: projectColumn,
loading,
total,
current,
pageSize,
setData,
setColumns,
setLoading,
setTotal,
setCurrent,
setPageSize,
} = useDataTable({
initialPage: 1,
initialPageSize: 10,
pageSizeOptions: [10, 20, 50, 100],
});
const contractTemplateList = ref<ContractTemplateSettingItem[]>([]);
const departmentListData = ref<DepartmentItem[]>([]);
const showModal = ref<boolean>(false);
const isEdit = ref<boolean>(false);
const currentNumberInfo = ref<any>(null);
// 列配置
const columns: TableColumnData[] = [
{
title: '模板名称',
dataIndex: 'name',
key: 'name',
width: 120,
ellipsis: true,
},
{
title: '合同类型',
dataIndex: 'contractType',
key: 'contractType',
width: 250,
render: ({ record }) => record.contractType || '-',
},
{
title: '适用范围',
dataIndex: 'departmentName',
key: 'departmentName',
render: ({ record }) => record.departmentName || '-',
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
slotName: 'status',
},
{
title: '操作',
key: 'operate',
slotName: 'operate',
width: 200,
},
];
// 获取列表数据
const getTemplateSettingListData = async () => {
const params = {
page: current.value,
page_size: pageSize.value,
};
setLoading(true);
const { code, data } = await getTemplateSettingList(params);
if (code === 200 && data) {
const { contractTemplateSetting, page } = data;
contractTemplateList.value = Array.isArray(contractTemplateSetting)
? contractTemplateSetting
: [];
setData(contractTemplateList.value);
if (page?.total) setTotal(page?.total);
}
setLoading(false);
};
// 部门列表
const getDepartmentListData = async () => {
try {
const { code, data } = await getDepartmentList();
if (code === 200) {
departmentListData.value = data.departmentList;
}
} catch (error) {
// console.error('获取部门列表失败:', error);
}
};
// 分页事件处理
const onPageChange = (page: number) => {
setCurrent(page);
current.value = page;
getTemplateSettingListData();
};
const onPageSizeChange = (size: number) => {
setPageSize(size);
pageSize.value = size;
getTemplateSettingListData();
};
const handleToggleStatus = async (id: number, currentStatus: UserStatus) => {
try {
const status: UserStatus = currentStatus === 1 ? 2 : 1;
const param = { id, status };
const { code, message } = await disableTemplateSetting(param);
if (code === 200) {
Message.success(message);
getTemplateSettingListData();
} else {
Message.error(message);
}
} catch (error) {
// 处理错误
}
};
const handleDel = async (id: number) => {
try {
const { code, message } = await delTemplateSetting(id);
if (code === 200) {
Message.success(message);
getTemplateSettingListData();
} else {
Message.error(message);
}
} catch (error) {
// 处理错误
}
};
const getTemplateSettingFromIdData = async (id: number) => {
const { code, data } = await getTemplateSettingFromId(id);
if (code === 200 && data) {
const { contractCodeSetting } = data;
currentNumberInfo.value = contractCodeSetting || null;
currentNumberInfo.value.arrange = camelToSnake(
currentNumberInfo.value.arrange
);
}
};
const handleAddContractNumber = () => {
// currentNumberInfo.value = null;
isEdit.value = false;
showModal.value = true;
};
const handleEditContractNumber = async (id: number) => {
await getTemplateSettingFromIdData(id);
isEdit.value = true;
// currentNumberInfo.value = info
showModal.value = true;
};
// 初始化数据
onMounted(() => {
setColumns(columns);
getTemplateSettingListData();
getDepartmentListData();
});
</script>
@@ -1,3 +0,0 @@
<template>
<div>123</div>
</template>
@@ -23,8 +23,8 @@
<a-col :span="18">
<contractNumber v-if="currentSettingId === 1" />
<contractTerms v-if="currentSettingId === 2" />
<ContractTemplate v-if="currentSettingId === 3" />
<createContractTemplate v-if="currentSettingId === 4" />
<contractFile v-if="currentSettingId === 3" />
<ContractTemplate v-if="currentSettingId === 4" />
</a-col>
</a-row>
</a-card>
@@ -37,7 +37,7 @@
import contractNumber from './contract-number.vue';
import contractTerms from './contract-terms.vue';
import ContractTemplate from './contract-template.vue';
import createContractTemplate from './create-contract-template.vue';
import contractFile from './contract-file.vue';
// import { } from '@/api/setting';
// import { Message } from '@arco-design/web-vue';
@@ -0,0 +1,167 @@
<template>
<a-modal
:visible="visible"
:title="isEdit ? '编辑创建合同模板' : '新增创建合同模板'"
unmount-on-close
@ok="handleSubmit"
@cancel="handleCancel"
>
<a-form
ref="formRef"
:model="form"
:rules="rules"
auto-label-width
layout="vertical"
>
<!-- 模版名称 -->
<a-form-item label="模版名称" field="name" required>
<a-input v-model="form.name" placeholder="请输入模板名称" />
</a-form-item>
<!-- 适用范围(部门) -->
<a-form-item label="适用范围" field="departmentId">
<a-tree-select
v-model="form.departmentId"
:data="props.departmentListData"
:field-names="{ key: 'id', title: 'name', children: 'children' }"
placeholder="请选择适用范围"
allow-clear
/>
</a-form-item>
<a-form-item label="适用项目" field="projects">
<a-select
v-model="form.projects"
multiple
:disabled="!form.departmentId"
placeholder="请选择适用项目"
>
<template v-if="deptProjectList.length">
<a-option
v-for="item in deptProjectList"
:key="item.id"
:value="item.id"
>
{{ item.name }}
</a-option>
</template>
</a-select>
</a-form-item>
<a-form-item label="上传文档" field="urlArr">
<FileUpload
v-model:object-keys="form.urlArr"
v-model:signed-put-u-r-l="form.urlArr"
:max-count="1"
:upload-type="1"
accept="doc,.docx"
/>
<!-- <a-upload draggable action="/" /> -->
<!-- <FileUpload tip="仅支持.doc / .docx格式,最大文件尺寸10MB" v-model:object-keys="form.url"
v-model:signed-put-u-r-l="form.url" list-type="picture-card" /> -->
</a-form-item>
</a-form>
</a-modal>
</template>
<script setup lang="ts">
import { ref, reactive, watch } from 'vue';
import type { FormInstance } from '@arco-design/web-vue';
import { createWordSetting, updateWordSetting } from '@/api/setting';
import { DepartmentItem } from '@/types/setting';
import { getDeptProjectListFromDeptId } from '@/api/common';
import { Message } from '@arco-design/web-vue';
import FileUpload from '@/components/common/FileUpload.vue';
interface TreeNode {
id: string | number;
name: string;
children?: TreeNode[];
}
const props = defineProps<{
visible: boolean;
isEdit: boolean;
record?: DepartmentItem | null;
departmentListData: TreeNode[]; // 修复类型
}>();
const emit = defineEmits<{
(e: 'update:visible', val: boolean): void;
(e: 'submitted'): void;
}>();
// 表单数据
const formRef = ref<FormInstance>();
const form = reactive<any>({
name: '',
departmentId: null,
projects: [],
url: '',
urlArr: [],
id: null,
});
const deptProjectList = ref<any>([]);
// 校验规则
const rules = {
name: [{ required: true, message: '请输入模板名称' }],
departmentId: [{ required: true, message: '请选择适用范围' }],
projects: [{ required: true, message: '请选择适用项目' }],
urlArr: [{ required: true, message: '请上传合同文档' }],
};
const getDeptProjectListFromDeptIdData = async (id) => {
const { code, data } = await getDeptProjectListFromDeptId(id);
if (code === 200) {
deptProjectList.value = data?.deptProjectList || [];
}
};
// 表单事件
const handleCancel = () => {
emit('update:visible', false);
};
// Watch 弹窗控制 & 初始化
watch(
() => props.visible,
(val) => {
if (val) {
if (props.record) {
// form.id = props.record?.id;
// form.name = props.record?.name;
// form.parent_id = props.record?.parentId ?? '';
// form.user_id = props.record?.UserId ?? '';
// form.remark = props.record?.remark ?? '';
// Object.assign(form, props.record);
} else {
Object.assign(form, {
id: undefined,
name: '',
departmentId: null,
});
}
}
},
{ immediate: true }
);
watch(
() => form.departmentId,
(id) => {
if (id) {
deptProjectList.value = [];
getDeptProjectListFromDeptIdData(id);
}
}
);
const handleSubmit = async () => {
await formRef.value?.validate();
const params = JSON.parse(JSON.stringify(form));
params.url = form.urlArr[0];
delete params.urlArr;
const { code, message } = props.isEdit
? await updateWordSetting(params)
: await createWordSetting(params);
if (code === 200) {
Message.success(message);
handleCancel();
// 通知父组件更新部门列表数据
emit('submitted');
}
};
</script>
@@ -0,0 +1,112 @@
<template>
<a-modal
:visible="visible"
:title="isEdit ? '编辑创建合同模板' : '新增创建合同模板'"
unmount-on-close
@ok="handleSubmit"
@cancel="handleCancel"
>
<a-form
ref="formRef"
:model="form"
:rules="rules"
auto-label-width
layout="vertical"
>
<!-- 模版名称 -->
<a-form-item label="模版名称" field="name" required>
<a-input v-model="form.name" placeholder="请输入模板名称" />
</a-form-item>
<!-- 适用范围(部门) -->
<a-form-item label="适用范围" field="user_id">
<a-tree-select
v-model="form.departmentId"
:data="props.departmentListData"
:field-names="{ key: 'id', title: 'name', children: 'children' }"
placeholder="请选择适用范围"
allow-clear
/>
</a-form-item>
</a-form>
</a-modal>
</template>
<script setup lang="ts">
import { ref, reactive, watch } from 'vue';
import type { FormInstance } from '@arco-design/web-vue';
import { createTemplateSetting, updateTemplateSetting } from '@/api/setting';
import { DepartmentItem, CreateTemplateSettingParam } from '@/types/setting';
import { Message } from '@arco-design/web-vue';
interface TreeNode {
id: string | number;
name: string;
children?: TreeNode[];
}
const props = defineProps<{
visible: boolean;
isEdit: boolean;
record?: DepartmentItem | null;
departmentListData: TreeNode[]; // 修复类型
}>();
const emit = defineEmits<{
(e: 'update:visible', val: boolean): void;
(e: 'submitted'): void;
}>();
// 表单数据
const formRef = ref<FormInstance>();
const form = reactive<CreateTemplateSettingParam>({
name: '',
departmentId: null,
// id: undefined,
});
// 校验规则
const rules = {
name: [{ required: true, message: '请输入模板名称' }],
departmentId: [{ required: true, message: '请选择适用范围' }],
};
// Watch 弹窗控制 & 初始化
watch(
() => props.visible,
(val) => {
if (val) {
if (props.record) {
// form.id = props.record?.id;
// form.name = props.record?.name;
// form.parent_id = props.record?.parentId ?? '';
// form.user_id = props.record?.UserId ?? '';
// form.remark = props.record?.remark ?? '';
// Object.assign(form, props.record);
} else {
Object.assign(form, {
id: undefined,
name: '',
departmentId: null,
});
}
}
},
{ immediate: true }
);
// 表单事件
const handleCancel = () => {
emit('update:visible', false);
};
const handleSubmit = async () => {
await formRef.value?.validate();
const { code, message } = props.isEdit
? await updateTemplateSetting(form)
: await createTemplateSetting(form);
if (code === 200) {
Message.success(message);
handleCancel();
// 通知父组件更新部门列表数据
emit('submitted');
}
};
</script>
+237 -50
View File
@@ -63,13 +63,8 @@
</template>
</a-tree>
</a-col>
<a-col :span="12">
<a-descriptions
v-if="departmentDetailInfo"
:column="1"
layout="horizontal"
bordered
>
<a-col v-if="departmentDetailInfo" :span="12">
<a-descriptions :column="1" layout="horizontal" bordered>
<a-descriptions-item :label="t('department-name')">
{{ departmentDetailInfo.name }}</a-descriptions-item
>
@@ -83,6 +78,39 @@
{{ departmentDetailInfo.remark }}</a-descriptions-item
>
</a-descriptions>
<a-card title="选择的项目" style="margin-top: 15px">
<template #extra>
<a-button type="primary" @click="handleSaveProject"
>保存</a-button
>
</template>
<ul>
<li
v-for="item in allProjetList"
:key="item.id"
style="margin-top: 10px"
>
<a-checkbox
:model-value="projectIdCheck.includes(item.id)"
@change="(val) => onCheckChangeProject(val, item)"
>{{ item.name }}</a-checkbox
>
<ul v-if="item?.buildings?.length" class="flex">
<li
v-for="subItem in item.buildings"
:key="subItem.id"
:class="[
'building_item',
{ choose: projectBuildingIdCheck.includes(subItem.id) },
]"
@click="handleChooseBuildingId(item, subItem.id)"
>
{{ subItem.name }}
</li>
</ul>
</li>
</ul>
</a-card>
</a-col>
</a-row>
<departmentFormModal
@@ -106,8 +134,10 @@
departmentSetUp,
departmentSetDown,
delDepartment,
saveDataPermission,
} from '@/api/setting';
import { DepartmentItem, UserList } from '@/types/setting';
import { getAllProjectList } from '@/api/business';
import { debounce } from '@/utils';
import { Message } from '@arco-design/web-vue';
import departmentFormModal from './components/department-form-modal.vue';
@@ -121,7 +151,8 @@
const expandedKeys = ref<(string | number)[]>([]);
const { t } = useI18n();
const projectIdCheck = ref<any>([]); // 已勾选的项目
const projectBuildingIdCheck = ref<any>([]); // 已勾选的项目楼栋
watch(
allDepartmentKeys,
(val) => {
@@ -133,7 +164,7 @@
const showModal = ref<boolean>(false);
const isEdit = ref<boolean>(false);
const departmentDetailInfo = ref<DepartmentItem | null>(null);
const allProjetList = ref<any>(null);
interface TreeNode {
id: string | number;
isShowEditIcon?: boolean;
@@ -150,22 +181,137 @@
});
};
/**
* 通用切换器
* @param type "project" | "building"
* @param project 当前项目对象 { id, buildings }
* @param targetId 被点击的 id(项目 id 或楼栋 id)
*/
const toggleCheck = (
type: 'project' | 'building',
project: any,
targetId: number
) => {
const projectId = project.id;
const buildingIds =
project.buildings?.map((b: any) => b.id).filter(Boolean) || [];
if (type === 'project') {
if (projectIdCheck.value.includes(projectId)) {
// 取消项目 → 去掉该项目和所有楼栋
projectIdCheck.value = projectIdCheck.value.filter(
(id) => id !== projectId
);
projectBuildingIdCheck.value = projectBuildingIdCheck.value.filter(
(id) => !buildingIds.includes(id)
);
} else {
// 勾选项目 → 加上项目和所有楼栋
projectIdCheck.value.push(projectId);
projectBuildingIdCheck.value.push(
...buildingIds.filter(
(id) => !projectBuildingIdCheck.value.includes(id)
)
);
}
}
if (type === 'building') {
if (projectBuildingIdCheck.value.includes(targetId)) {
// 取消楼栋
projectBuildingIdCheck.value = projectBuildingIdCheck.value.filter(
(id) => id !== targetId
);
// 如果该项目没有任何楼栋被选中 → 去掉项目
const stillChecked = buildingIds.some((id) =>
projectBuildingIdCheck.value.includes(id)
);
if (!stillChecked) {
projectIdCheck.value = projectIdCheck.value.filter(
(id) => id !== projectId
);
}
} else {
// 勾选楼栋
projectBuildingIdCheck.value.push(targetId);
// 确保项目也勾选
if (!projectIdCheck.value.includes(projectId)) {
projectIdCheck.value.push(projectId);
}
}
}
};
// 勾选/取消项目
const onCheckChangeProject = (_: any, project: any) => {
toggleCheck('project', project, project.id);
};
// 勾选/取消楼栋
const handleChooseBuildingId = (project: any, buildingId: number) => {
toggleCheck('building', project, buildingId);
};
// 生成保存所需的 projects
const getSaveProjects = () => {
const result: { project_id: number; building_id: number }[] = [];
// 遍历所有勾选的项目
projectIdCheck.value.forEach((pid: number) => {
const project = allProjetList.value?.find((p: any) => p.id === pid);
if (!project) return;
const buildingIds =
project.buildings?.map((b: any) => b.id).filter(Boolean) || [];
// 过滤出该项目下被选中的楼栋
const selectedBuildings = buildingIds.filter((bid) =>
projectBuildingIdCheck.value.includes(bid)
);
// 没有楼栋时,不生成数据(保证数据干净)
selectedBuildings.forEach((bid) => {
result.push({
project_id: project.id,
building_id: bid,
});
});
});
return result;
};
const currentNode = ref<TreeNode | null>(null);
const onSelect = debounce(
async (_: (string | number)[], event: { node: TreeNode }) => {
const { node } = event;
if (node.id === currentNode.value?.id) return;
currentNode.value = node;
// 递归重置所有节点的 isShowEditIcon
resetEditIcon(departmentListData.value);
// 只设置当前节点
if (currentNode.value.level !== 1) {
node.isShowEditIcon = true;
if (node.id !== currentNode.value?.id) {
currentNode.value = node;
// 递归重置所有节点的 isShowEditIcon
resetEditIcon(departmentListData.value);
// 只设置当前节点
if (currentNode.value.level !== 1) {
node.isShowEditIcon = true;
}
const data = await getDepartmentDetailData(
Number(currentNode.value.id)
);
departmentDetailInfo.value = data.department;
if (Array.isArray(data?.projects)) {
// 楼栋勾选
projectBuildingIdCheck.value = data.projects.map(
(item) => item.building_id
);
// 项目勾选(去重)
projectIdCheck.value = [
...new Set(data.projects.map((item) => item.project_id)),
];
} else {
projectIdCheck.value = [];
projectBuildingIdCheck.value = [];
}
}
departmentDetailInfo.value = await getDepartmentDetailData(
Number(currentNode.value.id)
);
},
300
);
@@ -174,32 +320,36 @@
const allUserList = ref<UserList>([]);
const userKeyword = ref<string>('');
const getAllUserListData = async () => {
try {
const { code, data } = await getAllUserList({
keyword: userKeyword.value,
});
if (code === 200) {
const { user } = data;
allUserList.value = Array.isArray(user) ? user : [];
}
} catch (error) {
// 处理错误
async function getAllUserListData() {
const { code, data } = await getAllUserList({
keyword: userKeyword.value,
});
if (code === 200) {
const { user } = data;
allUserList.value = Array.isArray(user) ? user : [];
}
};
}
const handleAdd = () => {
// 所有项目信息
async function getAllProjectListData() {
const { code, data } = await getAllProjectList();
if (code === 200) {
allProjetList.value = data?.projectsList || [];
}
}
function handleAdd() {
isEdit.value = false;
departmentDetailInfo.value = null;
showModal.value = true;
};
}
const handleEdit = () => {
function handleEdit() {
showModal.value = true;
isEdit.value = true;
};
}
const handleDelete = async (item: { id: string | number }) => {
async function handleDelete(item: { id: string | number }) {
const { id } = item;
try {
const { code, message } = await delDepartment(Number(id));
@@ -210,9 +360,9 @@
} catch (error) {
// 处理错误
}
};
}
const handleMoveUp = async (item: { id: string | number }) => {
async function handleMoveUp(item: { id: string | number }) {
const { id } = item;
try {
const { code, message } = await departmentSetUp(Number(id));
@@ -225,25 +375,34 @@
} catch (error) {
// 处理错误
}
};
}
const handleMoveDown = async (item: { id: string | number }) => {
async function handleMoveDown(item: { id: string | number }) {
const { id } = item;
try {
const { code, message } = await departmentSetDown(Number(id));
if (code === 200) {
Message.success(message);
getDepartmentListData();
} else {
Message.info(message);
}
} catch (error) {
// 处理错误
const { code, message } = await departmentSetDown(Number(id));
if (code === 200) {
Message.success(message);
getDepartmentListData();
} else {
Message.info(message);
}
}
const handleSaveProject = async () => {
if (!currentNode?.value?.id) return Message.warning('请先选择部门');
const saveProjects = getSaveProjects();
if (saveProjects.length === 0) return Message.warning('请先选择项目');
const params = {
id: currentNode.value?.id,
projects: saveProjects,
};
const { code, message } = await saveDataPermission(params);
if (code === 200) Message.success(message);
return code;
};
onMounted(() => {
getAllUserListData();
getAllProjectListData();
});
</script>
@@ -253,4 +412,32 @@
height: 100%;
padding: 15px 0;
}
.flex {
display: flex;
align-items: center;
margin-top: 10px;
.building_item {
background-color: #efefef;
color: rgba(154, 154, 154, 1);
width: 100px;
height: 28px;
line-height: 28px;
border: 1px solid #efefef;
margin-right: 16px;
text-align: center;
cursor: pointer;
&:last-child {
margin-right: 0;
}
&.choose {
background-color: #eaf3fe;
color: rgba(22, 93, 255, 1);
border-color: rgba(22, 93, 255, 1);
}
}
}
</style>