2 changed files with 920 additions and 0 deletions
@ -0,0 +1,703 @@ |
|||||
|
<!-- |
||||
|
* 服务申报详情视图 |
||||
|
* |
||||
|
* @Author: Assistant |
||||
|
* @Date: 2026-01-11 |
||||
|
* @Description: 查看服务申报详情时打开的完整功能视图 |
||||
|
--> |
||||
|
<template> |
||||
|
<div class="service-applications-detail"> |
||||
|
<a-card size="small" :bordered="false" :hoverable="true" title="服务申报表"> |
||||
|
<!-- 返回按钮 --> |
||||
|
<div class="detail-header"> |
||||
|
<a-button type="link" @click="backToList" style="margin-bottom: 16px"> |
||||
|
< 返回列表 |
||||
|
</a-button> |
||||
|
</div> |
||||
|
|
||||
|
<!---------- 查询表单form begin -----------> |
||||
|
<a-form class="smart-query-form"> |
||||
|
<a-row class="smart-query-form-row"> |
||||
|
<a-form-item label="执业机构" class="smart-query-form-item"> |
||||
|
<DepartmentTreeSelect style="width: 150px" v-model:value="queryForm.firmId" placeholder="请选择执业机构" /> |
||||
|
</a-form-item> |
||||
|
<a-form-item label="律师名称" class="smart-query-form-item"> |
||||
|
<a-select |
||||
|
v-model:value="queryForm.userId" |
||||
|
style="width: 150px" |
||||
|
placeholder="请选择律师" |
||||
|
:showSearch="true" |
||||
|
:allowClear="true" |
||||
|
@focus="loadAllEmployees" |
||||
|
> |
||||
|
<a-select-option v-for="item in employeeList" :key="item.employeeId" :value="item.employeeId"> |
||||
|
{{ item.actualName }} |
||||
|
<template v-if="item.departmentName"> ({{ item.departmentName }}) </template> |
||||
|
</a-select-option> |
||||
|
</a-select> |
||||
|
</a-form-item> |
||||
|
<a-form-item label="服务开始时间" class="smart-query-form-item"> |
||||
|
<a-date-picker style="width: 150px" v-model:value="queryForm.serviceStart" placeholder="开始时间" /> |
||||
|
</a-form-item> |
||||
|
<a-form-item label="服务结束时间" class="smart-query-form-item"> |
||||
|
<a-date-picker style="width: 150px" v-model:value="queryForm.serviceEnd" placeholder="结束时间" /> |
||||
|
</a-form-item> |
||||
|
<a-form-item label="组织单位名称" class="smart-query-form-item"> |
||||
|
<a-input style="width: 150px" v-model:value="queryForm.organizerName" placeholder="组织单位名称" /> |
||||
|
</a-form-item> |
||||
|
<a-form-item label="服务对象负责人姓名" class="smart-query-form-item"> |
||||
|
<a-input style="width: 150px" v-model:value="queryForm.managerName" placeholder="服务对象负责人姓名" /> |
||||
|
</a-form-item> |
||||
|
<a-form-item label="执业机构审核状态" class="smart-query-form-item"> |
||||
|
<a-select style="width: 150px" v-model:value="queryForm.firmAuditStatus" placeholder="请选择审核状态"> |
||||
|
<a-select-option v-for="status in Object.values(REVIEW_ENUM)" :key="status.value" :value="status.value"> |
||||
|
{{ status.desc }} |
||||
|
</a-select-option> |
||||
|
</a-select> |
||||
|
</a-form-item> |
||||
|
<a-form-item label="协会审核状态" class="smart-query-form-item"> |
||||
|
<a-select style="width: 150px" v-model:value="queryForm.associationAuditStatus" placeholder="请选择审核状态"> |
||||
|
<a-select-option v-for="status in Object.values(REVIEW_ENUM)" :key="status.value" :value="status.value"> |
||||
|
{{ status.desc }} |
||||
|
</a-select-option> |
||||
|
</a-select> |
||||
|
</a-form-item> |
||||
|
<a-form-item class="smart-query-form-item smart-margin-left10"> |
||||
|
<a-button v-privilege="'serviceApplications:query'" type="primary" @click="onSearch"> |
||||
|
<template #icon> |
||||
|
<SearchOutlined /> |
||||
|
</template> |
||||
|
查询 |
||||
|
</a-button> |
||||
|
<a-button @click="resetQuery" class="smart-margin-left10"> |
||||
|
<template #icon> |
||||
|
<ReloadOutlined /> |
||||
|
</template> |
||||
|
重置 |
||||
|
</a-button> |
||||
|
</a-form-item> |
||||
|
</a-row> |
||||
|
</a-form> |
||||
|
<!---------- 查询表单form end -----------> |
||||
|
|
||||
|
<!---------- 表格操作行 begin -----------> |
||||
|
<a-row class="smart-table-btn-block"> |
||||
|
<div class="smart-table-operate-block"> |
||||
|
<a-button v-privilege="'serviceApplications:add'" @click="showForm" type="primary"> |
||||
|
<template #icon> |
||||
|
<PlusOutlined /> |
||||
|
</template> |
||||
|
新建申报 |
||||
|
</a-button> |
||||
|
<a-button @click="batchSubmit" type="primary" :disabled="selectedRowKeyList.length == 0"> |
||||
|
<template #icon> |
||||
|
<SendOutlined /> |
||||
|
</template> |
||||
|
批量提交 |
||||
|
</a-button> |
||||
|
|
||||
|
<!-- 批量审核按钮(不是user角色显示) --> |
||||
|
<a-button |
||||
|
v-if="isNotUser" |
||||
|
@click="batchAudit" |
||||
|
type="primary" |
||||
|
:disabled="selectedRowKeyList.length == 0" |
||||
|
> |
||||
|
<template #icon> |
||||
|
<CheckCircleOutlined /> |
||||
|
</template> |
||||
|
批量审核 |
||||
|
</a-button> |
||||
|
|
||||
|
<!-- 批量上报按钮(cto角色显示) --> |
||||
|
<a-button |
||||
|
v-if="isCtoRole" |
||||
|
@click="batchReport" |
||||
|
type="primary" |
||||
|
:disabled="selectedRowKeyList.length == 0" |
||||
|
> |
||||
|
<template #icon> |
||||
|
<UploadOutlined /> |
||||
|
</template> |
||||
|
批量上报 |
||||
|
</a-button> |
||||
|
|
||||
|
<a-button @click="confirmBatchDelete" type="primary" danger :disabled="selectedRowKeyList.length == 0"> |
||||
|
<template #icon> |
||||
|
<DeleteOutlined /> |
||||
|
</template> |
||||
|
批量删除 |
||||
|
</a-button> |
||||
|
</div> |
||||
|
<div class="smart-table-setting-block"> |
||||
|
<TableOperator v-model="columns" :tableId="null" :refresh="queryData" /> |
||||
|
</div> |
||||
|
</a-row> |
||||
|
<!---------- 表格操作行 end -----------> |
||||
|
|
||||
|
<!---------- 表格 begin -----------> |
||||
|
<a-table |
||||
|
size="small" |
||||
|
:scroll="{ x: 1800, y: 800 }" |
||||
|
:dataSource="tableData" |
||||
|
:columns="columns" |
||||
|
rowKey="applicationId" |
||||
|
bordered |
||||
|
:loading="tableLoading" |
||||
|
:pagination="false" |
||||
|
:row-selection="{ selectedRowKeys: selectedRowKeyList, onChange: onSelectChange }" |
||||
|
> |
||||
|
<template #bodyCell="{ text, record, column }"> |
||||
|
<template v-if="column.dataIndex === 'action'"> |
||||
|
<div class="smart-table-operate"> |
||||
|
<a-button @click="showDetail(record)" type="link">详情</a-button> |
||||
|
<a-button v-if="(record.firmAuditStatus === 0 || record.firmAuditStatus === 4) && record.userId === loginInfo?.userId" @click="showForm(record)" type="link">编辑</a-button> |
||||
|
<a-button v-if="(record.firmAuditStatus === 0 && record.userId === loginInfo?.userId)" @click="onSubmit(record)" type="link">提交</a-button> |
||||
|
<a-button v-if="canAuditRecord(record)" @click="showAuditModal(record)" type="link">审核</a-button> |
||||
|
<a-button v-if="canRejectRecord(record)" @click="showRejectModal(record)" danger type="link">驳回</a-button> |
||||
|
<a-button v-if="record.firmAuditStatus === 0 && record.userId === loginInfo?.userId" @click="onDelete(record)" danger type="link">删除</a-button> |
||||
|
</div> |
||||
|
</template> |
||||
|
</template> |
||||
|
</a-table> |
||||
|
<!---------- 表格 end -----------> |
||||
|
|
||||
|
<!---------- 审核弹框 begin -----------> |
||||
|
<a-modal |
||||
|
v-model:visible="auditModalVisible" |
||||
|
title="服务申报审核" |
||||
|
:confirm-loading="auditLoading" |
||||
|
@ok="handleAudit" |
||||
|
@cancel="handleAuditCancel" |
||||
|
width="400px" |
||||
|
> |
||||
|
<div style="text-align: center; padding: 20px 0;"> |
||||
|
<p style="margin-bottom: 20px; font-size: 16px;">请选择审核结果:</p> |
||||
|
<a-radio-group v-model:value="auditForm.auditResult" size="large"> |
||||
|
<a-radio :value="3" style="margin-right: 30px;"> |
||||
|
<span style="font-size: 16px;">同意</span> |
||||
|
</a-radio> |
||||
|
<a-radio :value="4"> |
||||
|
<span style="font-size: 16px;">拒绝</span> |
||||
|
</a-radio> |
||||
|
</a-radio-group> |
||||
|
</div> |
||||
|
</a-modal> |
||||
|
<!---------- 审核弹框 end -----------> |
||||
|
|
||||
|
<!---------- 批量审核弹框 begin -----------> |
||||
|
<a-modal |
||||
|
v-model:visible="batchAuditModalVisible" |
||||
|
title="批量审核服务申报" |
||||
|
:confirm-loading="batchAuditLoading" |
||||
|
@ok="handleBatchAudit" |
||||
|
@cancel="handleBatchAuditCancel" |
||||
|
width="500px" |
||||
|
> |
||||
|
<a-form :model="batchAuditForm" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }"> |
||||
|
<a-form-item label="审核结果" required> |
||||
|
<a-radio-group v-model:value="batchAuditForm.auditResult"> |
||||
|
<a-radio :value="3">同意</a-radio> |
||||
|
<a-radio :value="4">拒绝</a-radio> |
||||
|
</a-radio-group> |
||||
|
</a-form-item> |
||||
|
<a-form-item label="选中记录"> |
||||
|
<span style="color: #1890ff;">{{ selectedRowKeyList.length }} 条记录</span> |
||||
|
</a-form-item> |
||||
|
</a-form> |
||||
|
</a-modal> |
||||
|
<!---------- 批量审核弹框 end -----------> |
||||
|
|
||||
|
<!---------- 驳回弹框 begin -----------> |
||||
|
<a-modal |
||||
|
v-model:visible="rejectModalVisible" |
||||
|
title="驳回服务申报" |
||||
|
:confirm-loading="rejectLoading" |
||||
|
@ok="handleReject" |
||||
|
@cancel="handleRejectCancel" |
||||
|
width="500px" |
||||
|
> |
||||
|
<a-form :model="rejectForm" layout="vertical"> |
||||
|
<a-form-item label="驳回原因" required> |
||||
|
<a-textarea |
||||
|
v-model:value="rejectForm.rejectReason" |
||||
|
placeholder="请输入驳回原因" |
||||
|
rows="4" |
||||
|
style="resize: vertical;" |
||||
|
/> |
||||
|
</a-form-item> |
||||
|
</a-form> |
||||
|
</a-modal> |
||||
|
<!---------- 驳回弹框 end -----------> |
||||
|
|
||||
|
<div class="smart-query-table-page"> |
||||
|
<a-pagination |
||||
|
showSizeChanger |
||||
|
showQuickJumper |
||||
|
show-less-items |
||||
|
:pageSizeOptions="PAGE_SIZE_OPTIONS" |
||||
|
:defaultPageSize="queryForm.pageSize" |
||||
|
v-model:current="queryForm.pageNum" |
||||
|
v-model:pageSize="queryForm.pageSize" |
||||
|
:total="total" |
||||
|
@change="queryData" |
||||
|
@showSizeChange="queryData" |
||||
|
:show-total="(total) => `共${total}条`" |
||||
|
/> |
||||
|
</div> |
||||
|
|
||||
|
<ServiceApplicationsForm ref="formRef" @reloadList="queryData"/> |
||||
|
</a-card> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { ref, reactive, onMounted, computed } from 'vue'; |
||||
|
import { useRouter, useRoute } from 'vue-router'; |
||||
|
import { |
||||
|
SearchOutlined, |
||||
|
ReloadOutlined, |
||||
|
PlusOutlined, |
||||
|
SendOutlined, |
||||
|
CheckCircleOutlined, |
||||
|
UploadOutlined, |
||||
|
DeleteOutlined |
||||
|
} from '@ant-design/icons-vue'; |
||||
|
import { message } from 'ant-design-vue'; |
||||
|
import { serviceApplicationsApi } from '/@/api/business/service-applications/service-applications-api'; |
||||
|
import DepartmentTreeSelect from '/@/components/system/department-tree-select/index.vue'; |
||||
|
import ServiceApplicationsForm from './service-applications-form.vue'; |
||||
|
import TableOperator from '/@/components/smart-table/table-operator/index.vue'; |
||||
|
|
||||
|
const router = useRouter(); |
||||
|
const route = useRoute(); |
||||
|
|
||||
|
// 响应式数据 |
||||
|
const tableLoading = ref(false); |
||||
|
const tableData = ref([]); |
||||
|
const total = ref(0); |
||||
|
const selectedRowKeyList = ref([]); |
||||
|
const employeeList = ref([]); |
||||
|
const loginInfo = ref({}); |
||||
|
|
||||
|
// 审核相关状态 |
||||
|
const auditModalVisible = ref(false); |
||||
|
const auditLoading = ref(false); |
||||
|
const rejectModalVisible = ref(false); |
||||
|
const rejectLoading = ref(false); |
||||
|
const batchAuditModalVisible = ref(false); |
||||
|
const batchAuditLoading = ref(false); |
||||
|
|
||||
|
// 审核表单 |
||||
|
const auditForm = reactive({ |
||||
|
applicationId: undefined, |
||||
|
auditResult: 3 |
||||
|
}); |
||||
|
|
||||
|
const rejectForm = reactive({ |
||||
|
applicationId: undefined, |
||||
|
rejectReason: '', |
||||
|
approvalRemark: '' |
||||
|
}); |
||||
|
|
||||
|
const batchAuditForm = reactive({ |
||||
|
auditResult: 3 |
||||
|
}); |
||||
|
|
||||
|
// 查询表单 |
||||
|
const queryForm = reactive({ |
||||
|
firmId: undefined, |
||||
|
userId: undefined, |
||||
|
serviceStart: undefined, |
||||
|
serviceEnd: undefined, |
||||
|
organizerName: undefined, |
||||
|
managerName: undefined, |
||||
|
firmAuditStatus: undefined, |
||||
|
associationAuditStatus: undefined, |
||||
|
pageNum: 1, |
||||
|
pageSize: 10 |
||||
|
}); |
||||
|
|
||||
|
// 表单引用 |
||||
|
const formRef = ref(); |
||||
|
|
||||
|
// 常量定义 |
||||
|
const PAGE_SIZE_OPTIONS = ['10', '20', '50', '100']; |
||||
|
const REVIEW_ENUM = { |
||||
|
0: { value: 0, desc: '待提交' }, |
||||
|
1: { value: 1, desc: '待审核' }, |
||||
|
2: { value: 2, desc: '审核中' }, |
||||
|
3: { value: 3, desc: '审核通过' }, |
||||
|
4: { value: 4, desc: '审核不通过' } |
||||
|
}; |
||||
|
|
||||
|
// 计算属性 |
||||
|
const isNotUser = computed(() => { |
||||
|
// 这里需要根据实际权限判断,暂时返回true |
||||
|
return true; |
||||
|
}); |
||||
|
|
||||
|
const isCtoRole = computed(() => { |
||||
|
// 判断是否为CTO角色 |
||||
|
return false; |
||||
|
}); |
||||
|
|
||||
|
// 权限判断函数 |
||||
|
function canAuditRecord(record) { |
||||
|
return record.firmAuditStatus === 1 && isNotUser.value; |
||||
|
} |
||||
|
|
||||
|
function canRejectRecord(record) { |
||||
|
return record.firmAuditStatus === 1 && isNotUser.value; |
||||
|
} |
||||
|
|
||||
|
// 选择行变化 |
||||
|
function onSelectChange(selectedRowKeys) { |
||||
|
selectedRowKeyList.value = selectedRowKeys; |
||||
|
} |
||||
|
|
||||
|
// 返回列表 |
||||
|
function backToList() { |
||||
|
router.push('/business/erp/service/service-applications-count'); |
||||
|
} |
||||
|
|
||||
|
// 显示详情 |
||||
|
function showDetail(record) { |
||||
|
message.info(`查看详情: ${record.applicationId}`); |
||||
|
} |
||||
|
|
||||
|
// 显示编辑表单 |
||||
|
function showForm(record) { |
||||
|
if (formRef.value) { |
||||
|
formRef.value.show(record); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 提交申报 |
||||
|
function onSubmit(record) { |
||||
|
message.info(`提交申报: ${record.applicationId}`); |
||||
|
} |
||||
|
|
||||
|
// 显示审核弹窗 |
||||
|
function showAuditModal(record) { |
||||
|
auditForm.applicationId = record.applicationId; |
||||
|
auditModalVisible.value = true; |
||||
|
} |
||||
|
|
||||
|
// 显示驳回弹窗 |
||||
|
function showRejectModal(record) { |
||||
|
rejectForm.applicationId = record.applicationId; |
||||
|
rejectModalVisible.value = true; |
||||
|
} |
||||
|
|
||||
|
// 删除申报 |
||||
|
function onDelete(record) { |
||||
|
message.info(`删除申报: ${record.applicationId}`); |
||||
|
} |
||||
|
|
||||
|
// 批量提交 |
||||
|
function batchSubmit() { |
||||
|
if (selectedRowKeyList.value.length === 0) { |
||||
|
message.warning('请选择要提交的记录'); |
||||
|
return; |
||||
|
} |
||||
|
message.info(`批量提交 ${selectedRowKeyList.value.length} 条记录`); |
||||
|
} |
||||
|
|
||||
|
// 批量审核 |
||||
|
function batchAudit() { |
||||
|
if (selectedRowKeyList.value.length === 0) { |
||||
|
message.warning('请选择要审核的记录'); |
||||
|
return; |
||||
|
} |
||||
|
batchAuditModalVisible.value = true; |
||||
|
} |
||||
|
|
||||
|
// 批量上报 |
||||
|
function batchReport() { |
||||
|
if (selectedRowKeyList.value.length === 0) { |
||||
|
message.warning('请选择要上报的记录'); |
||||
|
return; |
||||
|
} |
||||
|
message.info(`批量上报 ${selectedRowKeyList.value.length} 条记录`); |
||||
|
} |
||||
|
|
||||
|
// 批量删除确认 |
||||
|
function confirmBatchDelete() { |
||||
|
if (selectedRowKeyList.value.length === 0) { |
||||
|
message.warning('请选择要删除的记录'); |
||||
|
return; |
||||
|
} |
||||
|
message.info(`批量删除 ${selectedRowKeyList.value.length} 条记录`); |
||||
|
} |
||||
|
|
||||
|
// 审核处理 |
||||
|
function handleAudit() { |
||||
|
auditLoading.value = true; |
||||
|
setTimeout(() => { |
||||
|
auditLoading.value = false; |
||||
|
auditModalVisible.value = false; |
||||
|
message.success('审核成功'); |
||||
|
queryData(); |
||||
|
}, 1000); |
||||
|
} |
||||
|
|
||||
|
function handleAuditCancel() { |
||||
|
auditModalVisible.value = false; |
||||
|
auditForm.applicationId = undefined; |
||||
|
auditForm.auditResult = 3; |
||||
|
} |
||||
|
|
||||
|
// 驳回处理 |
||||
|
function handleReject() { |
||||
|
if (!rejectForm.rejectReason.trim()) { |
||||
|
message.warning('请输入驳回原因'); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
rejectLoading.value = true; |
||||
|
setTimeout(() => { |
||||
|
rejectLoading.value = false; |
||||
|
rejectModalVisible.value = false; |
||||
|
message.success('驳回成功'); |
||||
|
queryData(); |
||||
|
}, 1000); |
||||
|
} |
||||
|
|
||||
|
function handleRejectCancel() { |
||||
|
rejectModalVisible.value = false; |
||||
|
rejectForm.applicationId = undefined; |
||||
|
rejectForm.rejectReason = ''; |
||||
|
rejectForm.approvalRemark = ''; |
||||
|
} |
||||
|
|
||||
|
// 批量审核处理 |
||||
|
function handleBatchAudit() { |
||||
|
batchAuditLoading.value = true; |
||||
|
setTimeout(() => { |
||||
|
batchAuditLoading.value = false; |
||||
|
batchAuditModalVisible.value = false; |
||||
|
message.success('批量审核成功'); |
||||
|
queryData(); |
||||
|
}, 1000); |
||||
|
} |
||||
|
|
||||
|
function handleBatchAuditCancel() { |
||||
|
batchAuditModalVisible.value = false; |
||||
|
batchAuditForm.auditResult = 3; |
||||
|
} |
||||
|
|
||||
|
// 查询数据 |
||||
|
async function queryData() { |
||||
|
tableLoading.value = true; |
||||
|
try { |
||||
|
const res = await serviceApplicationsApi.queryPage(queryForm); |
||||
|
if (res.data) { |
||||
|
tableData.value = res.data.list || []; |
||||
|
total.value = res.data.total || 0; |
||||
|
} |
||||
|
} catch (error) { |
||||
|
console.error('查询数据失败:', error); |
||||
|
message.error('查询数据失败'); |
||||
|
} finally { |
||||
|
tableLoading.value = false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 搜索 |
||||
|
function onSearch() { |
||||
|
queryForm.pageNum = 1; |
||||
|
queryData(); |
||||
|
} |
||||
|
|
||||
|
// 重置查询 |
||||
|
function resetQuery() { |
||||
|
Object.assign(queryForm, { |
||||
|
firmId: undefined, |
||||
|
userId: undefined, |
||||
|
serviceStart: undefined, |
||||
|
serviceEnd: undefined, |
||||
|
organizerName: undefined, |
||||
|
managerName: undefined, |
||||
|
firmAuditStatus: undefined, |
||||
|
associationAuditStatus: undefined, |
||||
|
pageNum: 1, |
||||
|
pageSize: 10 |
||||
|
}); |
||||
|
queryData(); |
||||
|
} |
||||
|
|
||||
|
// 加载员工列表 |
||||
|
async function loadAllEmployees() { |
||||
|
// 实现加载员工列表的逻辑 |
||||
|
} |
||||
|
|
||||
|
// 页面初始化 |
||||
|
onMounted(() => { |
||||
|
// 从路由参数中获取筛选条件 |
||||
|
const { firmId, firmName, year, quarter } = route.query; |
||||
|
|
||||
|
// 设置查询表单默认值 |
||||
|
if (firmId) { |
||||
|
queryForm.firmId = firmId; |
||||
|
} |
||||
|
|
||||
|
// 自动查询数据 |
||||
|
queryData(); |
||||
|
}); |
||||
|
|
||||
|
// 表格列定义 |
||||
|
const columns = ref([ |
||||
|
{ |
||||
|
title: '执业机构', |
||||
|
dataIndex: 'departmentName', |
||||
|
key: 'departmentName', |
||||
|
ellipsis: true, |
||||
|
width: 150 |
||||
|
}, |
||||
|
{ |
||||
|
title: '律师姓名', |
||||
|
dataIndex: 'userName', |
||||
|
key: 'userName', |
||||
|
ellipsis: true, |
||||
|
width: 100 |
||||
|
}, |
||||
|
{ |
||||
|
title: '职务名称', |
||||
|
dataIndex: 'positionName', |
||||
|
key: 'positionName', |
||||
|
ellipsis: true, |
||||
|
width: 100 |
||||
|
}, |
||||
|
{ |
||||
|
title: '服务开始时间', |
||||
|
dataIndex: 'serviceStart', |
||||
|
key: 'serviceStart', |
||||
|
ellipsis: true, |
||||
|
width: 150 |
||||
|
}, |
||||
|
{ |
||||
|
title: '服务结束时间', |
||||
|
dataIndex: 'serviceEnd', |
||||
|
key: 'serviceEnd', |
||||
|
ellipsis: true, |
||||
|
width: 150 |
||||
|
}, |
||||
|
{ |
||||
|
title: '服务时长(小时)', |
||||
|
dataIndex: 'serviceDuration', |
||||
|
key: 'serviceDuration', |
||||
|
ellipsis: true, |
||||
|
width: 100, |
||||
|
align: 'center' |
||||
|
}, |
||||
|
{ |
||||
|
title: '受益人数', |
||||
|
dataIndex: 'beneficiaryCount', |
||||
|
key: 'beneficiaryCount', |
||||
|
ellipsis: true, |
||||
|
width: 100, |
||||
|
align: 'center' |
||||
|
}, |
||||
|
{ |
||||
|
title: '组织单位名称', |
||||
|
dataIndex: 'organizerName', |
||||
|
key: 'organizerName', |
||||
|
ellipsis: true, |
||||
|
width: 150 |
||||
|
}, |
||||
|
{ |
||||
|
title: '服务对象负责人姓名', |
||||
|
dataIndex: 'organizerContact', |
||||
|
key: 'organizerContact', |
||||
|
ellipsis: true, |
||||
|
width: 120 |
||||
|
}, |
||||
|
{ |
||||
|
title: '联系方式', |
||||
|
dataIndex: 'organizerPhone', |
||||
|
key: 'organizerPhone', |
||||
|
ellipsis: true, |
||||
|
width: 120 |
||||
|
}, |
||||
|
{ |
||||
|
title: '执业机构审核状态', |
||||
|
dataIndex: 'firmAuditStatus', |
||||
|
key: 'firmAuditStatus', |
||||
|
ellipsis: true, |
||||
|
width: 120, |
||||
|
align: 'center', |
||||
|
customRender: ({ text }) => { |
||||
|
const status = Object.values(REVIEW_ENUM).find(item => item.value === text); |
||||
|
return status ? status.desc : text; |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: '执业机构审核人', |
||||
|
dataIndex: 'firmAuditUserName', |
||||
|
key: 'firmAuditUserName', |
||||
|
ellipsis: true, |
||||
|
width: 120 |
||||
|
}, |
||||
|
{ |
||||
|
title: '执业机构审核时间', |
||||
|
dataIndex: 'firmAuditTime', |
||||
|
key: 'firmAuditTime', |
||||
|
ellipsis: true, |
||||
|
width: 150 |
||||
|
}, |
||||
|
{ |
||||
|
title: '协会审核状态', |
||||
|
dataIndex: 'associationAuditStatus', |
||||
|
key: 'associationAuditStatus', |
||||
|
ellipsis: true, |
||||
|
width: 120, |
||||
|
align: 'center', |
||||
|
customRender: ({ text }) => { |
||||
|
const status = Object.values(REVIEW_ENUM).find(item => item.value === text); |
||||
|
return status ? status.desc : text; |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: '协会审核意见', |
||||
|
dataIndex: 'associationAuditOpinion', |
||||
|
key: 'associationAuditOpinion', |
||||
|
ellipsis: true, |
||||
|
width: 150 |
||||
|
}, |
||||
|
{ |
||||
|
title: '协会审核人', |
||||
|
dataIndex: 'associationAuditUserName', |
||||
|
key: 'associationAuditUserName', |
||||
|
ellipsis: true, |
||||
|
width: 120 |
||||
|
}, |
||||
|
{ |
||||
|
title: '协会审核时间', |
||||
|
dataIndex: 'associationAuditTime', |
||||
|
key: 'associationAuditTime', |
||||
|
ellipsis: true, |
||||
|
width: 150 |
||||
|
}, |
||||
|
{ |
||||
|
title: '操作', |
||||
|
dataIndex: 'action', |
||||
|
key: 'action', |
||||
|
fixed: 'right', |
||||
|
width: 150, |
||||
|
align: 'center' |
||||
|
} |
||||
|
]); |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.service-applications-detail { |
||||
|
padding: 16px; |
||||
|
} |
||||
|
|
||||
|
.detail-header { |
||||
|
border-bottom: 1px solid #f0f0f0; |
||||
|
padding-bottom: 16px; |
||||
|
margin-bottom: 16px; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,217 @@ |
|||||
|
<!-- |
||||
|
* 律所统计概览组件(CEO专用) |
||||
|
* |
||||
|
* @Author: Assistant |
||||
|
* @Date: 2026-01-11 |
||||
|
* @Description: CEO角色查看各律所服务申报统计概览 |
||||
|
--> |
||||
|
<template> |
||||
|
<div class="law-firm-statistics"> |
||||
|
<!-- 律所统计概览 --> |
||||
|
<a-card title="律所服务申报统计" class="statistics-card"> |
||||
|
<!-- 查询条件 --> |
||||
|
<div class="query-section"> |
||||
|
<a-form :model="queryForm" layout="inline"> |
||||
|
<a-form-item label="年度"> |
||||
|
<a-select v-model:value="queryForm.year" placeholder="请选择年度" style="width: 120px"> |
||||
|
<a-select-option v-for="year in yearOptions" :key="year" :value="year">{{ year }}</a-select-option> |
||||
|
</a-select> |
||||
|
</a-form-item> |
||||
|
<a-form-item label="季度"> |
||||
|
<a-select v-model:value="queryForm.quarter" placeholder="请选择季度" style="width: 120px"> |
||||
|
<a-select-option v-for="quarter in quarterOptions" :key="quarter.value" :value="quarter.value"> |
||||
|
{{ quarter.label }} |
||||
|
</a-select-option> |
||||
|
</a-select> |
||||
|
</a-form-item> |
||||
|
<a-form-item label="律所名称"> |
||||
|
<DepartmentTreeSelect |
||||
|
v-model:value="queryForm.firmId" |
||||
|
placeholder="请选择律所" |
||||
|
style="width: 300px" |
||||
|
/> |
||||
|
</a-form-item> |
||||
|
<a-form-item> |
||||
|
<a-button type="primary" @click="handleQuery" :loading="loading"> |
||||
|
<SearchOutlined /> |
||||
|
查询 |
||||
|
</a-button> |
||||
|
<a-button @click="handleReset" style="margin-left: 8px"> |
||||
|
<ReloadOutlined /> |
||||
|
重置 |
||||
|
</a-button> |
||||
|
</a-form-item> |
||||
|
</a-form> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 统计表格 --> |
||||
|
<div class="statistics-table"> |
||||
|
<a-table |
||||
|
:dataSource="tableData" |
||||
|
:columns="columns" |
||||
|
:loading="loading" |
||||
|
:pagination="pagination" |
||||
|
rowKey="firmId" |
||||
|
size="middle" |
||||
|
@change="handleTableChange" |
||||
|
> |
||||
|
<template #bodyCell="{ column, record }"> |
||||
|
<!-- 查看详情按钮 --> |
||||
|
<template v-if="column.dataIndex === 'action'"> |
||||
|
<a-button type="link" @click="handleViewDetail(record)">查看详情</a-button> |
||||
|
</template> |
||||
|
|
||||
|
<!-- 服务时长 --> |
||||
|
<template v-else-if="column.dataIndex === 'totalDuration'"> |
||||
|
{{ record.totalDuration || 0 }} 小时 |
||||
|
</template> |
||||
|
</template> |
||||
|
</a-table> |
||||
|
</div> |
||||
|
</a-card> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { ref, reactive, onMounted } from 'vue'; |
||||
|
import { SearchOutlined, ReloadOutlined } from '@ant-design/icons-vue'; |
||||
|
import { message } from 'ant-design-vue'; |
||||
|
import { serviceApplicationsApi } from '/@/api/business/service-applications/service-applications-api'; |
||||
|
import DepartmentTreeSelect from '/@/components/system/department-tree-select/index.vue'; |
||||
|
import { router } from '/@/router'; // 导入router实例(命名导出) |
||||
|
|
||||
|
// 定义事件 |
||||
|
const emit = defineEmits(['firm-selected']); |
||||
|
|
||||
|
// 响应式数据 |
||||
|
const loading = ref(false); |
||||
|
const tableData = ref([]); |
||||
|
|
||||
|
// 分页配置 |
||||
|
const pagination = ref({ |
||||
|
current: 1, |
||||
|
pageSize: 10, |
||||
|
total: 0, |
||||
|
showSizeChanger: true, |
||||
|
showQuickJumper: true, |
||||
|
pageSizeOptions: ['10', '20', '50', '100'] |
||||
|
}); |
||||
|
|
||||
|
// 年度和季度选项 |
||||
|
const yearOptions = ref([]); |
||||
|
const quarterOptions = ref([ |
||||
|
{ value: 1, label: '第一季度' }, |
||||
|
{ value: 2, label: '第二季度' }, |
||||
|
{ value: 3, label: '第三季度' }, |
||||
|
{ value: 4, label: '第四季度' } |
||||
|
]); |
||||
|
|
||||
|
// 表格列配置 |
||||
|
const columns = ref([ |
||||
|
{ title: '律所名称', dataIndex: 'firmName', key: 'firmName', width: 200 }, |
||||
|
{ title: '律师人数', dataIndex: 'lawyerCount', key: 'lawyerCount', width: 120 }, |
||||
|
{ title: '申报总数', dataIndex: 'reportCount', key: 'reportCount', width: 120 }, |
||||
|
{ title: '已通过数', dataIndex: 'approvedCount', key: 'approvedCount', width: 120 }, |
||||
|
{ title: '服务时长(小时)', dataIndex: 'totalServiceDuration', key: 'totalServiceDuration', width: 120 }, |
||||
|
{ title: '操作', dataIndex: 'action', key: 'action', width: 120, fixed: 'right' } |
||||
|
]); |
||||
|
|
||||
|
// 查询表单 |
||||
|
const queryForm = reactive({ |
||||
|
year: new Date().getFullYear(), |
||||
|
quarter: null, |
||||
|
firmId: null |
||||
|
}); |
||||
|
|
||||
|
// 初始化年度选项 |
||||
|
function initYearOptions() { |
||||
|
const currentYear = new Date().getFullYear(); |
||||
|
const years = []; |
||||
|
for (let i = currentYear - 5; i <= currentYear + 1; i++) { |
||||
|
years.push(i); |
||||
|
} |
||||
|
yearOptions.value = years; |
||||
|
} |
||||
|
|
||||
|
// 查询数据 |
||||
|
async function handleQuery() { |
||||
|
try { |
||||
|
loading.value = true; |
||||
|
const params = { |
||||
|
year: queryForm.year, |
||||
|
quarter: queryForm.quarter, |
||||
|
firmId: queryForm.firmId, |
||||
|
pageNum: pagination.value.current, |
||||
|
pageSize: pagination.value.pageSize |
||||
|
}; |
||||
|
|
||||
|
const res = await serviceApplicationsApi.reportStatistics(params); |
||||
|
tableData.value = res.data.list || []; |
||||
|
pagination.value.total = res.data.total || 0; |
||||
|
} catch (error) { |
||||
|
message.error('查询失败'); |
||||
|
} finally { |
||||
|
loading.value = false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 重置查询条件 |
||||
|
function handleReset() { |
||||
|
queryForm.year = new Date().getFullYear(); |
||||
|
queryForm.quarter = null; |
||||
|
queryForm.firmId = null; |
||||
|
pagination.value.current = 1; |
||||
|
handleQuery(); |
||||
|
} |
||||
|
|
||||
|
// 处理分页变化 |
||||
|
function handleTableChange(paginationConfig) { |
||||
|
pagination.value = paginationConfig; |
||||
|
handleQuery(); |
||||
|
} |
||||
|
|
||||
|
// 处理查看详情 |
||||
|
function handleViewDetail(record) { |
||||
|
// 将部门id传递到服务记录页面 |
||||
|
// 使用Vue Router进行跳转,跳转到/erp/service/list |
||||
|
// 通过路由跳转传递查询参数 |
||||
|
const queryParams = {}; |
||||
|
if (record.firmId) { |
||||
|
queryParams.firmId = record.firmId; |
||||
|
} |
||||
|
// 使用Vue Router进行跳转 |
||||
|
router.push({ |
||||
|
path: '/erp/service/list', |
||||
|
query: queryParams |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
// 组件挂载时初始化 |
||||
|
onMounted(() => { |
||||
|
initYearOptions(); |
||||
|
handleQuery(); |
||||
|
}); |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.law-firm-statistics { |
||||
|
padding: 16px; |
||||
|
background: #fff; |
||||
|
min-height: 600px; |
||||
|
} |
||||
|
|
||||
|
.statistics-card { |
||||
|
margin-bottom: 16px; |
||||
|
} |
||||
|
|
||||
|
.query-section { |
||||
|
margin-bottom: 16px; |
||||
|
background: #fafafa; |
||||
|
padding: 16px; |
||||
|
border-radius: 4px; |
||||
|
} |
||||
|
|
||||
|
.statistics-table { |
||||
|
margin-top: 16px; |
||||
|
} |
||||
|
</style> |
||||
Loading…
Reference in new issue