|
@@ -1,32 +1,53 @@
|
|
|
<template>
|
|
|
<div class="person-files flex flex-col h-full">
|
|
|
- <SearchForm :fields="fields" :params="params"></SearchForm>
|
|
|
+ <SearchForm :fields="fields" :params="params">
|
|
|
+ <template #city="{ item, params }">
|
|
|
+ <select-area v-model="params[item.prop]" :level="2"></select-area>
|
|
|
+ </template>
|
|
|
+ <template #supplier="{ item, params }">
|
|
|
+ <select-supplier v-model="params[item.prop]"></select-supplier>
|
|
|
+ </template>
|
|
|
+ </SearchForm>
|
|
|
<div class="flex-1 page-wrap">
|
|
|
- <t-space size="small">
|
|
|
- <t-button theme="success" @click="handleAdd">新增</t-button>
|
|
|
- <upload-button
|
|
|
- upload-url="/api/upload"
|
|
|
- :button-props="{
|
|
|
- content: '批量导入',
|
|
|
- theme: 'success',
|
|
|
- }"
|
|
|
- ></upload-button>
|
|
|
- <t-button
|
|
|
- theme="success"
|
|
|
- @click="multExport"
|
|
|
- :disabled="!selectedRowKeys.length"
|
|
|
- >批量导出</t-button
|
|
|
- >
|
|
|
- <t-button
|
|
|
- theme="success"
|
|
|
- :disabled="!selectedRowKeys.length"
|
|
|
- @click="handleDestroy"
|
|
|
- >作废</t-button
|
|
|
- >
|
|
|
- </t-space>
|
|
|
+ <div class="flex justify-between items-center">
|
|
|
+ <t-space>
|
|
|
+ <span>在册:{{ statisticsInfo.totalCount }}人</span>
|
|
|
+ <span>无效:{{ statisticsInfo.validCount }}人</span>
|
|
|
+ <span>有效:{{ statisticsInfo.invalidCount }}人</span>
|
|
|
+ <span
|
|
|
+ >实施工程师有效:{{ statisticsInfo.effectEngineerCount }}人</span
|
|
|
+ >
|
|
|
+ <span
|
|
|
+ >区域负责人有效:{{ statisticsInfo.regionCoordinatorCount }}人</span
|
|
|
+ >
|
|
|
+ <span
|
|
|
+ >助理实施工程师有效:{{
|
|
|
+ statisticsInfo.assistantEngineerCount
|
|
|
+ }}人</span
|
|
|
+ >
|
|
|
+ </t-space>
|
|
|
+ <t-space size="small">
|
|
|
+ <t-button theme="success" @click="handleAdd">新增</t-button>
|
|
|
+ <upload-button
|
|
|
+ upload-url="/api/admin/user/archives/import"
|
|
|
+ :button-props="{
|
|
|
+ content: '批量导入',
|
|
|
+ theme: 'success',
|
|
|
+ }"
|
|
|
+ param-file-name="MultipartFile"
|
|
|
+ ></upload-button>
|
|
|
+ <t-button theme="success" @click="multExport">批量导出</t-button>
|
|
|
+ <t-button
|
|
|
+ theme="success"
|
|
|
+ :disabled="!selectedRowKeys.length"
|
|
|
+ @click="handleDestroy"
|
|
|
+ >作废</t-button
|
|
|
+ >
|
|
|
+ </t-space>
|
|
|
+ </div>
|
|
|
<t-table
|
|
|
size="small"
|
|
|
- row-key="id"
|
|
|
+ row-key="userArchivesId"
|
|
|
:columns="columns"
|
|
|
:data="tableData"
|
|
|
bordered
|
|
@@ -41,6 +62,49 @@
|
|
|
select-on-row-click
|
|
|
@select-change="selectChange"
|
|
|
>
|
|
|
+ <template #archives-time="{ col, row }">
|
|
|
+ {{ timestampFilter(row[col.colKey]) }}
|
|
|
+ </template>
|
|
|
+ <template #valid-time="{ col, row }">
|
|
|
+ {{ timestampFilter(row[col.colKey]) }}
|
|
|
+ </template>
|
|
|
+ <template #gender="{ col, row }">
|
|
|
+ {{ genderTypeFilter(row[col.colKey]) }}
|
|
|
+ </template>
|
|
|
+ <template #education="{ col, row }">
|
|
|
+ {{ educationTypeFilter(row[col.colKey]) }}
|
|
|
+ </template>
|
|
|
+ <template #status="{ col, row }">
|
|
|
+ {{ authenticationStatusFilter(row[col.colKey]) }}
|
|
|
+ </template>
|
|
|
+ <template #remain-day="{ row }">
|
|
|
+ <span>
|
|
|
+ {{
|
|
|
+ dayCountFilter(row.authenticationValidTime - row.archivesTime)
|
|
|
+ }}天
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ <template #photo="{ col, row }">
|
|
|
+ <t-image
|
|
|
+ :src="row[col.colKey]"
|
|
|
+ fit="contain"
|
|
|
+ :style="{ width: '100px', height: '100px' }"
|
|
|
+ ></t-image>
|
|
|
+ </template>
|
|
|
+ <template #roles="{ row }">
|
|
|
+ {{
|
|
|
+ row.roleTypeList
|
|
|
+ .map((item) => authenticationRoleFilter(item))
|
|
|
+ .join(',')
|
|
|
+ }}
|
|
|
+ </template>
|
|
|
+ <template #operate="{ row }">
|
|
|
+ <div class="table-operations" @click.stop>
|
|
|
+ <t-link theme="primary" hover="color" @click="handleEdit(row)">
|
|
|
+ 修改
|
|
|
+ </t-link>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
</t-table>
|
|
|
</div>
|
|
|
|
|
@@ -53,111 +117,68 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="jsx" name="PersonFiles">
|
|
|
-import { ref, reactive } from 'vue';
|
|
|
+import { ref, reactive, computed, onMounted } from 'vue';
|
|
|
+import { omit } from 'lodash';
|
|
|
+
|
|
|
import { DialogPlugin, MessagePlugin } from 'tdesign-vue-next';
|
|
|
import useFetchTable from '@/hooks/useFetchTable';
|
|
|
import AddPersonFileDialog from './add-person-file-dialog';
|
|
|
import {
|
|
|
personFilesListApi,
|
|
|
+ personFilesStatisticsApi,
|
|
|
personFilesDestroyApi,
|
|
|
personFilesExportApi,
|
|
|
} from '@/api/resource-guard';
|
|
|
+import { dictToOptionList } from '@/utils/tool';
|
|
|
+import { AUTHENTICATION_ROLE, AUTHENTICATION_STATUS } from '@/config/constants';
|
|
|
+import {
|
|
|
+ authenticationRoleFilter,
|
|
|
+ authenticationStatusFilter,
|
|
|
+ timestampFilter,
|
|
|
+ dayCountFilter,
|
|
|
+ genderTypeFilter,
|
|
|
+ educationTypeFilter,
|
|
|
+} from '@/utils/filter';
|
|
|
|
|
|
const curRow = ref(null);
|
|
|
const showAddPersonFileDialog = ref(false);
|
|
|
|
|
|
-const columns = [
|
|
|
- {
|
|
|
- colKey: 'row-select',
|
|
|
- type: 'multiple',
|
|
|
- width: 50,
|
|
|
- fixed: 'left',
|
|
|
- },
|
|
|
- { colKey: 'a', title: '档案流水号' },
|
|
|
- { colKey: 'b', title: '姓名' },
|
|
|
- { colKey: 'c', title: '省份' },
|
|
|
- { colKey: 'd', title: '城市' },
|
|
|
- { colKey: 'e', title: '区县' },
|
|
|
- { colKey: 'f', title: '性别' },
|
|
|
- { colKey: 'g', title: '年龄' },
|
|
|
- { colKey: 'h', title: '身份证号' },
|
|
|
- { colKey: 'i', title: '学历' },
|
|
|
- { colKey: 'j', title: '手机号' },
|
|
|
- { colKey: 'k', title: '电子邮箱' },
|
|
|
- { colKey: 'l', title: '底照' },
|
|
|
- { colKey: 'm', title: '供应商' },
|
|
|
- { colKey: 'n', title: '入档时间' },
|
|
|
- { colKey: 'o', title: '认证项目角色', width: 110 },
|
|
|
- { colKey: 'p', title: '认证分数' },
|
|
|
- { colKey: 'q', title: '认证有效期' },
|
|
|
- { colKey: 'r', title: '剩余有效天数', width: 110 },
|
|
|
- { colKey: 's', title: '认证状态' },
|
|
|
- { colKey: 't', title: '备注' },
|
|
|
- {
|
|
|
- title: '操作',
|
|
|
- colKey: 'operate',
|
|
|
- fixed: 'right',
|
|
|
- width: 80,
|
|
|
- align: 'center',
|
|
|
- cell: (h, { row }) => {
|
|
|
- return (
|
|
|
- <div class="table-operations">
|
|
|
- <t-link
|
|
|
- theme="primary"
|
|
|
- hover="color"
|
|
|
- onClick={(e) => {
|
|
|
- e.stopPropagation();
|
|
|
- handleEdit(row);
|
|
|
- }}
|
|
|
- >
|
|
|
- 修改
|
|
|
- </t-link>
|
|
|
- </div>
|
|
|
- );
|
|
|
- },
|
|
|
- },
|
|
|
-];
|
|
|
-const { pagination, tableData, fetchData, search, onChange } = useFetchTable(
|
|
|
- personFilesListApi,
|
|
|
- {
|
|
|
- fetchDataHandle: () => {
|
|
|
- selectedRowKeys.value = [];
|
|
|
- },
|
|
|
- }
|
|
|
-);
|
|
|
-
|
|
|
-const selectedRowKeys = ref([]);
|
|
|
-const selectChange = (value, { selectedRowData }) => {
|
|
|
- selectedRowKeys.value = value;
|
|
|
-};
|
|
|
-
|
|
|
const fields = ref([
|
|
|
{
|
|
|
- prop: 'a',
|
|
|
+ prop: 'city',
|
|
|
label: '区域',
|
|
|
labelWidth: 100,
|
|
|
type: 'select',
|
|
|
colSpan: 5,
|
|
|
+ cell: 'city',
|
|
|
},
|
|
|
{
|
|
|
- prop: 'b',
|
|
|
+ prop: 'supplierId',
|
|
|
label: '供应商',
|
|
|
labelWidth: 100,
|
|
|
type: 'select',
|
|
|
colSpan: 5,
|
|
|
+ cell: 'supplier',
|
|
|
},
|
|
|
{
|
|
|
- prop: 'c',
|
|
|
+ prop: 'archivesName',
|
|
|
label: '姓名',
|
|
|
labelWidth: 100,
|
|
|
colSpan: 5,
|
|
|
+ attrs: {
|
|
|
+ clearable: true,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
- prop: 'd',
|
|
|
+ prop: 'roleType',
|
|
|
label: '认证角色',
|
|
|
labelWidth: 140,
|
|
|
type: 'select',
|
|
|
colSpan: 6,
|
|
|
+ options: dictToOptionList(AUTHENTICATION_ROLE),
|
|
|
+ attrs: {
|
|
|
+ clearable: true,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
type: 'buttons',
|
|
@@ -169,40 +190,127 @@ const fields = ref([
|
|
|
text: '查询',
|
|
|
onClick: () => {
|
|
|
search();
|
|
|
+ getStatisticsInfo();
|
|
|
},
|
|
|
},
|
|
|
],
|
|
|
},
|
|
|
{
|
|
|
- prop: 'e',
|
|
|
+ prop: 'authenticationStatus',
|
|
|
label: '认证状态',
|
|
|
labelWidth: 100,
|
|
|
type: 'select',
|
|
|
colSpan: 5,
|
|
|
+ options: dictToOptionList(AUTHENTICATION_STATUS),
|
|
|
+ attrs: {
|
|
|
+ clearable: true,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
- prop: 'f',
|
|
|
+ prop: 'archivesTime',
|
|
|
label: '入档时间',
|
|
|
labelWidth: 100,
|
|
|
type: 'daterange',
|
|
|
colSpan: 10,
|
|
|
+ attrs: {
|
|
|
+ clearable: true,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
- prop: 'g',
|
|
|
+ prop: 'remainValidDay',
|
|
|
label: '剩余有效天数:≥',
|
|
|
labelWidth: 140,
|
|
|
colSpan: 6,
|
|
|
+ type: 'number',
|
|
|
},
|
|
|
]);
|
|
|
const params = reactive({
|
|
|
- a: '',
|
|
|
- b: '',
|
|
|
- c: '',
|
|
|
- d: '',
|
|
|
- e: '',
|
|
|
- f: [],
|
|
|
- g: '',
|
|
|
+ city: '',
|
|
|
+ supplierId: '',
|
|
|
+ archivesName: '',
|
|
|
+ roleType: '',
|
|
|
+ authenticationStatus: '',
|
|
|
+ archivesTime: [],
|
|
|
+ remainValidDay: null,
|
|
|
});
|
|
|
+const computedParams = computed(() => {
|
|
|
+ let data = omit(params, ['archivesTime']);
|
|
|
+ data.archivesTimeStart = params.archivesTime[0];
|
|
|
+ data.archivesTimeEnd = params.archivesTime[1];
|
|
|
+ return data;
|
|
|
+});
|
|
|
+
|
|
|
+const columns = [
|
|
|
+ {
|
|
|
+ colKey: 'row-select',
|
|
|
+ type: 'multiple',
|
|
|
+ width: 50,
|
|
|
+ fixed: 'left',
|
|
|
+ },
|
|
|
+ { colKey: 'userArchivesId', title: '档案流水号' },
|
|
|
+ { colKey: 'name', title: '姓名' },
|
|
|
+ { colKey: 'province', title: '省份' },
|
|
|
+ { colKey: 'city', title: '城市' },
|
|
|
+ { colKey: 'area', title: '区县' },
|
|
|
+ { colKey: 'gender', title: '性别', cell: 'gender', width: 60 },
|
|
|
+ { colKey: 'age', title: '年龄', width: 60 },
|
|
|
+ { colKey: 'identity', title: '身份证号', width: 160 },
|
|
|
+ { colKey: 'education', title: '学历', cell: 'education' },
|
|
|
+ { colKey: 'mobileNumber', title: '手机号', width: 120 },
|
|
|
+ { colKey: 'email', title: '电子邮箱' },
|
|
|
+ { colKey: 'basePhotoPath', title: '底照', cell: 'photo', width: 120 },
|
|
|
+ { colKey: 'supplierName', title: '供应商' },
|
|
|
+ {
|
|
|
+ colKey: 'archivesTime',
|
|
|
+ title: '入档时间',
|
|
|
+ cell: 'archives-time',
|
|
|
+ width: 170,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ colKey: 'roleTypeList',
|
|
|
+ title: '认证项目角色',
|
|
|
+ cell: 'roles',
|
|
|
+ minWidth: 110,
|
|
|
+ },
|
|
|
+ { colKey: 'authenticationScore', title: '认证分数' },
|
|
|
+ {
|
|
|
+ colKey: 'authenticationValidTime',
|
|
|
+ title: '认证有效期',
|
|
|
+ cell: 'valid-time',
|
|
|
+ width: 170,
|
|
|
+ },
|
|
|
+ { colKey: 'r', title: '剩余有效天数', cell: 'remainDay', width: 110 },
|
|
|
+ { colKey: 'authenticationStatus', title: '认证状态', cell: 'status' },
|
|
|
+ { colKey: 'remark', title: '备注' },
|
|
|
+ {
|
|
|
+ title: '操作',
|
|
|
+ colKey: 'operate',
|
|
|
+ cell: 'operate',
|
|
|
+ fixed: 'right',
|
|
|
+ width: 80,
|
|
|
+ align: 'center',
|
|
|
+ },
|
|
|
+];
|
|
|
+const { pagination, tableData, fetchData, search, onChange } = useFetchTable(
|
|
|
+ personFilesListApi,
|
|
|
+ {
|
|
|
+ fetchDataHandle: () => {
|
|
|
+ selectedRowKeys.value = [];
|
|
|
+ },
|
|
|
+ params: computedParams,
|
|
|
+ }
|
|
|
+);
|
|
|
+
|
|
|
+let statisticsInfo = ref({});
|
|
|
+const getStatisticsInfo = async () => {
|
|
|
+ const res = await personFilesStatisticsApi(params);
|
|
|
+ statisticsInfo.value = res || {};
|
|
|
+};
|
|
|
+
|
|
|
+const selectedRowKeys = ref([]);
|
|
|
+const selectChange = (value) => {
|
|
|
+ selectedRowKeys.value = value;
|
|
|
+};
|
|
|
|
|
|
const handleAdd = () => {
|
|
|
curRow.value = null;
|
|
@@ -235,23 +343,21 @@ const handleDestroy = () => {
|
|
|
});
|
|
|
};
|
|
|
const multExport = () => {
|
|
|
- if (!selectedRowKeys.value.length) {
|
|
|
- MessagePlugin.error('请选择要作废的记录');
|
|
|
- return;
|
|
|
- }
|
|
|
const confirmDia = DialogPlugin({
|
|
|
header: '操作提示',
|
|
|
- body: `确定要导出选择的所有记录吗?`,
|
|
|
+ body: `确定要导出所有记录吗?`,
|
|
|
confirmBtn: '确定',
|
|
|
cancelBtn: '取消',
|
|
|
onConfirm: async () => {
|
|
|
confirmDia.hide();
|
|
|
- const res = await personFilesExportApi(selectedRowKeys.value).catch(
|
|
|
- () => {}
|
|
|
- );
|
|
|
+ const res = await personFilesExportApi(computedParams).catch(() => {});
|
|
|
if (!res) return;
|
|
|
MessagePlugin.success('开始下载');
|
|
|
},
|
|
|
});
|
|
|
};
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ getStatisticsInfo();
|
|
|
+});
|
|
|
</script>
|