EvaluationSystemAdvancedPerson.vue 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  1. <template>
  2. <div class="safety-platform-container">
  3. <header class="safety-platform-container__header">
  4. <div class="evaluation-header">
  5. <h1 class="evaluation-title">{{ evaluationDetail.exName || '先进个人信息' }}</h1>
  6. <div class="evaluation-meta">
  7. <span>考核部门: {{ evaluationDetail.deptNames || '-' }}</span>
  8. <span>创建人: {{ evaluationDetail.createdUserName || '-' }}</span>
  9. <span>创建时间: {{ formatDateTime(evaluationDetail.createdAt) || '-' }}</span>
  10. </div>
  11. </div>
  12. </header>
  13. <main class="safety-platform-container__main">
  14. <div class="search-table-container">
  15. <header>
  16. <div class="act-search">
  17. <section class="select-box">
  18. <div class="select-box--item">
  19. <span>部门:</span>
  20. <el-cascader
  21. ref="deptCascaderRef"
  22. v-model="deptId"
  23. :options="deptTree"
  24. :props="cascaderDeptProp"
  25. :show-all-levels="false"
  26. placeholder="请选择部门"
  27. filterable
  28. clearable
  29. @change="handleDeptChange"
  30. />
  31. </div>
  32. <div class="select-box--item">
  33. <span>员工工号/名称:</span>
  34. <el-input
  35. v-model="tableQuery.queryParam.userName"
  36. placeholder="搜索员工工号或名称"
  37. class="act-search-input"
  38. />
  39. </div>
  40. <div class="select-box--item">
  41. <span>时间范围:</span>
  42. <el-date-picker
  43. v-model="tableQuery.queryParam.dateRange"
  44. type="daterange"
  45. range-separator="至"
  46. start-placeholder="开始日期"
  47. end-placeholder="结束日期"
  48. value-format="YYYY-MM-DD"
  49. format="YYYY-MM-DD"
  50. />
  51. </div>
  52. </section>
  53. <section class="search-btn">
  54. <el-button type="primary" @click="handleSearch">查询</el-button>
  55. <el-button @click="handleReset">重置</el-button>
  56. <el-button type="primary" @click="openAddDialog">
  57. 添加
  58. </el-button>
  59. <el-button plain class="search-table-container--button" @click="handleExport">
  60. 导出
  61. </el-button>
  62. </section>
  63. </div>
  64. </header>
  65. <div class="batch-table">
  66. <BasicTable
  67. ref="basicTableRef"
  68. :tableData="tableData"
  69. :tableConfig="tableConfig"
  70. @update:pageSize="handleSizeChange"
  71. @update:pageNumber="handleCurrentChange"
  72. >
  73. <template #action="scope">
  74. <div class="action-container--div" style="justify-content: left">
  75. <ActionButton text="编辑" @click="handleEdit(scope.row)" />
  76. <ActionButton text="删除" @click="handleDelete(scope.row)" />
  77. </div>
  78. </template>
  79. </BasicTable>
  80. </div>
  81. </div>
  82. </main>
  83. <!-- 添加/编辑先进个人对话框 -->
  84. <el-dialog
  85. v-model="addDialogVisible"
  86. :title="`${isEditMode ? '编辑' : '新增'}先进个人`"
  87. width="800px"
  88. :close-on-click-modal="false"
  89. @close="handleDialogClose"
  90. >
  91. <div class="add-dialog-content">
  92. <div class="description">
  93. <span class="description-label">说明:</span>
  94. <span class="description-text">
  95. 评为先进集体部门,先进个人可以申报两位员工。非先进集体部门,只能申报一位员工为先进个人。
  96. </span>
  97. </div>
  98. <!-- 普通部门表单 -->
  99. <el-form
  100. v-if="deptType === 'normal'"
  101. ref="normalFormRef"
  102. :model="normalForm"
  103. :rules="normalFormRules"
  104. label-width="140px"
  105. >
  106. <el-form-item label="所属部门:">
  107. <el-cascader
  108. v-model="currentDeptId"
  109. :options="deptTree"
  110. :props="cascaderDeptProp"
  111. :show-all-levels="false"
  112. placeholder="请选择所属部门"
  113. filterable
  114. clearable
  115. style="width: 100%"
  116. />
  117. </el-form-item>
  118. <el-form-item label="员工工号:" prop="employeeCode">
  119. <el-input
  120. v-model="normalForm.employeeCode"
  121. placeholder="请输入员工工号"
  122. maxlength="50"
  123. />
  124. </el-form-item>
  125. <el-form-item label="员工姓名:" prop="employeeName">
  126. <el-input
  127. v-model="normalForm.employeeName"
  128. placeholder="请输入员工姓名"
  129. maxlength="50"
  130. />
  131. </el-form-item>
  132. <el-form-item label="员工联系方式:" prop="employeeContact">
  133. <el-input
  134. v-model="normalForm.employeeContact"
  135. placeholder="请输入11位手机号码"
  136. maxlength="11"
  137. @input="handlePhoneInput"
  138. />
  139. </el-form-item>
  140. <el-form-item label="个人先进描述:" prop="remark">
  141. <el-input
  142. v-model="normalForm.remark"
  143. type="textarea"
  144. :rows="4"
  145. placeholder="请填写个人先进获取内容描述。"
  146. maxlength="300"
  147. show-word-limit
  148. />
  149. </el-form-item>
  150. </el-form>
  151. <!-- 先进集体部门表格表单(暂不使用) -->
  152. <!--
  153. <div v-if="deptType === 'advanced'">
  154. <el-table :data="advancedFormList" border style="width: 100%">
  155. <el-table-column label="编号" width="80" align="center">
  156. <template #default="{ $index }">
  157. {{ $index + 1 }}
  158. </template>
  159. </el-table-column>
  160. <el-table-column label="员工工号" prop="employeeCode">
  161. <template #default="{ row, $index }">
  162. <el-input
  163. v-model="row.employeeCode"
  164. placeholder="请输入..."
  165. maxlength="50"
  166. />
  167. </template>
  168. </el-table-column>
  169. <el-table-column label="员工姓名" prop="employeeName">
  170. <template #default="{ row }">
  171. <el-input
  172. v-model="row.employeeName"
  173. placeholder="请输入..."
  174. maxlength="50"
  175. />
  176. </template>
  177. </el-table-column>
  178. <el-table-column label="员工联系方式" prop="employeeContact">
  179. <template #default="{ row }">
  180. <el-input
  181. v-model="row.employeeContact"
  182. placeholder="请输入11位手机号码"
  183. maxlength="11"
  184. @input="(val) => handlePhoneInputForTable(row, val)"
  185. />
  186. </template>
  187. </el-table-column>
  188. <el-table-column label="个人先进描述" prop="remark">
  189. <template #default="{ row }">
  190. <el-input
  191. v-model="row.remark"
  192. type="textarea"
  193. :rows="2"
  194. placeholder="请输入..."
  195. maxlength="300"
  196. />
  197. </template>
  198. </el-table-column>
  199. <el-table-column label="操作" width="150" align-center>
  200. <template #default="{ $index }">
  201. <el-button
  202. type="primary"
  203. link
  204. :disabled="advancedFormList.length >= 2"
  205. @click="handleAddAdvancedRow"
  206. >
  207. 新增
  208. </el-button>
  209. <el-button
  210. type="danger"
  211. link
  212. @click="handleRemoveAdvancedRow($index)"
  213. >
  214. 删除
  215. </el-button>
  216. </template>
  217. </el-table-column>
  218. </el-table>
  219. </div>
  220. -->
  221. </div>
  222. <template #footer>
  223. <div class="dialog-footer">
  224. <el-button @click="handleDialogClose">取消</el-button>
  225. <el-button type="primary" @click="handleSave">保存</el-button>
  226. </div>
  227. </template>
  228. </el-dialog>
  229. </div>
  230. </template>
  231. <script lang="ts" setup>
  232. import { computed, onMounted, reactive, ref } from 'vue';
  233. import { useRoute } from 'vue-router';
  234. import { ElMessage, ElMessageBox } from 'element-plus';
  235. import type { FormInstance, FormRules } from 'element-plus';
  236. import BasicTable from '@/components/BasicTable.vue';
  237. import useTableConfig from '@/hooks/useTableConfigHook';
  238. import ActionButton from '@/components/ActionButton.vue';
  239. import { TABLE_OPTIONS } from '../../evaluationSystem/configs/tables';
  240. import { EVALUATION_ADVANCED_PERSON_TABLE_COLUMNS } from '../../evaluationSystem/configs/targetTables';
  241. import type { QueryPageRequest } from '@/types/basic-query';
  242. import {
  243. querySecurityExamineIssueAdvancedUser,
  244. querySecurityExamineDetail,
  245. saveSecurityExamineAdvUserAdmin,
  246. updateSecurityExamineAdvUserAdmin,
  247. deleteSecurityExamineDeptAdvUser,
  248. querySecurityExamineAdvUser,
  249. } from '@/api/evaluationSystem';
  250. import type {
  251. QuerySecurityExamineIssueAdvancedUserParams,
  252. EvaluationDeptAdvancedUserItem,
  253. EvaluationSystemItem,
  254. SaveSecurityExamineAdvUserAdminRequest,
  255. UpdateSecurityExamineAdvUserAdminRequest,
  256. } from '@/api/evaluationSystem';
  257. import { getAllDepartments } from '@/api/auth/dept';
  258. import type { DeptTree } from '@/types/dept/type';
  259. const route = useRoute();
  260. // 表格
  261. const basicTableRef = ref<InstanceType<typeof BasicTable>>();
  262. const { tableConfig, pagination } = useTableConfig(EVALUATION_ADVANCED_PERSON_TABLE_COLUMNS, TABLE_OPTIONS);
  263. const tableData = ref<any[]>([]);
  264. const tableQuery = reactive<QueryPageRequest<any>>({
  265. pageNumber: pagination.pageNumber,
  266. pageSize: pagination.pageSize,
  267. queryParam: {
  268. deptName: '',
  269. userName: '',
  270. dateRange: null as any,
  271. startTime: '',
  272. endTime: '',
  273. },
  274. });
  275. // 部门树(复用物品领取记录的部门下拉框逻辑)
  276. const deptCascaderRef = ref();
  277. const deptTree = ref<DeptTree[]>([]);
  278. const deptId = ref<number | null>(null);
  279. const cascaderDeptProp = {
  280. checkStrictly: true,
  281. expandTrigger: 'hover' as const,
  282. value: 'id',
  283. label: 'deptName',
  284. emitPath: false,
  285. };
  286. const getDeptTreeData = async () => {
  287. try {
  288. const res = await getAllDepartments();
  289. deptTree.value = res?.[0]?.children ?? [];
  290. } catch (e) {
  291. console.error('获取部门树失败:', e);
  292. }
  293. };
  294. const handleDeptChange = () => {
  295. const nodes = deptCascaderRef.value?.getCheckedNodes?.();
  296. tableQuery.queryParam.deptName = nodes?.[0]?.label ?? '';
  297. };
  298. // 从路由获取考核对象ID(psemId)
  299. const evaluationId = computed(() => {
  300. const id = route.query.id;
  301. return id ? Number(id) : undefined;
  302. });
  303. // 考核表详情
  304. const evaluationDetail = ref<Partial<EvaluationSystemItem>>({});
  305. const psemId = ref<number | undefined>(undefined); // 考核表ID(从接口获取)
  306. const deptUserId = ref<number | undefined>(undefined); // 部门用户ID(从接口获取)
  307. const currentDeptId = ref<number | undefined>(undefined); // 当前部门ID(用于保存操作)
  308. // 添加对话框相关
  309. const addDialogVisible = ref(false); // 添加对话框
  310. const deptType = ref<'normal' | 'advanced'>('normal'); // 当前部门类型
  311. const isEditMode = ref(false); // 是否为编辑模式
  312. const currentEditRow = ref<any>(null); // 当前编辑的行数据
  313. const editDetailData = ref<EvaluationDeptAdvancedUserItem | null>(null); // 编辑时的详情数据
  314. // 普通部门表单
  315. const normalFormRef = ref<FormInstance>();
  316. const normalForm = reactive({
  317. employeeCode: '',
  318. employeeName: '',
  319. employeeContact: '',
  320. remark: '',
  321. });
  322. const normalFormRules: FormRules = {
  323. employeeCode: [
  324. { required: true, message: '请输入员工工号', trigger: 'blur' },
  325. ],
  326. employeeName: [
  327. { required: true, message: '请输入员工姓名', trigger: 'blur' },
  328. ],
  329. employeeContact: [
  330. { required: true, message: '请输入员工联系方式', trigger: 'blur' },
  331. { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的11位手机号码', trigger: 'blur' },
  332. ],
  333. remark: [
  334. { required: true, message: '请输入个人先进描述', trigger: 'blur' },
  335. { max: 300, message: '最多输入300个字符', trigger: 'blur' },
  336. ],
  337. };
  338. // 先进集体部门表单列表
  339. const advancedFormList = ref<Array<{
  340. employeeCode: string;
  341. employeeName: string;
  342. employeeContact: string;
  343. remark: string;
  344. }>>([
  345. {
  346. employeeCode: '',
  347. employeeName: '',
  348. employeeContact: '',
  349. remark: '',
  350. },
  351. ]);
  352. // 打开新增先进个人(普通部门)弹窗
  353. const openAddDialog = () => {
  354. deptType.value = 'normal';
  355. isEditMode.value = false;
  356. currentEditRow.value = null;
  357. editDetailData.value = null;
  358. // 重置部门与表单
  359. currentDeptId.value = undefined;
  360. if (normalFormRef.value) {
  361. normalFormRef.value.resetFields();
  362. }
  363. normalForm.employeeCode = '';
  364. normalForm.employeeName = '';
  365. normalForm.employeeContact = '';
  366. normalForm.remark = '';
  367. addDialogVisible.value = true;
  368. };
  369. const handleSizeChange = (value: number) => {
  370. pagination.pageSize = value;
  371. tableQuery.pageSize = value;
  372. getTableData();
  373. };
  374. const handleCurrentChange = (value: number) => {
  375. pagination.pageNumber = value;
  376. tableQuery.pageNumber = value;
  377. getTableData();
  378. };
  379. async function getTableData() {
  380. tableConfig.loading = true;
  381. try {
  382. const params: QuerySecurityExamineIssueAdvancedUserParams = {
  383. pageNumber: tableQuery.pageNumber,
  384. pageSize: tableQuery.pageSize,
  385. queryParam: {
  386. psemId: evaluationId.value, // 考核表ID(从路由参数获取)
  387. deptName: tableQuery.queryParam.deptName || undefined,
  388. userName: tableQuery.queryParam.userName || undefined,
  389. planStartTime: tableQuery.queryParam.startTime || undefined,
  390. planEndTime: tableQuery.queryParam.endTime || undefined,
  391. },
  392. };
  393. const res = await querySecurityExamineIssueAdvancedUser(params);
  394. if (res) {
  395. // 映射返回数据字段到表格字段(先进个人信息)
  396. tableData.value = res.records.map((item: EvaluationDeptAdvancedUserItem) => ({
  397. id: item.id, // 记录ID(用于删除等操作)
  398. employeeCode: item.advUserStaffNo || '-', // 员工工号
  399. employeeName: item.advUserName || '-', // 员工姓名
  400. employeeContact: item.advUserLink || '-', // 员工联系方式
  401. deptName: item.deptName || '-', // 所属部门
  402. departmentLeader: item.deptUserName || '-', // 部门负责人
  403. remark: item.remark || '-', // 先进个人描述
  404. reportDate: item.planEndTime || '-', // 上报日期
  405. // 保留原始数据,供编辑等操作使用
  406. originalData: item, // 保存列表接口返回的完整原始数据
  407. }));
  408. pagination.total = res.totalRow;
  409. }
  410. } catch (e) {
  411. console.error('获取先进个人信息列表失败:', e);
  412. tableData.value = [];
  413. pagination.total = 0;
  414. } finally {
  415. tableConfig.loading = false;
  416. }
  417. }
  418. function handleSearch() {
  419. if (tableQuery.queryParam.dateRange && tableQuery.queryParam.dateRange.length === 2) {
  420. tableQuery.queryParam.startTime = tableQuery.queryParam.dateRange[0];
  421. tableQuery.queryParam.endTime = tableQuery.queryParam.dateRange[1];
  422. } else {
  423. tableQuery.queryParam.startTime = '';
  424. tableQuery.queryParam.endTime = '';
  425. }
  426. pagination.pageNumber = 1;
  427. tableQuery.pageNumber = 1;
  428. getTableData();
  429. }
  430. const handleReset = () => {
  431. tableQuery.queryParam.deptName = '';
  432. tableQuery.queryParam.userName = '';
  433. tableQuery.queryParam.dateRange = null;
  434. deptId.value = null;
  435. handleSearch();
  436. };
  437. // 选择部门类型(从下拉菜单触发)
  438. const selectDeptType = (type: 'normal' | 'advanced') => {
  439. deptType.value = type;
  440. addDialogVisible.value = true;
  441. // 如果是先进集体部门,初始化表格数据(默认1行)
  442. if (type === 'advanced') {
  443. advancedFormList.value = [
  444. {
  445. employeeCode: '',
  446. employeeName: '',
  447. employeeContact: '',
  448. remark: '',
  449. },
  450. ];
  451. }
  452. };
  453. // 处理电话号码输入(只允许数字)
  454. const handlePhoneInput = (value: string) => {
  455. // 只保留数字
  456. normalForm.employeeContact = value.replace(/\D/g, '');
  457. };
  458. // 处理表格中电话号码输入(只允许数字)
  459. const handlePhoneInputForTable = (row: any, value: string) => {
  460. // 只保留数字
  461. row.employeeContact = value.replace(/\D/g, '');
  462. };
  463. // 添加先进集体部门行
  464. const handleAddAdvancedRow = () => {
  465. if (advancedFormList.value.length < 2) {
  466. advancedFormList.value.push({
  467. employeeCode: '',
  468. employeeName: '',
  469. employeeContact: '',
  470. remark: '',
  471. });
  472. }
  473. };
  474. // 删除先进集体部门行
  475. const handleRemoveAdvancedRow = (index: number) => {
  476. if (advancedFormList.value.length > 1) {
  477. advancedFormList.value.splice(index, 1);
  478. } else {
  479. ElMessage.warning('至少需要保留一条记录');
  480. }
  481. };
  482. // 关闭对话框
  483. const handleDialogClose = () => {
  484. addDialogVisible.value = false;
  485. isEditMode.value = false;
  486. currentEditRow.value = null;
  487. editDetailData.value = null;
  488. // 重置表单
  489. if (normalFormRef.value) {
  490. normalFormRef.value.resetFields();
  491. }
  492. normalForm.employeeCode = '';
  493. normalForm.employeeName = '';
  494. normalForm.employeeContact = '';
  495. normalForm.remark = '';
  496. advancedFormList.value = [
  497. {
  498. employeeCode: '',
  499. employeeName: '',
  500. employeeContact: '',
  501. remark: '',
  502. },
  503. ];
  504. deptType.value = 'normal';
  505. currentDeptId.value = undefined;
  506. };
  507. // 验证普通部门表单
  508. const validateNormalForm = (): Promise<boolean> => {
  509. return new Promise((resolve) => {
  510. if (!normalFormRef.value) {
  511. resolve(false);
  512. return;
  513. }
  514. normalFormRef.value.validate((valid) => {
  515. resolve(valid);
  516. });
  517. });
  518. };
  519. // 验证先进集体部门表单
  520. const validateAdvancedForm = (): boolean => {
  521. const phonePattern = /^1[3-9]\d{9}$/;
  522. for (let i = 0; i < advancedFormList.value.length; i++) {
  523. const item = advancedFormList.value[i];
  524. if (!item.employeeCode || !item.employeeName || !item.employeeContact || !item.remark) {
  525. ElMessage.warning(`请填写第${i + 1}行的所有必填项`);
  526. return false;
  527. }
  528. if (!phonePattern.test(item.employeeContact)) {
  529. ElMessage.warning(`第${i + 1}行的员工联系方式请输入正确的11位手机号码`);
  530. return false;
  531. }
  532. if (item.remark.length > 300) {
  533. ElMessage.warning(`第${i + 1}行的个人先进描述最多输入300个字符`);
  534. return false;
  535. }
  536. }
  537. return true;
  538. };
  539. // 保存
  540. const handleSave = async () => {
  541. try {
  542. if (isEditMode.value) {
  543. // 编辑模式:直接使用详情接口返回的数据作为更新参数,
  544. // 并用弹窗表单中的输入值覆盖相应字段
  545. if (!editDetailData.value || !editDetailData.value.id) {
  546. ElMessage.error('缺少编辑记录数据,无法保存');
  547. return;
  548. }
  549. const updatePayload: UpdateSecurityExamineAdvUserAdminRequest = {
  550. ...editDetailData.value,
  551. advUserStaffNo: normalForm.employeeCode,
  552. advUserName: normalForm.employeeName,
  553. advUserLink: normalForm.employeeContact,
  554. remark: normalForm.remark,
  555. };
  556. // 编辑模式:调用更新接口
  557. await updateSecurityExamineAdvUserAdmin(updatePayload);
  558. } else {
  559. // 新增模式:psemId 使用路由参数的 id,deptId 使用选择的部门
  560. if (!evaluationId.value || !currentDeptId.value) {
  561. ElMessage.error('缺少必要参数');
  562. return;
  563. }
  564. // 目前仅保留普通部门表单逻辑
  565. // 验证普通部门表单
  566. const isValid = await validateNormalForm();
  567. if (!isValid) {
  568. return;
  569. }
  570. const createPayload: SaveSecurityExamineAdvUserAdminRequest = {
  571. psemId: evaluationId.value,
  572. deptId: currentDeptId.value,
  573. advUserStaffNo: normalForm.employeeCode,
  574. advUserName: normalForm.employeeName,
  575. advUserLink: normalForm.employeeContact,
  576. remark: normalForm.remark,
  577. };
  578. // 新增模式:调用保存接口
  579. await saveSecurityExamineAdvUserAdmin(createPayload);
  580. }
  581. ElMessage.success('保存成功');
  582. handleDialogClose();
  583. getTableData();
  584. } catch (e) {
  585. console.error('保存失败:', e);
  586. ElMessage.error('保存失败');
  587. }
  588. };
  589. const handleEdit = async (row: any) => {
  590. if (!row.id) {
  591. ElMessage.error('缺少记录ID,无法编辑');
  592. return;
  593. }
  594. try {
  595. // 调用管理员端详情接口获取数据
  596. const detail = await querySecurityExamineAdvUser(row.id);
  597. // 保存当前编辑的行数据和详情数据
  598. currentEditRow.value = row;
  599. editDetailData.value = detail;
  600. isEditMode.value = true;
  601. deptType.value = 'normal'; // 编辑时固定为普通部门
  602. addDialogVisible.value = true;
  603. // 回填表单数据(普通部门)- 使用详情数据
  604. currentDeptId.value = detail.deptId || undefined;
  605. normalForm.employeeCode = detail.advUserStaffNo || '';
  606. normalForm.employeeName = detail.advUserName || '';
  607. normalForm.employeeContact = detail.advUserLink || '';
  608. normalForm.remark = detail.remark || '';
  609. } catch (e) {
  610. console.error('获取详情失败:', e);
  611. ElMessage.error('获取详情失败');
  612. }
  613. };
  614. const handleDelete = async (row: any) => {
  615. try {
  616. await ElMessageBox.confirm('确定要删除这条记录吗?', '提示', {
  617. confirmButtonText: '确定',
  618. cancelButtonText: '取消',
  619. type: 'warning',
  620. });
  621. if (!row.id) {
  622. ElMessage.error('缺少记录ID,无法删除');
  623. return;
  624. }
  625. await deleteSecurityExamineDeptAdvUser(row.id);
  626. ElMessage.success('删除成功');
  627. getTableData();
  628. } catch (e: any) {
  629. // 用户取消删除或删除失败
  630. if (e !== 'cancel') {
  631. console.error('删除失败:', e);
  632. ElMessage.error('删除失败');
  633. }
  634. }
  635. };
  636. const handleExport = () => {
  637. // TODO: 导出当前筛选结果
  638. console.log('export advanced person list', tableQuery);
  639. };
  640. // 格式化日期时间
  641. const formatDateTime = (dateTimeStr: string | undefined): string => {
  642. if (!dateTimeStr) return '';
  643. try {
  644. const date = new Date(dateTimeStr);
  645. const year = date.getFullYear();
  646. const month = String(date.getMonth() + 1).padStart(2, '0');
  647. const day = String(date.getDate()).padStart(2, '0');
  648. const hours = String(date.getHours()).padStart(2, '0');
  649. const minutes = String(date.getMinutes()).padStart(2, '0');
  650. const seconds = String(date.getSeconds()).padStart(2, '0');
  651. return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  652. } catch (e) {
  653. return dateTimeStr;
  654. }
  655. };
  656. // 获取考核表详情
  657. const getEvaluationDetail = async () => {
  658. // 路由参数中的id是考核表ID(psemId),直接使用
  659. if (!evaluationId.value) return;
  660. try {
  661. const res = await querySecurityExamineDetail(evaluationId.value);
  662. if (res) {
  663. evaluationDetail.value = {
  664. exName: res.exName,
  665. deptNames: res.deptNames,
  666. createdUserName: res.createdUserName,
  667. createdAt: res.createdAt,
  668. };
  669. // 保存考核表ID,用于提交时使用
  670. psemId.value = res.id;
  671. }
  672. } catch (e) {
  673. console.error('获取考核表详情失败:', e);
  674. }
  675. };
  676. onMounted(() => {
  677. getDeptTreeData();
  678. getTableData();
  679. getEvaluationDetail();
  680. });
  681. </script>
  682. <style scoped lang="scss">
  683. @use '@/styles/page-details-layout.scss' as *;
  684. @use '@/styles/page-main-layout.scss' as *;
  685. @use '@/styles/basic-table-action.scss' as *;
  686. @use '@/styles/basic-table-file.scss' as *;
  687. @use '@/views/traffic/violation/style/act-search-table.scss' as *;
  688. .safety-platform-container__header {
  689. padding-bottom: 0 !important;
  690. }
  691. .evaluation-header {
  692. width: 100%;
  693. }
  694. .evaluation-title {
  695. font-size: 20px;
  696. font-weight: bold;
  697. margin: 0 0 12px 0;
  698. color: #333;
  699. }
  700. .evaluation-meta {
  701. margin-bottom: 12px;
  702. display: flex;
  703. gap: 24px;
  704. font-size: 14px;
  705. color: #666;
  706. }
  707. .evaluation-meta span {
  708. white-space: nowrap;
  709. }
  710. .add-dialog-content {
  711. .description {
  712. margin-bottom: 24px;
  713. padding: 12px;
  714. background-color: #f5f7fa;
  715. border-radius: 4px;
  716. .description-label {
  717. font-weight: bold;
  718. color: #333;
  719. }
  720. .description-text {
  721. color: #666;
  722. line-height: 1.6;
  723. }
  724. }
  725. }
  726. .dialog-footer {
  727. text-align: right;
  728. }
  729. </style>