Compare commits

...

2 Commits

Author SHA1 Message Date
renjianbo
46e9ade6b5 Merge branch 'dev' of http://101.43.95.130:3001/admin/rlz into dev 2026-05-17 01:13:12 +08:00
renjianbo
8f2d9c337a feat: add certification approve/reject with enhanced UI (#18)
- Add PUT /approve/{id} and PUT /reject/{id} endpoints
- Add state filter dropdown (pending/approved/rejected)
- Add colored status tags and approve/reject action buttons
- Add reject reason dialog and detail view with image previews

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-17 01:13:01 +08:00
2 changed files with 308 additions and 365 deletions

View File

@@ -1,44 +1,61 @@
import request from '@/utils/request' import request from '@/utils/request'
// 查询renzheng列表 // 查询renzheng列表
export function listRenzheng(query) { export function listRenzheng(query) {
return request({ return request({
url: '/system/renzheng/list', url: '/system/renzheng/list',
method: 'get', method: 'get',
params: query params: query
}) })
} }
// 查询renzheng详细 // 查询renzheng详细
export function getRenzheng(id) { export function getRenzheng(id) {
return request({ return request({
url: '/system/renzheng/' + id, url: '/system/renzheng/' + id,
method: 'get' method: 'get'
}) })
} }
// 新增renzheng // 新增renzheng
export function addRenzheng(data) { export function addRenzheng(data) {
return request({ return request({
url: '/system/renzheng', url: '/system/renzheng',
method: 'post', method: 'post',
data: data data: data
}) })
} }
// 修改renzheng // 修改renzheng
export function updateRenzheng(data) { export function updateRenzheng(data) {
return request({ return request({
url: '/system/renzheng', url: '/system/renzheng',
method: 'put', method: 'put',
data: data data: data
}) })
} }
// 删除renzheng // 删除renzheng
export function delRenzheng(id) { export function delRenzheng(id) {
return request({ return request({
url: '/system/renzheng/' + id, url: '/system/renzheng/' + id,
method: 'delete' method: 'delete'
}) })
} }
// 审核通过
export function approveRenzheng(id) {
return request({
url: '/system/renzheng/approve/' + id,
method: 'put'
})
}
// 审核驳回
export function rejectRenzheng(id, juejuereson) {
return request({
url: '/system/renzheng/reject/' + id,
method: 'put',
data: { juejuereson }
})
}

View File

@@ -1,321 +1,247 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="名称" prop="name"> <el-form-item label="姓名" prop="name">
<el-input <el-input v-model="queryParams.name" placeholder="请输入姓名" clearable @keyup.enter.native="handleQuery" />
v-model="queryParams.name" </el-form-item>
placeholder="请输入名称" <el-form-item label="用户ID" prop="userId">
clearable <el-input v-model="queryParams.userId" placeholder="请输入用户ID" clearable @keyup.enter.native="handleQuery" />
@keyup.enter.native="handleQuery" </el-form-item>
/> <el-form-item label="认证状态" prop="state">
</el-form-item> <el-select v-model="queryParams.state" placeholder="请选择认证状态" clearable>
<el-form-item label="用户ID" prop="userId"> <el-option label="全部" :value="null" />
<el-input <el-option label="待审核" value="0" />
v-model="queryParams.userId" <el-option label="已通过" value="1" />
placeholder="请输入用户ID" <el-option label="已驳回" value="2" />
clearable </el-select>
@keyup.enter.native="handleQuery" </el-form-item>
/> <el-form-item>
</el-form-item> <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-form-item label="审核不通过原因" prop="juejuereson"> <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
<el-input </el-form-item>
v-model="queryParams.juejuereson" </el-form>
placeholder="请输入审核不通过原因"
clearable <el-row :gutter="10" class="mb8">
@keyup.enter.native="handleQuery" <el-col :span="1.5">
/> <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
</el-form-item> v-hasPermi="['system:renzheng:add']">新增</el-button>
<el-form-item label="认证状态1是新的1是通过2是驳回" prop="state"> </el-col>
<el-input <el-col :span="1.5">
v-model="queryParams.state" <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete"
placeholder="请输入认证状态1是新的1是通过2是驳回" v-hasPermi="['system:renzheng:remove']">删除</el-button>
clearable </el-col>
@keyup.enter.native="handleQuery" <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
/> </el-row>
</el-form-item>
<el-form-item> <el-table v-loading="loading" :data="renzhengList" @selection-change="handleSelectionChange">
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> <el-table-column type="selection" width="55" align="center" />
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> <el-table-column label="ID" align="center" prop="id" width="70" />
</el-form-item> <el-table-column label="姓名" align="center" prop="name" min-width="80" />
</el-form> <el-table-column label="身份证号" align="center" prop="identityNo" min-width="170" />
<el-table-column label="用户ID" align="center" prop="userId" width="80" />
<el-row :gutter="10" class="mb8"> <el-table-column label="人脸照" align="center" prop="facePic" width="80">
<el-col :span="1.5"> <template slot-scope="scope">
<el-button <image-preview :src="scope.row.facePic" :width="50" :height="50" />
type="primary" </template>
plain </el-table-column>
icon="el-icon-plus" <el-table-column label="身份证正面" align="center" prop="frontIdentity" width="80">
size="mini" <template slot-scope="scope">
@click="handleAdd" <image-preview :src="scope.row.frontIdentity" :width="50" :height="50" />
v-hasPermi="['system:renzheng:add']" </template>
>新增</el-button> </el-table-column>
</el-col> <el-table-column label="身份证反面" align="center" prop="backIdentity" width="80">
<el-col :span="1.5"> <template slot-scope="scope">
<el-button <image-preview :src="scope.row.backIdentity" :width="50" :height="50" />
type="success" </template>
plain </el-table-column>
icon="el-icon-edit" <el-table-column label="认证状态" align="center" prop="state" width="90">
size="mini" <template slot-scope="scope">
:disabled="single" <el-tag :type="stateTagType(scope.row.state)">{{ stateMap[scope.row.state] || scope.row.state }}</el-tag>
@click="handleUpdate" </template>
v-hasPermi="['system:renzheng:edit']" </el-table-column>
>修改</el-button> <el-table-column label="驳回原因" align="center" prop="juejuereson" min-width="120" show-overflow-tooltip />
</el-col> <el-table-column label="提交时间" align="center" prop="createTime" width="160" />
<el-col :span="1.5"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="220">
<el-button <template slot-scope="scope">
type="danger" <el-button size="mini" type="success" icon="el-icon-check" @click="handleApprove(scope.row)"
plain v-if="scope.row.state == '0' || scope.row.state == null"
icon="el-icon-delete" v-hasPermi="['system:renzheng:edit']">通过</el-button>
size="mini" <el-button size="mini" type="danger" icon="el-icon-close" @click="handleReject(scope.row)"
:disabled="multiple" v-if="scope.row.state == '0' || scope.row.state == null"
@click="handleDelete" v-hasPermi="['system:renzheng:edit']">驳回</el-button>
v-hasPermi="['system:renzheng:remove']" <el-button size="mini" type="text" icon="el-icon-view" @click="handleDetail(scope.row)">详情</el-button>
>删除</el-button> <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
</el-col> v-hasPermi="['system:renzheng:remove']">删除</el-button>
<el-col :span="1.5"> </template>
<el-button </el-table-column>
type="warning" </el-table>
plain
icon="el-icon-download" <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
size="mini" @pagination="getList" />
@click="handleExport"
v-hasPermi="['system:renzheng:export']" <!-- 驳回原因对话框 -->
>导出</el-button> <el-dialog :title="'审核驳回'" :visible.sync="rejectOpen" width="450px" append-to-body>
</el-col> <el-form ref="rejectForm" :model="rejectForm" :rules="rejectRules" label-width="80px">
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> <el-form-item label="驳回原因" prop="juejuereson">
</el-row> <el-input v-model="rejectForm.juejuereson" type="textarea" :rows="3" placeholder="请输入驳回原因" />
</el-form-item>
<el-table v-loading="loading" :data="renzhengList" @selection-change="handleSelectionChange"> </el-form>
<el-table-column type="selection" width="55" align="center" /> <div slot="footer" class="dialog-footer">
<el-table-column label="ID" align="center" prop="id" /> <el-button type="primary" @click="submitReject">确 定</el-button>
<el-table-column label="名称" align="center" prop="name" /> <el-button @click="rejectOpen = false">取 消</el-button>
<el-table-column label="人脸照地址" align="center" prop="facePic" width="100"> </div>
<template slot-scope="scope"> </el-dialog>
<image-preview :src="scope.row.facePic" :width="50" :height="50"/>
</template> <!-- 认证详情对话框 -->
</el-table-column> <el-dialog :title="'认证详情'" :visible.sync="detailOpen" width="650px" append-to-body>
<el-table-column label="用户ID" align="center" prop="userId" /> <el-descriptions :column="2" border>
<el-table-column label="身份证正面" align="center" prop="frontIdentity" width="100"> <el-descriptions-item label="ID">{{ detail.id }}</el-descriptions-item>
<template slot-scope="scope"> <el-descriptions-item label="姓名">{{ detail.name }}</el-descriptions-item>
<image-preview :src="scope.row.frontIdentity" :width="50" :height="50"/> <el-descriptions-item label="身份证号">{{ detail.identityNo }}</el-descriptions-item>
</template> <el-descriptions-item label="用户ID">{{ detail.userId }}</el-descriptions-item>
</el-table-column> <el-descriptions-item label="认证状态">
<el-table-column label="身份证反面" align="center" prop="backIdentity" width="100"> <el-tag :type="stateTagType(detail.state)">{{ stateMap[detail.state] || detail.state }}</el-tag>
<template slot-scope="scope"> </el-descriptions-item>
<image-preview :src="scope.row.backIdentity" :width="50" :height="50"/> <el-descriptions-item label="驳回原因">{{ detail.juejuereson || '-' }}</el-descriptions-item>
</template> <el-descriptions-item label="人脸照" :span="2">
</el-table-column> <image-preview :src="detail.facePic" :width="120" :height="120" v-if="detail.facePic" />
<el-table-column label="审核不通过原因" align="center" prop="juejuereson" /> <span v-else>无</span>
<el-table-column label="认证状态1是新的1是通过2是驳回" align="center" prop="state" /> </el-descriptions-item>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <el-descriptions-item label="身份证正面">
<template slot-scope="scope"> <image-preview :src="detail.frontIdentity" :width="200" v-if="detail.frontIdentity" />
<el-button <span v-else>无</span>
size="mini" </el-descriptions-item>
type="text" <el-descriptions-item label="身份证反面">
icon="el-icon-edit" <image-preview :src="detail.backIdentity" :width="200" v-if="detail.backIdentity" />
@click="handleUpdate(scope.row)" <span v-else>无</span>
v-hasPermi="['system:renzheng:edit']" </el-descriptions-item>
>修改</el-button> <el-descriptions-item label="提交时间">{{ detail.createTime }}</el-descriptions-item>
<el-button <el-descriptions-item label="更新时间">{{ detail.updateTime }}</el-descriptions-item>
size="mini" </el-descriptions>
type="text" <div slot="footer" class="dialog-footer">
icon="el-icon-delete" <el-button type="success" @click="detailOpen = false; handleApprove(detail)"
@click="handleDelete(scope.row)" v-if="detail.state == '0' || detail.state == null"
v-hasPermi="['system:renzheng:remove']" v-hasPermi="['system:renzheng:edit']">审核通过</el-button>
>删除</el-button> <el-button type="danger" @click="detailOpen = false; handleReject(detail)"
</template> v-if="detail.state == '0' || detail.state == null"
</el-table-column> v-hasPermi="['system:renzheng:edit']">审核驳回</el-button>
</el-table> <el-button @click="detailOpen = false">关 闭</el-button>
</div>
<pagination </el-dialog>
v-show="total>0" </div>
:total="total" </template>
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize" <script>
@pagination="getList" import { listRenzheng, getRenzheng, delRenzheng, approveRenzheng, rejectRenzheng } from "@/api/system/renzheng";
/>
export default {
<!-- 添加或修改renzheng对话框 --> name: "Renzheng",
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> data() {
<el-form ref="form" :model="form" :rules="rules" label-width="80px"> return {
<el-form-item label="名称" prop="name"> loading: true,
<el-input v-model="form.name" placeholder="请输入名称" /> ids: [],
</el-form-item> single: true,
<el-form-item label="人脸照地址"> multiple: true,
<image-upload v-model="form.facePic"/> showSearch: true,
</el-form-item> total: 0,
<el-form-item label="用户ID" prop="userId"> renzhengList: [],
<el-input v-model="form.userId" placeholder="请输入用户ID" /> detailOpen: false,
</el-form-item> detail: {},
<el-form-item label="身份证正面"> rejectOpen: false,
<image-upload v-model="form.frontIdentity"/> rejectForm: { id: null, juejuereson: '' },
</el-form-item> rejectRules: {
<el-form-item label="身份证反面"> juejuereson: [{ required: true, message: '请输入驳回原因', trigger: 'blur' }]
<image-upload v-model="form.backIdentity"/> },
</el-form-item> stateMap: { '0': '待审核', '1': '已通过', '2': '已驳回' },
<el-form-item label="审核不通过原因" prop="juejuereson"> queryParams: {
<el-input v-model="form.juejuereson" placeholder="请输入审核不通过原因" /> pageNum: 1,
</el-form-item> pageSize: 10,
<el-form-item label="认证状态1是新的1是通过2是驳回" prop="state"> name: null,
<el-input v-model="form.state" placeholder="请输入认证状态1是新的1是通过2是驳回" /> userId: null,
</el-form-item> state: null,
</el-form> },
<div slot="footer" class="dialog-footer"> form: {},
<el-button type="primary" @click="submitForm">确 定</el-button> rules: {}
<el-button @click="cancel">取 消</el-button> };
</div> },
</el-dialog> created() {
</div> this.getList();
</template> },
methods: {
<script> stateTagType(state) {
import { listRenzheng, getRenzheng, delRenzheng, addRenzheng, updateRenzheng } from "@/api/system/renzheng"; const map = { '0': 'warning', '1': 'success', '2': 'danger' };
return map[state] || 'info';
export default { },
name: "Renzheng", getList() {
data() { this.loading = true;
return { listRenzheng(this.queryParams).then(response => {
// 遮罩层 this.renzhengList = response.rows;
loading: true, this.total = response.total;
// 选中数组 this.loading = false;
ids: [], });
// 非单个禁用 },
single: true, cancel() {
// 非多个禁用 this.open = false;
multiple: true, },
// 显示搜索条件 handleQuery() {
showSearch: true, this.queryParams.pageNum = 1;
// 总条数 this.getList();
total: 0, },
// renzheng表格数据 resetQuery() {
renzhengList: [], this.resetForm("queryForm");
// 弹出层标题 this.handleQuery();
title: "", },
// 是否显示弹出层 handleSelectionChange(selection) {
open: false, this.ids = selection.map(item => item.id)
// 查询参数 this.single = selection.length !== 1
queryParams: { this.multiple = !selection.length
pageNum: 1, },
pageSize: 10, handleAdd() {
name: null, this.$router.push({ path: '/system/renzheng/edit' });
facePic: null, },
userId: null, handleDetail(row) {
frontIdentity: null, getRenzheng(row.id).then(response => {
backIdentity: null, this.detail = response.data;
juejuereson: null, this.detailOpen = true;
state: null, });
}, },
// 表单参数 handleApprove(row) {
form: {}, this.$modal.confirm('确认通过该认证申请?').then(() => {
// 表单校验 approveRenzheng(row.id).then(() => {
rules: { this.$modal.msgSuccess("审核通过");
} this.getList();
}; });
}, }).catch(() => {});
created() { },
this.getList(); handleReject(row) {
}, this.rejectForm = { id: row.id, juejuereson: '' };
methods: { this.rejectOpen = true;
/** 查询renzheng列表 */ },
getList() { submitReject() {
this.loading = true; this.$refs["rejectForm"].validate(valid => {
listRenzheng(this.queryParams).then(response => { if (valid) {
this.renzhengList = response.rows; rejectRenzheng(this.rejectForm.id, this.rejectForm.juejuereson).then(() => {
this.total = response.total; this.$modal.msgSuccess("已驳回");
this.loading = false; this.rejectOpen = false;
}); this.getList();
}, });
// 取消按钮 }
cancel() { });
this.open = false; },
this.reset(); handleDelete(row) {
}, const ids = row.id || this.ids;
// 表单重置 this.$modal.confirm('是否确认删除认证编号为"' + ids + '"的数据项?').then(function () {
reset() { return delRenzheng(ids);
this.form = { }).then(() => {
id: null, this.getList();
name: null, this.$modal.msgSuccess("删除成功");
facePic: null, }).catch(() => {});
userId: null, },
frontIdentity: null, handleExport() {
backIdentity: null, this.download('system/renzheng/export', {
juejuereson: null, ...this.queryParams
state: null, }, `renzheng_${new Date().getTime()}.xlsx`)
createBy: null, }
createTime: null, }
updateBy: null, };
updateTime: null </script>
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length!==1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = "添加renzheng";
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
const id = row.id || this.ids
getRenzheng(id).then(response => {
this.form = response.data;
this.open = true;
this.title = "修改renzheng";
});
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.id != null) {
updateRenzheng(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addRenzheng(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids;
this.$modal.confirm('是否确认删除renzheng编号为"' + ids + '"的数据项?').then(function() {
return delRenzheng(ids);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
},
/** 导出按钮操作 */
handleExport() {
this.download('system/renzheng/export', {
...this.queryParams
}, `renzheng_${new Date().getTime()}.xlsx`)
}
}
};
</script>