| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545 |
- <template>
- <div class="app-container backcheck-candidate-page">
- <div class="bg-white p-4 rounded main-box">
- <!-- 顶部工具栏 -->
- <div class="header-bar flex justify-between items-center mb-4">
- <el-input v-model="queryParams.keyword" placeholder="请输入姓名/手机号" style="width: 320px" clearable @keyup.enter="handleQuery">
- <template #append>
- <el-button type="primary" @click="handleQuery">
- <el-icon><i-ep-search /></el-icon>
- </el-button>
- </template>
- </el-input>
- <div class="flex gap-2">
- <el-button type="primary" @click="handleSync">同步至单位</el-button>
- <el-button type="primary" plain @click="handleExport">导出列表</el-button>
- </div>
- </div>
- <!-- 数据表格 -->
- <el-table
- v-loading="loading"
- :data="filteredTableData"
- style="width: 100%"
- header-cell-class-name="custom-header"
- class="custom-table"
- @selection-change="handleSelectionChange"
- >
- <el-table-column type="selection" width="50" align="center" />
- <el-table-column label="姓名" min-width="160">
- <template #default="scope">
- <div class="flex flex-col">
- <el-link type="primary" :underline="false" @click="handleDetail(scope.row)">
- {{ scope.row.name }}
- </el-link>
- <span class="text-xs text-gray-400">{{ scope.row.studentNo }}</span>
- </div>
- </template>
- </el-table-column>
- <el-table-column prop="idType" label="身份证类型" min-width="140" />
- <el-table-column label="身份证号码" min-width="140">
- <template #default="scope">
- <div class="flex items-center gap-2">
- <span>{{ scope.row.idNoDisplay }}</span>
- <el-icon
- v-if="scope.row.idNo && scope.row.idNo !== '****'"
- :class="['cursor-pointer', scope.row.showIdNo ? 'text-primary' : 'text-gray-400']"
- @click="toggleIdNo(scope.row)"
- >
- <i-ep-view v-if="!scope.row.showIdNo" />
- <i-ep-hide v-else />
- </el-icon>
- </div>
- </template>
- </el-table-column>
- <el-table-column prop="mobile" label="手机号" min-width="140" />
- <el-table-column label="状态" min-width="100">
- <template #default="scope">
- <div class="flex items-center">
- <span :class="['status-dot', scope.row.status === '完成' ? 'dot-success' : 'dot-danger']"></span>
- <span>{{ scope.row.status }}</span>
- </div>
- </template>
- </el-table-column>
- <el-table-column label="系统内供职公司" min-width="280">
- <template #default="scope">
- <div class="flex items-center gap-2 flex-wrap">
- <template v-if="scope.row.companies && scope.row.companies.length > 0">
- <template v-for="(comp, index) in scope.row.companies" :key="index">
- <div class="company-tag-wrapper">
- <span class="company-name">{{ comp.name }}</span>
- <span :class="['tag-status', getStatusClass(comp.status)]" @click="handleTagClick(comp, scope.row)">
- {{ comp.status }}
- </span>
- </div>
- </template>
- </template>
- <span v-else>-</span>
- </div>
- </template>
- </el-table-column>
- <el-table-column prop="finishTime" label="完成时间" min-width="180" />
- <el-table-column label="操作" width="220" align="left" fixed="right">
- <template #default="scope">
- <div class="operation-links">
- <el-link type="primary" :underline="false" @click="handleDetail(scope.row)">详情</el-link>
-
- <!-- 情况1:完成状态 -> 显示打款 -->
- <template v-if="scope.row.status === '完成'">
- <el-link type="primary" :underline="false" @click="openPayDialog(scope.row)">打款</el-link>
- </template>
- <!-- 情况2:未完成且有待审核公司 -> 显示审核通过/拒绝、退款 -->
- <template v-else-if="scope.row.status === '未完成' && scope.row.companies && scope.row.companies.length > 0">
- <el-link type="primary" :underline="false" @click="handleAudit(scope.row, '通过')">审核通过</el-link>
- <el-link type="primary" :underline="false" @click="handleAudit(scope.row, '拒绝')">审核拒绝</el-link>
- <el-link type="danger" :underline="false" @click="handleRefund(scope.row)">退款</el-link>
- </template>
- <!-- 情况3:未完成且无供职公司 -> 显示开始核验、退款 -->
- <template v-else-if="scope.row.status === '未完成'">
- <el-link type="primary" :underline="false" @click="handleStartCheck(scope.row)">开始核验</el-link>
- <el-link type="danger" :underline="false" @click="handleRefund(scope.row)">退款</el-link>
- </template>
- </div>
- </template>
- </el-table-column>
- </el-table>
- <!-- 分页栏 -->
- <div class="pagination-wrapper mt-4 flex justify-end">
- <el-pagination
- v-model:current-page="queryParams.pageNum"
- v-model:page-size="queryParams.pageSize"
- :total="total"
- background
- layout="total, sizes, prev, pager, next"
- @size-change="handleSizeChange"
- @current-change="handleCurrentChange"
- />
- </div>
- </div>
- <!-- 弹窗部分 -->
- <el-dialog v-model="rejectDialog.visible" title="审核说明" width="520px" class="custom-dialog">
- <div class="dialog-content">
- <div class="info-row"><span class="label">结果:</span><span class="value">{{ rejectDialog.form.result }}</span></div>
- <div class="info-row mt-4">
- <span class="label">备注:</span>
- <el-input v-model="rejectDialog.form.remark" type="textarea" :rows="4" placeholder="请输入说明" />
- </div>
- </div>
- <template #footer>
- <div class="dialog-footer">
- <el-button @click="rejectDialog.visible = false">取消</el-button>
- <el-button type="primary" @click="confirmReject">确定</el-button>
- </div>
- </template>
- </el-dialog>
- <el-dialog v-model="sendDialog.visible" title="发送至公司" width="520px" class="custom-dialog">
- <div class="dialog-content">
- <div class="info-row"><span class="label">{{ sendDialog.form.companyName }}</span></div>
- <div class="info-row mt-1"><span class="label">总价:</span><span class="value">{{ sendDialog.form.orderNo }}</span></div>
- <div class="info-row mt-4 flex items-center">
- <span class="label required">可获得金额</span>
- <el-input v-model="sendDialog.form.amount" style="width: 200px; margin-left: 10px;">
- <template #suffix>元</template>
- </el-input>
- </div>
- </div>
- <template #footer>
- <div class="dialog-footer">
- <el-button @click="sendDialog.visible = false">取消</el-button>
- <el-button type="primary" @click="confirmSend">确定</el-button>
- </div>
- </template>
- </el-dialog>
- <el-dialog v-model="payDialog.visible" title="打款" width="520px" class="custom-dialog">
- <div class="dialog-content">
- <div class="info-row"><span class="label">{{ payDialog.form.companyName }}</span></div>
- <div class="info-row mt-1"><span class="label">总价:</span><span class="value">{{ payDialog.form.orderNo }}</span></div>
- </div>
- <template #footer>
- <div class="dialog-footer">
- <el-button @click="payDialog.visible = false">取消</el-button>
- <el-button type="primary" @click="confirmPay">确定</el-button>
- </div>
- </template>
- </el-dialog>
- <el-dialog v-model="refundDialog.visible" title="确认退款" width="480px" class="custom-dialog">
- <div class="dialog-content">
- <div class="flex items-center gap-3">
- <el-icon color="#e6a23c" size="24"><i-ep-warning-filled /></el-icon>
- <span class="text-base">确定要为候选人 <span class="font-bold">{{ refundDialog.name }}</span> 办理退款吗?</span>
- </div>
- <div class="mt-4 text-gray-500 text-sm">退款金额将原路返回至下单账户。</div>
- </div>
- <template #footer>
- <div class="dialog-footer">
- <el-button @click="refundDialog.visible = false">取消</el-button>
- <el-button type="danger" @click="confirmRefund">确定退款</el-button>
- </div>
- </template>
- </el-dialog>
- </div>
- </template>
- <script setup lang="ts">
- import { reactive, ref, computed, onMounted } from 'vue';
- import { useRoute, useRouter } from 'vue-router';
- import { ElMessage } from 'element-plus';
- import { listBackRecord } from '@/api/system/backRecord';
- import { BackRecordVO } from '@/api/system/backRecord/types';
- const route = useRoute();
- const router = useRouter();
- const loading = ref(false);
- const total = ref(0);
- const queryParams = reactive({
- pageNum: 1,
- pageSize: 10,
- keyword: '',
- orderId: (route.query.id as string) || '',
- status: ''
- });
- onMounted(() => {
- if (queryParams.orderId) {
- getList();
- }
- });
- // 审核弹窗
- const rejectDialog = reactive({
- visible: false,
- form: {
- id: '',
- result: '',
- remark: ''
- }
- });
- // 发送弹窗
- const sendDialog = reactive({
- visible: false,
- form: {
- id: '',
- companyName: '',
- orderNo: 'ORD20250327001',
- amount: ''
- }
- });
- // 打款弹窗
- const payDialog = reactive({
- visible: false,
- form: {
- id: '',
- companyName: '',
- orderNo: 'ORD20250327001'
- }
- });
- // 退款弹窗
- const refundDialog = reactive({
- visible: false,
- id: '',
- name: ''
- });
- // 状态映射
- const statusMap: Record<string, string> = {
- '0': '待处理',
- '1': '进行中',
- '2': '已完成',
- '3': '失败'
- };
- const tableData = ref<any[]>([]);
- // 搜索过滤逻辑
- const filteredTableData = computed(() => {
- return tableData.value;
- });
- const getList = async () => {
- loading.value = true;
- try {
- const data = await listBackRecord({
- orderId: queryParams.orderId,
- status: queryParams.status || undefined,
- pageNum: queryParams.pageNum,
- pageSize: queryParams.pageSize
- });
-
- console.log('后端返回数据:', data);
-
- if (data && data.rows) {
- // 将后端数据转换为前端表格格式
- tableData.value = data.rows.map((record: BackRecordVO) => {
- const idCard = record.studentIdCard || '****';
- return {
- id: record.id,
- candidateId: record.candidateId,
- orderId: record.orderId,
- name: record.studentName || record.studentNo || `候选人${record.candidateId}`,
- studentNo: record.studentNo,
- idType: '居民身份证',
- idNo: record.studentIdCard || '****',
- idNoDisplay: maskIdCard(record.studentIdCard || '****'),
- showIdNo: false,
- mobile: record.studentMobile || '****',
- status: statusMap[record.status] || record.status,
- companies: [],
- finishTime: record.finishTime || '-',
- reportUrl: record.reportUrl,
- createTime: record.createTime
- };
- });
- total.value = data.total || 0;
- } else {
- tableData.value = [];
- total.value = 0;
- }
- } catch (error) {
- console.error('获取候选人列表失败:', error);
- tableData.value = [];
- total.value = 0;
- } finally {
- loading.value = false;
- }
- };
- // 隐藏身份证号码(显示为*)
- const maskIdCard = (idCard: string): string => {
- if (!idCard || idCard === '****') return '****';
- return idCard.replace(/./g, '*');
- };
- // 切换身份证号码显示/隐藏
- const toggleIdNo = (row: any) => {
- row.showIdNo = !row.showIdNo;
- row.idNoDisplay = row.showIdNo ? row.idNo : maskIdCard(row.idNo);
- };
- const handleQuery = () => { getList(); };
- const handleSelectionChange = () => {};
- const handleSizeChange = () => { getList(); };
- const handleCurrentChange = () => { getList(); };
- const handleDetail = (row: any) => {
- router.push({
- name: 'BackcheckReport',
- query: {
- id: row.id,
- name: row.name,
- status: row.status,
- studentNo: row.studentNo,
- mobile: row.mobile,
- idCard: row.idNo,
- gender: row.studentGender
- }
- });
- };
- const getStatusClass = (status: string) => {
- switch (status) {
- case '通过': return 'status-success';
- case '拒绝': return 'status-danger';
- case '发送': return 'status-primary';
- default: return 'status-info';
- }
- };
- const handleTagClick = (comp: any, row: any) => {
- if (comp.status === '发送') {
- openSendDialog(row, comp);
- } else if (comp.status === '拒绝') {
- handleAudit(row, '拒绝', comp);
- }
- };
- const handleAudit = (row: any, type: string, comp?: any) => {
- rejectDialog.form.id = row.id;
- rejectDialog.form.result = type;
- rejectDialog.form.remark = type === '拒绝' ? '说明说明说明说明说明说明说明说明' : '';
- // 如果是从标签点击进来的,可以记录具体的公司名称(可选,根据需求)
- console.log('正在审核公司:', comp?.name || '全选');
- rejectDialog.visible = true;
- };
- const handleStartCheck = (row: any) => {
- ElMessage.success(`已为候选人 ${row.name} 开始核验`);
- };
- const confirmReject = () => {
- rejectDialog.visible = false;
- ElMessage.success('审核说明已提交');
- };
- const openSendDialog = (row: any, comp?: any) => {
- sendDialog.form.id = row.id;
- sendDialog.form.companyName = comp?.name || row.companies?.[0]?.name || 'XXXXXXXX公司';
- sendDialog.form.amount = '198.00'; // 默认一个金额
- sendDialog.visible = true;
- };
- const confirmSend = () => {
- sendDialog.visible = false;
- ElMessage.success(`已发送至 ${sendDialog.form.companyName}`);
- };
- const openPayDialog = (row: any, comp?: any) => {
- payDialog.form.id = row.id;
- payDialog.form.companyName = comp?.name || row.companies?.[0]?.name || 'XXXXXXXX公司';
- payDialog.visible = true;
- };
- const confirmPay = () => {
- payDialog.visible = false;
- ElMessage.success('打款已确认');
- };
- const handleRefund = (row: any) => {
- refundDialog.id = row.id;
- refundDialog.name = row.name;
- refundDialog.visible = true;
- };
- const confirmRefund = () => {
- refundDialog.visible = false;
- ElMessage.success(`候选人 ${refundDialog.name} 的退款申请已提交`);
- };
- const handleSync = () => {
- loading.value = true;
- setTimeout(() => {
- loading.value = false;
- ElMessage.success('同步至单位成功');
- }, 500);
- };
- const handleExport = () => {
- ElMessage.success('正在导出列表...');
- };
- getList();
- </script>
- <style scoped lang="scss">
- .backcheck-candidate-page {
- padding: 20px;
- background-color: #f0f2f5;
- height: calc(100vh - 84px);
- display: flex;
- flex-direction: column;
- }
- .main-box {
- flex: 1;
- display: flex;
- flex-direction: column;
- overflow: hidden;
- }
- .custom-table {
- flex: 1;
- overflow: hidden;
- :deep(.el-table__inner-wrapper) {
- height: 100% !important;
- }
- }
- .status-dot {
- display: inline-block;
- width: 8px;
- height: 8px;
- border-radius: 50%;
- margin-right: 8px;
- }
- .dot-success { background-color: #67c23a; }
- .dot-danger { background-color: #f56c6c; }
- .company-tag-wrapper {
- display: flex;
- align-items: center;
- border: 1px solid #dcdfe6;
- padding: 0;
- border-radius: 4px;
- background-color: #fff;
- overflow: hidden;
- height: 24px;
- margin: 2px 0;
- }
- .company-name {
- font-size: 12px;
- color: #606266;
- padding: 0 8px;
- }
- .tag-status {
- height: 100%;
- padding: 0 8px;
- font-size: 12px;
- display: flex;
- align-items: center;
- cursor: pointer;
-
- &.status-success { color: #67c23a; background-color: #f0f9eb; }
- &.status-danger { color: #f56c6c; background-color: #fef0f0; }
- &.status-primary { color: #409eff; background-color: #ecf5ff; }
- &.status-info { color: #909399; background-color: #f4f4f5; }
- }
- .operation-links {
- display: flex;
- gap: 12px;
- }
- .custom-table {
- border: none !important;
- :deep(.el-table__inner-wrapper::before) { display: none; }
- }
- :deep(.custom-header th) {
- background-color: #f7f8fa !important;
- color: #4e5969;
- font-weight: 500;
- padding: 12px 0;
- border-bottom: none !important;
- }
- .pagination-wrapper {
- padding: 20px 0;
- background-color: #fff;
- display: flex;
- justify-content: flex-end;
- }
- :deep(.custom-dialog) {
- .el-dialog__header {
- border-bottom: 1px solid #f0f2f5;
- margin-right: 0;
- padding: 15px 20px;
- }
- .el-dialog__body { padding: 20px 40px; }
- .dialog-content {
- .info-row {
- font-size: 14px;
- color: #333;
- .label {
- font-weight: 500;
- &.required::before { content: '*'; color: #f56c6c; margin-right: 4px; }
- }
- }
- }
- .dialog-footer { display: flex; justify-content: flex-end; gap: 12px; }
- }
- </style>
|