Browse Source

fix:服务修改

master
wang 6 months ago
parent
commit
94f913dbcd
  1. 7
      src/api/business/cost/firm-reports-api.js
  2. 170
      src/views/business/erp/cost/firm-reports-form.vue
  3. 145
      src/views/business/erp/cost/firm-reports-list.vue
  4. 17
      src/views/business/erp/letter/letter-list.vue
  5. 28
      src/views/business/erp/penalty-apply/penalty-apply-list.vue
  6. 74
      src/views/business/erp/service/ceo-service-detail.vue
  7. 11
      src/views/business/erp/service/law-firm-service-report-statistics.vue
  8. 2
      src/views/business/erp/service/service-applications-count.vue
  9. 110
      src/views/business/erp/service/service-applications-list.vue
  10. 77
      src/views/business/erp/service/service-applications-report-list.vue

7
src/api/business/cost/firm-reports-api.js

@ -73,4 +73,11 @@ export const firmReportsApi = {
return postRequest('/firmReports/review', param);
},
/**
* 驳回 @author wzh
*/
reject: (idList) => {
return postRequest('/firmReports/reject', idList);
},
};

170
src/views/business/erp/cost/firm-reports-form.vue

@ -28,15 +28,15 @@
:max="2100"
/>
</a-form-item>
<a-form-item label="月份" name="declareMonth">
<a-form-item label="季度" name="declareQuarter">
<a-select
v-model:value="form.declareMonth"
placeholder="请选择月份"
@change="onMonthChange"
v-model:value="form.declareQuarter"
placeholder="请选择季度"
@change="onQuarterChange"
style="width: 100%"
>
<a-select-option v-for="month in monthOptions" :key="month.value" :value="month.value">
{{ month.label }}
<a-select-option v-for="quarter in quarterOptions" :key="quarter.value" :value="quarter.value">
{{ quarter.label }}
</a-select-option>
</a-select>
</a-form-item>
@ -62,7 +62,7 @@
/>
<div style="font-size: 12px; color: #666; margin-top: 4px;">
本年度已填报收入:{{ annualIncomeInfo.revenue || 0 }} 万元
<span v-if="annualIncomeInfo.revenue > 0 && form.revenue">,合计:{{ formatNumber((annualIncomeInfo.revenue || 0) + (form.revenue || 0)) }} 万元</span>
<span v-if="annualIncomeInfo.revenue > 0 && form.revenue">,合计:{{ formatNumber(parseFloat(annualIncomeInfo.revenue || 0) + parseFloat(form.revenue || 0)) }} 万元</span>
</div>
</a-form-item>
@ -156,37 +156,37 @@
totalCost: 0 // 总成本支出
});
// 月份选项(只能填报上一个月)
const monthOptions = ref([]);
// 季度选项(只能填报上一个季度)
const quarterOptions = ref([]);
// 初始化月份选项,只能选择上一个月
async function initMonthOptions() {
// 初始化季度选项,只能选择上一个季度
async function initQuarterOptions() {
const currentDate = new Date();
const currentYear = currentDate.getFullYear();
const currentMonth = currentDate.getMonth() + 1; // 当前月份(1-12)
const currentMonth = currentDate.getMonth() + 1;
// 计算上一个月
let lastMonth = currentMonth - 1;
let lastMonthYear = currentYear;
// 计算当前季度
const currentQuarter = Math.ceil(currentMonth / 3);
if (lastMonth === 0) {
lastMonth = 12;
lastMonthYear = currentYear - 1;
// 计算上一个季度
let lastQuarter = currentQuarter - 1;
let lastQuarterYear = currentYear;
if (lastQuarter === 0) {
lastQuarter = 4;
lastQuarterYear = currentYear - 1;
}
// 设置默认年份为上一个月所在的年份
form.declareYear = lastMonthYear;
// 设置默认年份为上一个季度所在的年份
form.declareYear = lastQuarterYear;
// 只能选择上一个月
monthOptions.value = [
{ label: `${lastMonth}月`, value: `${lastMonth}月` }
// 只能选择上一个季度
quarterOptions.value = [
{ label: `第${lastQuarter}季度`, value: lastQuarter }
];
// 默认选中上一个月
form.declareMonth = `${lastMonth}月`;
// 设置默认月份后,立即获取公益成本数据
await getPublicWelfareCost();
// 默认选中上一个季度
form.declareQuarter = lastQuarter;
}
// 格式化数字
@ -202,8 +202,8 @@
const result = await firmReportsApi.income();
if (result.data) {
annualIncomeInfo.value = {
revenue: result.data.revenue || 0,
totalCost: result.data.totalCost || 0
revenue: parseFloat(result.data.revenue) || 0,
totalCost: parseFloat(result.data.totalCost) || 0
};
}
} catch (error) {
@ -212,9 +212,9 @@
}
}
// 获取系统计算的公益成本
// 获取系统计算的公益成本(季度累计)
async function getPublicWelfareCost() {
console.log('开始获取公益成本,部门ID:', departmentId.value, '年份:', form.declareYear, '月份:', form.declareMonth);
console.log('开始获取公益成本,部门ID:', departmentId.value, '年份:', form.declareYear, '季度:', form.declareQuarter);
if (!departmentId.value) {
message.warning('无法获取机构信息,请重新登录');
@ -227,40 +227,49 @@
return;
}
if (!form.declareMonth) {
console.log('月份未选择,跳过API调用');
if (!form.declareQuarter) {
console.log('季度未选择,跳过API调用');
return;
}
try {
// 将月度字符串转换为数字(如"1月" -> 1, "2月" -> 2, ..., "12月" -> 12)
let monthNumber;
if (typeof form.declareMonth === 'string') {
const monthMatch = form.declareMonth.match(/^(\d+)/);
if (monthMatch && monthMatch[1]) {
monthNumber = parseInt(monthMatch[1]);
// 处理季度值,可能是数字1-4或字符串"第一季度 (Q1)"等
let quarterNum = form.declareQuarter;
if (typeof quarterNum === 'string') {
// 从字符串中提取数字,如"第一季度 (Q1)"提取1
const match = quarterNum.match(/(\d+)/);
if (match) {
quarterNum = parseInt(match[1], 10);
} else {
console.error('无法解析季度字符串:', quarterNum);
return;
}
} else if (typeof form.declareMonth === 'number') {
monthNumber = form.declareMonth;
}
// 构建请求参数:包含部门ID、年份和月度数字
try {
// 计算季度对应的月份范围
const startMonth = (quarterNum - 1) * 3 + 1;
const endMonth = startMonth + 2;
// 获取季度内3个月的公益成本累计
let totalCost = 0;
for (let month = startMonth; month <= endMonth; month++) {
const queryForm = {
firmId: departmentId.value,
year: form.declareYear, // 后端期望的year字段
month: monthNumber // 月度字段转换为数字
year: form.declareYear,
month: month
};
console.log('调用接口: /serviceApplications/statistics/cost, 参数:', queryForm);
const response = await serviceApplicationsApi.getServiceApplicationsCost(queryForm);
console.log('接口返回数据:', response);
console.log(`第${month}月接口返回数据:`, response);
// 将分转换为万元(API返回的是分单位)
const costInYuan = response.data; // 分转元
//const costInWanYuan = costInYuan / 10000; // 元转万元
form.publicWelfareCost = costInYuan;
totalCost += parseFloat(response.data) || 0;
}
form.publicWelfareCost = totalCost;
console.log('转换后的公益成本:', form.publicWelfareCost, '万元');
console.log('季度累计公益成本:', form.publicWelfareCost, '万元');
calculateCosts();
} catch (error) {
message.error('获取公益成本失败');
@ -270,7 +279,7 @@
}
}
function show(rowData) {
async function show(rowData) {
console.log('表单show函数被调用,rowData:', rowData);
Object.assign(form, formDefault);
@ -280,26 +289,22 @@
// 正确判断模式:只有当rowData是对象且有id字段时才认为是编辑模式
if (rowData && typeof rowData === 'object' && rowData.id) {
console.log('编辑模式,使用现有数据');
console.log('编辑模式,使用现有数据:', rowData);
// 先设置表单数据
Object.assign(form, rowData);
// 确保declareMonth字段格式与字典系统匹配
if (form.declareMonth && typeof form.declareMonth === 'number') {
// 如果后端返回的是数字格式,转换为字典期望的字符串格式
form.declareMonth = form.declareMonth + '月';
} else if (form.declareMonth && form.declareMonth.includes('(')) {
// 如果返回的是显示名称格式(如"1月 (1)"),提取字典值
const match = form.declareMonth.match(/\(([^)]+)\)/);
if (match && match[1]) {
form.declareMonth = match[1] + '月'; // 提取数字并添加"月"后缀
}
}
// 编辑模式下也需要重新获取公益成本(驳回后可能需要更新)
// 确保表单数据已更新后再获取成本
await nextTick();
console.log('编辑模式表单数据:', form.declareYear, form.declareQuarter);
await getPublicWelfareCost();
} else {
console.log('新建模式,等待用户选择月份后获取公益成本');
// 新建模式下初始化月份选项(只能选择上一个月)
initMonthOptions();
console.log('新建模式,等待用户选择季度后获取公益成本');
// 新建模式下初始化季度选项(只能选择上一个季度)
await initQuarterOptions();
// 新建模式下获取本年度已填报收入
fetchAnnualIncome();
await fetchAnnualIncome();
// 获取公益成本数据
await getPublicWelfareCost();
}
visibleFlag.value = true;
@ -324,7 +329,7 @@
id: undefined,
firmId: undefined, // 律师事务所ID(部门ID)
declareYear: new Date().getFullYear(), // 报表年份
declareMonth: undefined, // 月度ID (1,2,3,4,5,6,7,8,9,10,11,12)
declareQuarter: undefined, // 季度 (1,2,3,4)
revenue: undefined, // 营业收入(万元)
//totalCost: 0, // 总成本支出(万元)
publicWelfareCost: undefined, // 公益成本支出(万元)
@ -334,7 +339,7 @@
let form = reactive({ ...formDefault });
const rules = {
declareMonth: [{ required: true, message: '请选择月份' }],
declareQuarter: [{ required: true, message: '请选择季度' }],
declareYear: [{ required: true, message: '请输入报表年份' }],
revenue: [{ required: true, message: '请输入律所收入' }],
publicWelfareCost: [{ required: true, message: '系统正在计算公益成本,请稍后' }],
@ -345,12 +350,12 @@
const showCostWarning = ref(false);
const costRatio = ref(0); // 当前成本比例
// 月份选择变化时的处理
function onMonthChange() {
console.log('月份选择变化:', form.declareMonth);
// 季度选择变化时的处理
function onQuarterChange() {
console.log('季度选择变化:', form.declareQuarter);
// 只有当选择了月份时才获取公益成本
if (form.declareMonth) {
// 只有当选择了季度时才获取公益成本
if (form.declareQuarter) {
getPublicWelfareCost();
}
@ -425,7 +430,7 @@
// 保存草稿
async function saveAsDraft() {
try {
await formRef.value.validateFields(['declareMonth', 'declareYear', 'revenue', 'publicWelfareCost']);
await formRef.value.validateFields(['declareQuarter', 'declareYear', 'revenue', 'publicWelfareCost']);
form.approvalStatus = '0'; // 草稿状态
await save();
} catch (err) {
@ -455,12 +460,9 @@
// 准备保存的数据,如果超过上限则使用计算值
const saveData = { ...form };
// 将月份格式转换为数字格式(如"1月" -> 1, "2月" -> 2)
if (saveData.declareMonth && typeof saveData.declareMonth === 'string') {
const monthMatch = saveData.declareMonth.match(/^(\d+)/);
if (monthMatch && monthMatch[1]) {
saveData.declareMonth = parseInt(monthMatch[1]);
}
// 确保季度是整数类型
if (saveData.declareQuarter) {
saveData.declareQuarter = parseInt(saveData.declareQuarter);
}
// 确保年份是整数类型

145
src/views/business/erp/cost/firm-reports-list.vue

@ -14,16 +14,24 @@
<DepartmentTreeSelect style="width: 250px" v-model:value="queryForm.firmId" placeholder="请选择律师事务所" />
</a-form-item>
<a-form-item label="年份" class="smart-query-form-item">
<a-input style="width: 150px" v-model:value="queryForm.declareYear" placeholder="请输入报表年份" />
<a-select
v-model:value="queryForm.declareYear"
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="月份" class="smart-query-form-item">
<a-form-item label="季度" class="smart-query-form-item">
<a-select
v-model:value="queryForm.declareMonth"
placeholder="请选择月份"
style="width: 100px"
v-model:value="queryForm.declareQuarter"
placeholder="请选择季度"
style="width: 120px"
>
<a-select-option v-for="month in monthOptions" :key="month.value" :value="month.value">
{{ month.label }}
<a-select-option v-for="quarter in quarterOptions" :key="quarter.value" :value="quarter.value">
{{ quarter.label }}
</a-select-option>
</a-select>
</a-form-item>
@ -85,7 +93,7 @@
<div class="smart-table-operate">
<a-button v-if="record.approvalStatus === 0 || record.approvalStatus === 4" @click="showForm(record)" type="link">编辑</a-button>
<a-button v-if="isCto && record.approvalStatus === 0 && (record.userId == currentUserId || !record.userId)" @click="onSubmit(record)" type="link">提交</a-button>
<a-button v-if="record.approvalStatus === 1 || record.approvalStatus === 2" @click="showAuditModal(record)" type="link">审核</a-button>
<a-button v-if="isCeo && record.approvalStatus === 3" @click="confirmReject(record)" danger type="link">驳回</a-button>
<a-button v-if="isCto && record.approvalStatus === 0 && (record.userId == currentUserId || !record.userId)" @click="onDelete(record)" danger type="link">删除</a-button>
</div>
</template>
@ -111,6 +119,8 @@
<FirmReportsForm ref="formRef" @reloadList="queryData"/>
</a-card>
</template>
<script setup>
@ -142,7 +152,7 @@
// 判断角色
const role = (res.data?.roleCode || res.data?.roleName || '').toLowerCase();
isCto.value = role === 'cto';
isCto.value = role === 'cto' || role === 'staff';
isCeo.value = role === 'ceo';
} catch (e) {
@ -164,9 +174,12 @@
ellipsis: true,
},
{
title: '月份',
dataIndex: 'declareMonth',
title: '季度',
dataIndex: 'declareQuarter',
ellipsis: true,
customRender: ({ text }) => {
return text ? `${text}` : '';
},
},
{
title: '营业收入(万元)',
@ -225,24 +238,29 @@
pageSize: 10,
firmId: undefined, // 律师事务所ID
declareYear: undefined, // 报表年份
declareMonth: undefined, // 报表月份
declareQuarter: undefined, // 报表季度
};
// 月份选项
const monthOptions = ref([
{ label: '1月', value: '1月' },
{ label: '2月', value: '2月' },
{ label: '3月', value: '3月' },
{ label: '4月', value: '4月' },
{ label: '5月', value: '5月' },
{ label: '6月', value: '6月' },
{ label: '7月', value: '7月' },
{ label: '8月', value: '8月' },
{ label: '9月', value: '9月' },
{ label: '10月', value: '10月' },
{ label: '11月', value: '11月' },
{ label: '12月', value: '12月' }
// 季度选项
const quarterOptions = ref([
{ label: '第1季度', value: 1 },
{ label: '第2季度', value: 2 },
{ label: '第3季度', value: 3 },
{ label: '第4季度', value: 4 }
]);
// 年份选项(最近5年)
const yearOptions = ref([]);
// 初始化年份选项
function initYearOptions() {
const currentYear = new Date().getFullYear();
const years = [];
for (let i = 0; i < 5; i++) {
years.push(currentYear - i);
}
yearOptions.value = years;
}
// 查询表单form
const queryForm = reactive({ ...queryFormState });
// 表格加载loading
@ -270,17 +288,9 @@
async function queryData() {
tableLoading.value = true;
try {
// 准备查询参数,将月份格式转换为数字
// 准备查询参数
const queryParams = { ...queryForm };
// 将月份格式转换为数字(如"2月" -> 2)
if (queryParams.declareMonth && typeof queryParams.declareMonth === 'string') {
const monthMatch = queryParams.declareMonth.match(/^(\d+)/);
if (monthMatch && monthMatch[1]) {
queryParams.declareMonth = parseInt(monthMatch[1]);
}
}
let queryResult = await firmReportsApi.queryPage(queryParams);
tableData.value = queryResult.data.list;
total.value = queryResult.data.total;
@ -329,60 +339,37 @@
}
}
// ---------------------------- 审核相关 ----------------------------
// 审核相关状态
const auditModalVisible = ref(false);
const auditLoading = ref(false);
const currentAuditRecord = ref(null);
const auditForm = reactive({
auditResult: 3, // 默认同意
auditRemark: ''
});
// 显示审核弹框
function showAuditModal(record) {
currentAuditRecord.value = record;
auditForm.auditResult = 3;
auditForm.auditRemark = '';
auditModalVisible.value = true;
}
// ---------------------------- 驳回相关 ----------------------------
// 处理审核
async function handleAudit() {
if (!currentAuditRecord.value) {
message.error('未选择审核记录');
return;
// 确认驳回
function confirmReject(record) {
Modal.confirm({
title: '提示',
content: '确定要驳回该成本报表吗?',
okText: '确定',
okType: 'danger',
onOk() {
return handleReject(record);
},
cancelText: '取消',
});
}
auditLoading.value = true;
const auditData = {
reportId: currentAuditRecord.value.reportId,
approvalStatus: auditForm.auditResult
};
// 处理驳回
async function handleReject(record) {
try {
await firmReportsApi.review(auditData);
message.success('审核成功');
auditModalVisible.value = false;
// 调用驳回接口,传递id数组
await firmReportsApi.reject([record.id]);
message.success('驳回成功');
queryData();
} catch (error) {
message.error('审核失败');
console.error('审核失败:', error);
} finally {
auditLoading.value = false;
message.error('驳回失败');
console.error('驳回失败:', error);
}
}
// 取消审核
function handleAuditCancel() {
auditModalVisible.value = false;
currentAuditRecord.value = null;
auditForm.auditResult = 3;
auditForm.auditRemark = '';
}
onMounted(async () => {
initYearOptions();
await getLoginInfo();
await queryData();
});

17
src/views/business/erp/letter/letter-list.vue

@ -75,17 +75,18 @@
<!---------- 表格操作行 begin ----------->
<a-row class="smart-table-btn-block">
<div class="smart-table-operate-block">
<!-- user角色只显示律师承诺书按钮 -->
<!-- user角色(律师)只显示律师承诺书按钮 -->
<a-button type="primary" @click="handleLawyerUpload" :loading="proofUploadLoading" v-if="isLawyerRole && !isFirmRole">
<UploadOutlined />
上传律师承诺书
</a-button>
<!-- cto角色显示两个按钮 -->
<a-button type="primary" @click="handleLawyerUpload" :loading="proofUploadLoading" v-if="isFirmRole" style="margin-left: 8px;">
<!-- cto角色(主任)显示两个按钮 -->
<a-button type="primary" @click="handleLawyerUpload" :loading="proofUploadLoading" v-if="isFirmRole && !isFirmAdmin" style="margin-left: 8px;">
<UploadOutlined />
上传律师承诺书
</a-button>
<!-- cto和staff都可以上传律所承诺书 -->
<a-button type="primary" @click="handleFirmUpload" :loading="proofUploadLoading" v-if="isFirmRole" style="margin-left: 8px;">
<UploadOutlined />
上传律所承诺书
@ -513,8 +514,10 @@ import AgreementModal from '/@/views/system/home/components/agreement.vue';
const isCeo = ref(false);
// 判断用户是否为律师角色
const isLawyerRole = ref(false);
// 判断用户是否为律所角色
// 判断用户是否为律所角色(cto或staff)
const isFirmRole = ref(false);
// 判断用户是否为行政人员角色
const isFirmAdmin = ref(false);
// 获取登录信息并检查角色
async function getLoginInfo() {
@ -533,8 +536,10 @@ import AgreementModal from '/@/views/system/home/components/agreement.vue';
isCeo.value = roleLower === 'ceo';
// 律师角色:user
isLawyerRole.value = roleLower === 'user' || userType === 'user';
// 律所角色:cto
isFirmRole.value = roleLower === 'cto' || userType === 'cto';
// 行政人员角色:staff
isFirmAdmin.value = roleLower === 'staff';
// 律所角色:cto 或 staff(行政人员)
isFirmRole.value = roleLower === 'cto' || roleLower === 'staff' || userType === 'cto';
}
} catch (e) {

28
src/views/business/erp/penalty-apply/penalty-apply-list.vue

@ -9,7 +9,7 @@
<!---------- 查询表单form begin ----------->
<a-form class="smart-query-form">
<a-row class="smart-query-form-row">
<a-form-item label="申请人" class="smart-query-form-item" v-if="isCeo || isCto">
<a-form-item label="申请人" class="smart-query-form-item" v-if="isCeo || isCto || isFirmAdmin">
<a-input style="width: 150px" v-model:value="queryForm.userName" placeholder="请输入申请人" />
</a-form-item>
<a-form-item label="申请日期" class="smart-query-form-item">
@ -45,13 +45,15 @@
<!---------- 表格操作行 begin ----------->
<a-row class="smart-table-btn-block">
<div class="smart-table-operate-block">
<a-button @click="() => showForm('user')" type="primary" v-if="!isCeo">
<!-- 申请律师无处罚证明:只有user角色可以申请,行政人员不能申请 -->
<a-button @click="() => showForm('user')" type="primary" v-if="isUser">
<template #icon>
<PlusOutlined />
</template>
申请律师无处罚证明
</a-button>
<a-button @click="() => showForm('cto')" type="primary" v-if="isCto">
<!-- 申请律所无处罚证明:cto和staff都可以申请 -->
<a-button @click="() => showForm('cto')" type="primary" v-if="isCto || isFirmAdmin">
<template #icon>
<PlusOutlined />
</template>
@ -84,8 +86,8 @@
<a-button type="link" size="small" @click="showAuditModal(record)" :disabled="record.auditStatus !== 1" v-if="isCeo">审批</a-button>
<a-button type="link" size="small" @click="handlePreview(record)" v-if="isCeo">预览</a-button>
<!-- CTO角色:判断status字段,状态为1(已提交)时显示审批按钮 -->
<a-button type="link" size="small" @click="showAuditModal(record)" :disabled="record.status !== 1" v-if="isCto">审批</a-button>
<!-- CTO角色和行政人员:判断status字段,状态为1(已提交)时显示审批按钮 -->
<a-button type="link" size="small" @click="showAuditModal(record)" :disabled="record.status !== 1" v-if="isCto || isFirmAdmin">审批</a-button>
<!-- 用户角色:当auditStatus为3(已批准)且当前用户是文件所有者时显示下载 -->
<a-button type="link" size="small" @click="handleDownload(record)" v-if="record.auditStatus === 3 && !isCeo && record.userId === loginInfo?.userId">下载</a-button>
@ -341,9 +343,12 @@ import PenaltyApplyForm from './penalty-apply-form.vue';
// 判断用户是否为User角色
const isUser = ref(false);
// 判断用户是否为CTO角色
// 判断用户是否为CTO角色(主任)
const isCto = ref(false);
// 判断用户是否为行政人员角色
const isFirmAdmin = ref(false);
// 重置查询条件
function resetQuery() {
let pageSize = queryForm.pageSize;
@ -414,10 +419,13 @@ import PenaltyApplyForm from './penalty-apply-form.vue';
// User角色判断
isUser.value = roleLower === 'user';
// CTO角色判断
// CTO角色判断(主任)
isCto.value = roleLower === 'cto';
console.log('用户角色:', userRole, 'isCeo:', isCeo.value, 'isUser:', isUser.value, 'isCto:', isCto.value);
// 行政人员角色判断
isFirmAdmin.value = roleLower === 'staff';
console.log('用户角色:', userRole, 'isCeo:', isCeo.value, 'isUser:', isUser.value, 'isCto:', isCto.value, 'isFirmAdmin:', isFirmAdmin.value);
}
}
@ -499,8 +507,8 @@ import PenaltyApplyForm from './penalty-apply-form.vue';
// 根据角色使用不同的审核状态字段
if (isCeo.value) {
auditData.auditStatusField = 'auditStatus'; // CEO角色使用律协审批状态字段
} else if (isCto.value) {
auditData.auditStatusField = 'status'; // CTO角色使用律所审批状态字段
} else if (isCto.value || isFirmAdmin.value) {
auditData.auditStatusField = 'status'; // CTO角色和行政人员使用律所审批状态字段
}
if (auditForm.auditRemark) {

74
src/views/business/erp/service/ceo-service-detail.vue

@ -109,9 +109,9 @@
批量审核
</a-button>
<!-- 批量上报按钮(cto角色显示) -->
<!-- 批量上报按钮(cto角色和行政人员角色显示) -->
<a-button
v-if="isCtoRole"
v-if="isCtoRole || isFirmAdmin"
@click="batchReport"
type="primary"
:disabled="selectedRowKeyList.length == 0"
@ -265,9 +265,11 @@ import {
} from '@ant-design/icons-vue';
import { message } from 'ant-design-vue';
import { serviceApplicationsApi } from '/@/api/business/service-applications/service-applications-api';
import { loginApi } from '/@/api/system/login-api';
import DepartmentTreeSelect from '/@/components/system/department-tree-select/index.vue';
import ServiceApplicationsForm from './service-applications-form.vue';
import TableOperator from '/@/components/support/table-operator/index.vue';
import { getRoleInfo } from '/@/utils/role-util';
const router = useRouter();
const route = useRoute();
@ -279,6 +281,7 @@ const total = ref(0);
const selectedRowKeyList = ref([]);
const employeeList = ref([]);
const loginInfo = ref({});
const roleInfo = ref(getRoleInfo(''));
// 审核相关状态
const auditModalVisible = ref(false);
@ -332,23 +335,54 @@ const REVIEW_ENUM = {
};
// 计算属性
const isNotUser = computed(() => {
// 这里需要根据实际权限判断,暂时返回true
return true;
});
const isCtoRole = computed(() => {
// 判断是否为CTO角色
return false;
});
const isNotUser = computed(() => roleInfo.value.isNotUser);
const isCtoRole = computed(() => roleInfo.value.isCto);
const isCeo = computed(() => roleInfo.value.isCeo);
const isFirmAdmin = computed(() => roleInfo.value.isFirmAdmin);
const isAssociationRole = computed(() => roleInfo.value.isAssociationRole);
// 权限判断函数
function canAuditRecord(record) {
return record.firmAuditStatus === 1 && isNotUser.value;
const userRole = (loginInfo.value.roleCode || loginInfo.value.roleName || '').toLowerCase();
if (userRole === 'ceo') {
return record.associationAuditStatus === 1;
}
if (userRole === 'cto' || userRole === 'staff') {
return record.firmAuditStatus === 1;
}
return false;
}
function canRejectRecord(record) {
return record.firmAuditStatus === 1 && isNotUser.value;
if (!isAssociationRole.value && !isCeo.value && !isCtoRole.value && !isFirmAdmin.value) {
return false;
}
if (isAssociationRole.value || isCeo.value) {
if (record.associationAuditStatus !== 3) {
return false;
}
if (!record.associationAuditTime) {
return false;
}
const auditDate = new Date(record.associationAuditTime);
const now = new Date();
const monthsDiff = (now.getFullYear() - auditDate.getFullYear()) * 12 + (now.getMonth() - auditDate.getMonth());
return monthsDiff <= 18;
} else if (isCtoRole.value || isFirmAdmin.value) {
if (record.associationAuditStatus !== 4) {
return false;
}
if (record.firmAuditStatus === 4) {
return false;
}
return true;
}
return false;
}
// 选择行变化
@ -534,6 +568,7 @@ async function loadAllEmployees() {
// 页面初始化
onMounted(() => {
getLoginInfo();
// 从路由参数中获取筛选条件
const { firmId, firmName, year, quarter } = route.query;
@ -546,6 +581,19 @@ onMounted(() => {
queryData();
});
// 获取登录信息
async function getLoginInfo() {
try {
const res = await loginApi.getLoginInfo();
loginInfo.value = res.data;
const userRole = res.data.roleCode || res.data.roleName || '';
roleInfo.value = getRoleInfo(userRole);
console.log('登录信息:', res.data);
} catch (e) {
console.error('获取登录信息失败:', e);
}
}
// 表格列定义
const columns = ref([
{

11
src/views/business/erp/service/law-firm-service-report-statistics.vue

@ -133,6 +133,7 @@
showQuickJumper
showTotal
@change="handleTableChange"
@showSizeChange="handleTableChange"
/>
</div>
</a-card>
@ -264,11 +265,11 @@
queryData();
}
function handleTableChange(pag) {
pagination.current = pag.current;
pagination.pageSize = pag.pageSize;
queryForm.pageNum = pag.current;
queryForm.pageSize = pag.pageSize;
function handleTableChange(page, pageSize) {
pagination.current = page;
pagination.pageSize = pageSize;
queryForm.pageNum = page;
queryForm.pageSize = pageSize;
queryData();
}

2
src/views/business/erp/service/service-applications-count.vue

@ -80,7 +80,7 @@ async function getLoginInfo() {
// 判断是否为CEO或CTO角色
const role = (res.data?.roleCode || res.data?.roleName || '').toLowerCase();
isCeo.value = role === 'ceo';
isCto.value = role === 'cto';
isCto.value = role === 'cto' || role === 'staff';
// 保持isAdmin兼容,但实际使用isCeo或isCto
isAdmin.value = isCeo.value || isCto.value;

110
src/views/business/erp/service/service-applications-list.vue

@ -113,9 +113,9 @@
<!-- 批量上报按钮(cto角色显示) -->
<!-- 批量上报按钮(cto角色和行政人员角色显示) -->
<a-button
v-if="isCtoRole"
v-if="isCtoRole || isFirmAdmin"
@click="batchReport"
type="primary"
:disabled="selectedRowKeyList.length == 0"
@ -308,7 +308,7 @@
</div>
</template>
<script setup>
import { reactive, ref, onMounted } from 'vue';
import { reactive, ref, onMounted, computed } from 'vue';
import { useRoute } from 'vue-router';
import { message, Modal } from 'ant-design-vue';
import { SmartLoading } from '/@/components/framework/smart-loading';
@ -326,6 +326,7 @@ import { PlusOutlined, DeleteOutlined, SendOutlined, ImportOutlined, ExportOutli
import { loginApi } from '/@/api/system/login-api';
import { firmReportsApi } from '/@/api/business/cost/firm-reports-api';
import AgreementModal from '/@/views/system/home/components/agreement-modal.vue';
import { getRoleInfo } from '/@/utils/role-util';
// ---------------------------- 表格列 ----------------------------
const columns = ref([
@ -480,20 +481,17 @@ import AgreementModal from '/@/views/system/home/components/agreement-modal.vue'
// 登录用户信息
const loginInfo = ref(null);
// 判断用户是否为user角色(不是user则显示批量审核)
const isNotUser = ref(false);
// 角色判断结果
const roleInfo = ref(getRoleInfo(''));
// 判断用户是否为cto角色(cto则额外显示批量上报)
const isCtoRole = ref(false);
// 判断用户是否为协会角色(协会角色显示驳回按钮)
const isAssociationRole = ref(false);
// 判断用户是否为CEO角色(CEO显示律所统计概览)
const isCeo = ref(false);
// 判断用户是否为律所角色
const isFirmRole = ref(false);
// 兼容旧代码的变量
const isNotUser = computed(() => roleInfo.value.isNotUser);
const isCtoRole = computed(() => roleInfo.value.isCto);
const isAssociationRole = computed(() => roleInfo.value.isAssociationRole);
const isCeo = computed(() => roleInfo.value.isCeo);
const isFirmRole = computed(() => roleInfo.value.isFirmRole);
const isFirmAdmin = computed(() => roleInfo.value.isFirmAdmin);
const canCreateApplication = computed(() => roleInfo.value.canCreateApplication);
// 获取登录信息
async function getLoginInfo() {
@ -510,32 +508,9 @@ import AgreementModal from '/@/views/system/home/components/agreement-modal.vue'
// 检查用户角色
function checkUserRole() {
if (loginInfo.value) {
// 根据用户角色判断权限
const userRole = loginInfo.value.roleCode || loginInfo.value.roleName || '';
const roleLower = userRole.toLowerCase();
// 不是user角色则显示批量审核按钮
isNotUser.value = roleLower != 'user';
// cto角色则额外显示批量上报按钮
isCtoRole.value = roleLower === 'cto';
// 协会角色(协会角色显示驳回按钮)
isAssociationRole.value = roleLower.includes('协会') ||
roleLower.includes('association') ||
roleLower.includes('律协') ||
roleLower.includes('律师协会');
// 律所角色判断
isFirmRole.value = roleLower.includes('律所') ||
roleLower.includes('firm') ||
roleLower.includes('lawyer') ||
roleLower.includes('律师');
// CEO角色判断(CEO不显示新建申报和批量提交按钮)
isCeo.value = roleLower === 'ceo';
console.log('用户角色:', userRole, '不是user:', isNotUser.value, '是cto:', isCtoRole.value, '是协会角色:', isAssociationRole.value, '是CEO:', isCeo.value);
roleInfo.value = getRoleInfo(userRole);
console.log('用户角色:', userRole, '角色信息:', roleInfo.value);
}
}
@ -588,8 +563,8 @@ import AgreementModal from '/@/views/system/home/components/agreement-modal.vue'
return record.associationAuditStatus === 1;
}
// cto角色:只能审核执业机构审核状态为待审核(1)的记录
if (userRole === 'cto') {
// cto角色和staff角色:只能审核执业机构审核状态为待审核(1)的记录
if (userRole === 'cto' || userRole === 'staff') {
return record.firmAuditStatus === 1;
}
@ -702,7 +677,7 @@ import AgreementModal from '/@/views/system/home/components/agreement-modal.vue'
);
if (canReportRecords.length === 0) {
message.warning('选中的记录不符合上报条件,请勿提交其它月份数据');
message.warning('选中的记录不符合上报条件,只能上报上个季度的数据');
return;
}
@ -719,47 +694,50 @@ import AgreementModal from '/@/views/system/home/components/agreement-modal.vue'
// 判断记录是否符合上报条件
function canReportRecord(record) {
// 只能上报已通过执业机构审核的记录(状态为3:已通过)
// 且协会审核状态必须是未提交(0)
// 且协会审核状态必须是未提交(0)或被驳回(4)
const isAuditPassed = record.firmAuditStatus === 3 &&
record.associationAuditStatus === 0;
(record.associationAuditStatus === 0 || record.associationAuditStatus === 4);
// 如果有成本查询权限,需要检查月份限制;否则不限制月份
// 如果有成本查询权限,需要检查季度限制;否则不限制
const hasCostPermission = loginInfo.value && loginInfo.value.costVisibleFlag === true;
if (hasCostPermission) {
// 有成本权限:只能上报上个月的数据
const isLastMonthData = isLastMonthRecord(record);
return isAuditPassed && isLastMonthData;
// 有成本权限:只能上报上个季度的数据
// 律协要求:二季度上报一季度的数据,三季度上报二季度的数据
const isLastQuarterData = isLastQuarterRecord(record);
return isAuditPassed && isLastQuarterData;
} else {
// 无成本权限:不限制月份,可以上报所有月份的数据
// 无成本权限:不限制季度,可以上报所有数据
return isAuditPassed;
}
}
// 判断记录是否为上个月的数据
function isLastMonthRecord(record) {
// 判断记录是否为上个季度的数据
function isLastQuarterRecord(record) {
if (!record.reportTime) return false;
const currentDate = new Date();
const currentYear = currentDate.getFullYear();
const currentMonth = currentDate.getMonth() + 1;
const currentQuarter = Math.ceil(currentMonth / 3);
// 计算上一个月
let lastMonth = currentMonth - 1;
let lastMonthYear = currentYear;
// 计算上个季度
let lastQuarter = currentQuarter - 1;
let lastQuarterYear = currentYear;
if (lastMonth === 0) {
lastMonth = 12;
lastMonthYear = currentYear - 1;
if (lastQuarter === 0) {
lastQuarter = 4;
lastQuarterYear = currentYear - 1;
}
// 解析记录的提交时间
const reportDate = new Date(record.reportTime);
const reportYear = reportDate.getFullYear();
const reportMonth = reportDate.getMonth() + 1;
const reportQuarter = Math.ceil(reportMonth / 3);
// 检查是否为上个月的数据
return reportYear === lastMonthYear && reportMonth === lastMonth;
// 检查是否为上个季度的数据
return reportYear === lastQuarterYear && reportQuarter === lastQuarter;
}
// 检查是否有未审核的数据
@ -1358,9 +1336,9 @@ function showAuditModal(record) {
// 判断记录是否可以驳回
function canRejectRecord(record) {
// 1. 必须是协会角色、CEO角色或CTO角色
if (!isAssociationRole.value && !isCeo.value && !isCtoRole.value) {
console.log('驳回按钮不显示:不是协会角色、CEO角色或CTO角色');
// 1. 必须是协会角色、CEO角色、CTO角色或行政人员角色
if (!isAssociationRole.value && !isCeo.value && !isCtoRole.value && !isFirmAdmin.value) {
console.log('驳回按钮不显示:不是协会角色、CEO角色、CTO角色或行政人员角色');
return false;
}
@ -1391,8 +1369,8 @@ function showAuditModal(record) {
}
return canReject;
} else if (isCtoRole.value) {
// CTO角色:协会审核状态必须是驳回(4)且执业机构审核状态不能是驳回(4)
} else if (isCtoRole.value || isFirmAdmin.value) {
// CTO角色和行政人员角色:协会审核状态必须是驳回(4)且执业机构审核状态不能是驳回(4)
if (record.associationAuditStatus !== 4) {
console.log('驳回按钮不显示:协会审核状态不是驳回', record.associationAuditStatus);
return false;

77
src/views/business/erp/service/service-applications-report-list.vue

@ -58,8 +58,8 @@
<a-row class="smart-table-btn-block">
<div class="smart-table-operate-block">
<!-- 新建申报按钮:非协会角色且非CEO角色显示 -->
<a-button v-if="!isAssociationRole && !isCeo" @click="showForm()" type="primary">
<!-- 新建申报按钮 -->
<a-button v-if="canCreateApplication" @click="showForm()" type="primary">
<template #icon>
<PlusOutlined />
</template>
@ -67,15 +67,15 @@
</a-button>
<a-button v-if="!isCeo" @click="confirmBatchDelete" type="primary" danger :disabled="!canBatchDelete()">
<a-button v-if="!isCeo && !isFirmAdmin" @click="confirmBatchDelete" type="primary" danger :disabled="!canBatchDelete()">
<template #icon>
<DeleteOutlined />
</template>
批量删除
</a-button>
<!-- 导出按钮:只有user用户显示 -->
<a-button v-if="!isNotUser" @click="handleExport" type="primary">
<!-- 导出按钮 -->
<a-button v-if="isNotUser" @click="handleExport" type="primary">
<template #icon>
<ExportOutlined />
</template>
@ -248,7 +248,7 @@
</div>
</template>
<script setup>
import { reactive, ref, onMounted } from 'vue';
import { reactive, ref, onMounted, computed } from 'vue';
import { useRoute } from 'vue-router';
import { message, Modal } from 'ant-design-vue';
import { SmartLoading } from '/@/components/framework/smart-loading';
@ -263,6 +263,7 @@ import { REVIEW_ENUM,SERVICEC_REVIEW_ENUM } from '/@/constants/system/review-con
import { PlusOutlined, DeleteOutlined, SendOutlined, ImportOutlined, ExportOutlined, DownloadOutlined, UploadOutlined, CheckCircleOutlined } from '@ant-design/icons-vue';
import { loginApi } from '/@/api/system/login-api';
import AgreementModal from '/@/views/system/home/components/agreement-modal.vue';
import { getRoleInfo } from '/@/utils/role-util';
// ---------------------------- 表格列 ----------------------------
const columns = ref([
@ -415,20 +416,17 @@ import AgreementModal from '/@/views/system/home/components/agreement-modal.vue'
// 登录用户信息
const loginInfo = ref(null);
// 判断用户是否为user角色(不是user则显示批量审核)
const isNotUser = ref(false);
// 角色判断结果
const roleInfo = ref(getRoleInfo(''));
// 判断用户是否为cto角色(cto则额外显示批量上报)
const isCtoRole = ref(false);
// 判断用户是否为协会角色(协会角色显示驳回按钮)
const isAssociationRole = ref(false);
// 判断用户是否为CEO角色(CEO显示律所统计概览)
const isCeo = ref(false);
// 判断用户是否为律所角色
const isFirmRole = ref(false);
// 兼容旧代码的变量
const isNotUser = computed(() => roleInfo.value.isNotUser);
const isCtoRole = computed(() => roleInfo.value.isCto);
const isAssociationRole = computed(() => roleInfo.value.isAssociationRole);
const isCeo = computed(() => roleInfo.value.isCeo);
const isFirmRole = computed(() => roleInfo.value.isFirmRole);
const isFirmAdmin = computed(() => roleInfo.value.isFirmAdmin);
const canCreateApplication = computed(() => roleInfo.value.canCreateApplication);
// 获取登录信息
async function getLoginInfo() {
@ -445,32 +443,9 @@ import AgreementModal from '/@/views/system/home/components/agreement-modal.vue'
// 检查用户角色
function checkUserRole() {
if (loginInfo.value) {
// 根据用户角色判断权限
const userRole = loginInfo.value.roleCode || loginInfo.value.roleName || '';
const roleLower = userRole.toLowerCase();
// 不是user角色则显示批量审核按钮
isNotUser.value = roleLower != 'user';
// cto角色则额外显示批量上报按钮
isCtoRole.value = roleLower === 'cto';
// 协会角色(协会角色显示驳回按钮)
isAssociationRole.value = roleLower.includes('协会') ||
roleLower.includes('association') ||
roleLower.includes('律协') ||
roleLower.includes('律师协会');
// 律所角色判断
isFirmRole.value = roleLower.includes('律所') ||
roleLower.includes('firm') ||
roleLower.includes('lawyer') ||
roleLower.includes('律师');
// CEO角色判断(CEO不显示新建申报和批量提交按钮)
isCeo.value = roleLower === 'ceo';
console.log('用户角色:', userRole, '不是user:', isNotUser.value, '是cto:', isCtoRole.value, '是协会角色:', isAssociationRole.value, '是CEO:', isCeo.value);
roleInfo.value = getRoleInfo(userRole);
console.log('用户角色:', userRole, '角色信息:', roleInfo.value);
}
}
@ -523,8 +498,8 @@ import AgreementModal from '/@/views/system/home/components/agreement-modal.vue'
return record.associationAuditStatus === 1;
}
// cto角色:只能审核执业机构审核状态为待审核(1)的记录
if (userRole === 'cto') {
// cto角色和staff角色:只能审核执业机构审核状态为待审核(1)的记录
if (userRole === 'cto' || userRole === 'staff') {
return record.firmAuditStatus === 1;
}
@ -1184,9 +1159,9 @@ function showAuditModal(record) {
// 判断记录是否可以驳回
function canRejectRecord(record) {
// 1. 必须是协会角色、CEO角色或CTO角色
if (!isAssociationRole.value && !isCeo.value && !isCtoRole.value) {
console.log('驳回按钮不显示:不是协会角色、CEO角色或CTO角色');
// 1. 必须是协会角色、CEO角色、CTO角色或行政人员角色
if (!isAssociationRole.value && !isCeo.value && !isCtoRole.value && !isFirmAdmin.value) {
console.log('驳回按钮不显示:不是协会角色、CEO角色、CTO角色或行政人员角色');
return false;
}
@ -1217,8 +1192,8 @@ function showAuditModal(record) {
}
return canReject;
} else if (isCtoRole.value) {
// CTO角色:协会审核状态必须是驳回(4)且执业机构审核状态不能是驳回(4)
} else if (isCtoRole.value || isFirmAdmin.value) {
// CTO角色和行政人员角色:协会审核状态必须是驳回(4)且执业机构审核状态不能是驳回(4)
if (record.associationAuditStatus !== 4) {
console.log('驳回按钮不显示:协会审核状态不是驳回', record.associationAuditStatus);
return false;

Loading…
Cancel
Save