| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421 |
- <template>
- <el-drawer
- v-model="isDrawer"
- size="480"
- :title="props.type === 'add' ? '添加监控调阅记录' : '编辑监控调阅记录'"
- @close="handleCloseDrawer"
- >
- <el-form ref="formRef" :model="formParams" :rules="rules" label-placement="left" :label-width="95">
- <el-form-item label="工号" prop="staffNo" style="margin-bottom: 8px">
- <el-input placeholder="请输入工号" v-model="formParams.staffNo" v-if="staffNoHtmlType === 'INPUT'" />
- <el-tree-select
- v-model="formParams.staffNo"
- check-strictly
- placeholder="请输入工号进行搜索"
- class="protocal-select"
- filterable
- remote
- clearable
- :loading="loading"
- :data="staffNoOptions"
- :render-after-expand="false"
- :default-expand-all="true"
- :remote-method="debouncedRemoteMethod"
- @clear="handleClearStaffNo"
- @change="handleChangeStaffNo"
- v-else
- />
- <el-text class="text-mode" type="primary" @click="handleChangeStaff">{{
- `切换为工号${staffNoHtmlType === 'INPUT' ? '选择' : '输入'}方式`
- }}</el-text>
- </el-form-item>
- <el-form-item label="姓名" prop="userName">
- <el-input
- :placeholder="staffNoHtmlType === 'INPUT' ? '请输入姓名' : '请选择工号,此项自动填充'"
- v-model="formParams.userName"
- :disabled="staffNoHtmlType === 'SELECT'"
- />
- </el-form-item>
- <el-form-item label="所属部门" prop="deptName">
- <el-tree-select
- v-model="formParams.deptName"
- :data="departmentArr"
- :render-after-expand="false"
- :default-expand-all="true"
- check-strictly
- :placeholder="staffNoHtmlType === 'INPUT' ? '请选择部门' : '请选择工号,此项自动填充'"
- class="protocal-select"
- :filter-node-method="filterDept"
- filterable
- clearable
- :disabled="staffNoHtmlType === 'SELECT'"
- />
- </el-form-item>
- <el-form-item label="调阅位置" prop="accessLocation">
- <el-input
- placeholder="请输入调阅位置"
- v-model="formParams.accessLocation"
- maxlength="50"
- show-word-limit
- clearable
- />
- </el-form-item>
- <el-form-item label="调阅时段" prop="accessTimeRange">
- <el-date-picker
- v-model="formParams.accessTimeRange"
- type="datetimerange"
- range-separator="至"
- start-placeholder="开始时间"
- end-placeholder="结束时间"
- format="YYYY-MM-DD HH:mm:ss"
- value-format="YYYY-MM-DD HH:mm:ss"
- style="width: 100%"
- @change="handleChangeAccessTimeRange"
- />
- </el-form-item>
- <el-form-item label="是否拷贝" prop="isCopy">
- <el-radio-group v-model="formParams.isCopy">
- <el-radio :value="0">否</el-radio>
- <el-radio :value="1">是</el-radio>
- </el-radio-group>
- </el-form-item>
- <el-form-item label="调阅状态" prop="accessStatus">
- <el-radio-group v-model="formParams.accessStatus">
- <el-radio :value="0">待调阅</el-radio>
- <el-radio :value="1">已调阅</el-radio>
- </el-radio-group>
- </el-form-item>
- <el-form-item label="审批单上传" prop="approvalFormUrl" :rules="approvalFormRules">
- <UploadImages
- ref="uploadImagesRef"
- :maxCount="1"
- :image-list="approvalImageList"
- @upload-success="handleApprovalUploadChange"
- />
- </el-form-item>
- <el-form-item label="记录人" prop="createdByName">
- <el-input placeholder="记录人" v-model="formParams.createdByName" disabled />
- </el-form-item>
- </el-form>
- <template #footer>
- <el-space>
- <el-button @click="handleCloseDrawer">取消</el-button>
- <el-button type="primary" @click="handleSubmitForm(formRef)">提交</el-button>
- </el-space>
- </template>
- </el-drawer>
- </template>
- <script lang="ts" setup>
- import { ref, reactive, watch, computed, onMounted } from 'vue';
- import { ElMessage, type FormInstance, type FormRules } from 'element-plus';
- import { debounce } from 'lodash-es';
- import { getAllDepartments } from '@/api/auth/dept';
- import { queryOrganizationUserTree } from '@/api/system/user';
- import { OrganizationUserTree } from '@/views/system/user/types';
- import { calculateTreeData } from '@/utils';
- import UploadImages from '@/views/disaster/disaster-control/src/components/UploadImages.vue';
- import { ImageItem } from '@/types/disaster-control';
- import { UPLOAD_BIZ_TYPE, uploadFileApi } from '@/api/minio';
- import {
- findUserByWorkNo,
- transformTreeData,
- TransformedTreeNode,
- findOrgCodeByWorkNo,
- } from '@/utils/findUserByWorkNo';
- import {
- SurveillanceInfoStruct,
- addSurveillanceInfo,
- updateSurveillanceInfo,
- } from '@/api/security-confidentiality-surveillance';
- import { useUserInfoHook } from '@/hooks/useUserInfoHook';
- const props = defineProps<{
- type: string; // add or edit
- initialData: SurveillanceInfoStruct;
- }>();
- const emits = defineEmits<{
- (e: 'close'): void;
- }>();
- const { id, realname, staffNo } = useUserInfoHook();
- const formRef = ref<FormInstance>();
- const formParams = ref<SurveillanceInfoStruct & { accessTimeRange: [string, string] }>({
- id: 0,
- staffNo: '',
- userName: '',
- deptId: 0,
- deptName: '',
- accessLocation: '',
- accessStartTime: '',
- accessEndTime: '',
- accessTimeRange: ['', ''],
- isCopy: 0,
- accessStatus: 0,
- approvalFormUrl: '',
- createdById: id,
- createdByName: realname,
- createdByStaffNo: staffNo,
- createdAt: '',
- updatedAt: '',
- isDeleted: 0,
- });
- const rules = reactive<FormRules<SurveillanceInfoStruct & { accessTimeRange: [string, string] }>>({
- staffNo: { required: true, message: '工号不能为空', trigger: 'blur' },
- userName: { required: true, message: '姓名不能为空', trigger: 'blur' },
- deptName: { required: true, message: '所属部门不能为空', trigger: 'blur' },
- accessLocation: { required: true, message: '调阅位置不能为空', trigger: 'blur' },
- accessTimeRange: { required: true, message: '调阅时段不能为空', trigger: 'change' },
- isCopy: { required: true, message: '请选择是否拷贝', trigger: 'change' },
- accessStatus: { required: true, message: '请选择调阅状态', trigger: 'change' },
- });
- // 审批单上传验证规则
- const approvalFormRules = [
- {
- validator: (_: unknown, value: string, callback: (err?: Error) => void) => {
- if (!value || value.trim() === '') {
- return callback(new Error('请上传审批单'));
- }
- callback();
- },
- trigger: ['blur', 'change'],
- },
- ];
- const isDrawer = ref(true);
- const loading = ref(false);
- const staffNoOptions = ref<TransformedTreeNode[]>([]); // 工号选择列表
- const OrganizationSourceData = ref<OrganizationUserTree[]>([]); // 组织结构树原始数据
- const departmentArr = ref<{ value: string | number; label: string }[]>([]);
- const sourceDepartArr = ref<{ value: string | number; label: string }[]>([]);
- // 工号输入/选择模式切换
- type STAFFNO_HTML_TYPE = 'INPUT' | 'SELECT';
- const staffNoHtmlType = ref<STAFFNO_HTML_TYPE>('SELECT');
- // 审批单上传相关
- const uploadImagesRef = ref<InstanceType<typeof UploadImages>>();
- const approvalImages = ref<ImageItem[]>([]);
- const approvalImageList = computed(() => {
- if (!formParams.value.approvalFormUrl) return [];
- // 如果是单个URL字符串,转换为数组格式
- try {
- const parsed = JSON.parse(formParams.value.approvalFormUrl);
- return Array.isArray(parsed) ? parsed : [parsed];
- } catch {
- // 如果不是JSON格式,直接作为单个URL处理
- return [{ url: formParams.value.approvalFormUrl }];
- }
- });
- // 通过工号查询组织结构树
- const remoteMethod = (query: string) => {
- if (query) {
- loading.value = true;
- queryOrganizationUserTree(Number(query)).then((res) => {
- if (res) {
- loading.value = false;
- staffNoOptions.value = transformTreeData(res, true);
- OrganizationSourceData.value = res;
- departmentArr.value = transformTreeData(OrganizationSourceData.value, false);
- }
- });
- } else {
- staffNoOptions.value = [];
- }
- };
- // 防抖
- const debouncedRemoteMethod = debounce(remoteMethod, 1000);
- const handleClearStaffNo = () => {
- formParams.value.staffNo = '';
- formParams.value.userName = '';
- formParams.value.deptId = undefined;
- formParams.value.deptName = '';
- };
- // 切换工号输入/选择模式
- const handleChangeStaff = () => {
- staffNoHtmlType.value = staffNoHtmlType.value === 'INPUT' ? 'SELECT' : 'INPUT';
- if (staffNoHtmlType.value === 'INPUT') {
- // 切换到输入模式时,清空工号、姓名和部门,并恢复部门列表
- formParams.value.staffNo = '';
- formParams.value.userName = '';
- formParams.value.deptId = undefined;
- formParams.value.deptName = '';
- departmentArr.value = sourceDepartArr.value;
- } else {
- // 切换到选择模式时,清空工号、姓名和部门
- formParams.value.staffNo = '';
- formParams.value.userName = '';
- formParams.value.deptId = undefined;
- formParams.value.deptName = '';
- }
- };
- // 递归查找树结构中的节点
- const findNodeInTree = (tree: any[], value: string | number): any => {
- for (const node of tree) {
- // 检查当前节点
- if (node.value === value) {
- return node;
- }
- // 检查子节点(如果有)
- if (node.children && node.children.length > 0) {
- const foundNode = findNodeInTree(node.children, value);
- if (foundNode) {
- return foundNode;
- }
- }
- }
- return null;
- };
- const handleChangeStaffNo = (value) => {
- const findUser = findUserByWorkNo(OrganizationSourceData.value, value);
- const deptId = Number(findOrgCodeByWorkNo(OrganizationSourceData.value, value));
- const dept = findNodeInTree(departmentArr.value, deptId);
- if (findUser) {
- formParams.value.staffNo = findUser.idtUserWorkNo;
- formParams.value.userName = findUser.appAccountAccountName;
- formParams.value.deptId = deptId;
- formParams.value.deptName = dept ? dept.label : '';
- }
- };
- const handleChangeAccessTimeRange = () => {
- console.log('accessTimeRange', formParams.value.accessTimeRange);
- if (formParams.value.accessTimeRange && formParams.value.accessTimeRange.length === 2) {
- formParams.value.accessStartTime = formParams.value.accessTimeRange[0];
- formParams.value.accessEndTime = formParams.value.accessTimeRange[1];
- }
- };
- // 格式化审批单图片
- const formatApprovalImage = async (file: File) => {
- if (!file) return '';
- const fileName = file.name;
- const res = await uploadFileApi({ bizType: UPLOAD_BIZ_TYPE.ATTACHMENT, fileName, file });
- return res.url;
- };
- const handleApprovalUploadChange = async () => {
- approvalImages.value = uploadImagesRef.value!.getUploadedImages();
- if (approvalImages.value && approvalImages.value.length > 0) {
- const image = approvalImages.value[0]; // 只取第一张图片
- if (!image.file && image.url) {
- // 如果已有URL,直接使用
- formParams.value.approvalFormUrl = image.url;
- } else if (image.file) {
- // 如果有新文件,上传后使用新URL
- const url = await formatApprovalImage(image.file);
- formParams.value.approvalFormUrl = url;
- }
- } else {
- // 如果没有图片,清空URL
- formParams.value.approvalFormUrl = '';
- }
- // 手动触发审批单字段的校验
- if (formRef.value) {
- formRef.value.validateField('approvalFormUrl');
- }
- };
- // 部门过滤函数
- const filterDept = (val: string, data: any) => {
- return data.label.includes(val);
- };
- // 初始化部门列表
- const initDepartmentList = () => {
- const departmentList = ref<{ value: string | number; label: string }[]>([]);
- getAllDepartments().then((res) => {
- departmentList.value = calculateTreeData(res, { level: 10, valueKey: 'id', labelKey: 'deptName' }, 1);
- sourceDepartArr.value = departmentList.value;
- departmentArr.value = departmentList.value;
- });
- };
- const handleCloseDrawer = () => {
- emits('close');
- };
- const handleSubmitForm = async (formEl: FormInstance | undefined) => {
- if (!formEl) return;
- // 处理调阅时段
- if (formParams.value.accessTimeRange && formParams.value.accessTimeRange.length === 2) {
- formParams.value.accessStartTime = formParams.value.accessTimeRange[0];
- formParams.value.accessEndTime = formParams.value.accessTimeRange[1];
- }
- await formEl.validate((valid) => {
- if (!valid) return;
- if (props.type === 'add') {
- addSurveillanceInfo(formParams.value).then(() => {
- ElMessage.success('添加成功');
- handleCloseDrawer();
- });
- } else {
- updateSurveillanceInfo(formParams.value).then(() => {
- ElMessage.success('编辑成功');
- handleCloseDrawer();
- });
- }
- });
- };
- watch(
- () => props.initialData,
- (newData) => {
- if (newData) {
- formParams.value = { ...newData, accessTimeRange: ['', ''] };
- // 处理调阅时段
- if (newData.accessStartTime && newData.accessEndTime) {
- formParams.value.accessTimeRange = [newData.accessStartTime, newData.accessEndTime];
- }
- // 处理审批单图片 - 直接使用URL字符串
- // approvalFormUrl 已经是字符串格式,不需要额外处理
- // 如果有工号,尝试查询用户信息
- if (newData.staffNo) {
- remoteMethod(newData.staffNo);
- }
- // 编辑模式下,记录人字段保持原有数据,不覆盖
- }
- },
- { immediate: true, deep: true },
- );
- onMounted(() => {
- initDepartmentList();
- // 只有在添加模式下才初始化记录人为当前登录用户
- if (props.type === 'add') {
- formParams.value.createdByName = realname;
- }
- });
- </script>
- <style lang="scss" scoped>
- .protocal-select:deep(.el-select-dropdown__wrap) {
- max-height: 600px;
- }
- .text-mode {
- cursor: pointer;
- font-size: 12px;
- margin-left: 4px;
- &:hover {
- text-decoration: underline;
- }
- }
- </style>
|