diff --git a/src/components/support/file-upload/index.vue b/src/components/support/file-upload/index.vue
index ff9ff5e..4c7dcc6 100644
--- a/src/components/support/file-upload/index.vue
+++ b/src/components/support/file-upload/index.vue
@@ -213,7 +213,7 @@
},
maxSize: {
type: Number,
- default: 10,
+ default: 50,
},
// 上传的文件类型
accept: {
diff --git a/src/components/system/service-count/excel-statistics-detail.vue b/src/components/system/service-count/excel-statistics-detail.vue
index 23ff1d3..b0ce389 100644
--- a/src/components/system/service-count/excel-statistics-detail.vue
+++ b/src/components/system/service-count/excel-statistics-detail.vue
@@ -63,10 +63,22 @@
序号
律师姓名
执业证号
- 季度累计公益服务时长
- 季度累计公益服务成本
- 年度累计公益服务时长
- 年度累计公益服务成本
+
+ 季度累计公益服务时长
+ {{ getSortIcon('quarterlyServiceDuration') }}
+
+
+ 季度累计公益服务成本
+ {{ getSortIcon('quarterlyServiceCost') }}
+
+
+ 年度累计公益服务时长
+ {{ getSortIcon('annualServiceDuration') }}
+
+
+ 年度累计公益服务成本
+ {{ getSortIcon('annualServiceCost') }}
+
@@ -76,9 +88,7 @@
{{ item.certificateNumber || '-' }}
{{ formatNumber(item.quarterlyServiceDuration) }}
{{ formatCurrency(item.quarterlyServiceCost) }}
-
{{ formatNumber(item.annualServiceDuration) }}
-
{{ formatCurrency(item.annualServiceCost) }}
@@ -150,6 +160,66 @@ function initYearOptions() {
// 表格数据
const tableData = ref(props.tableData || []);
+// 排序状态:{ field: 'annualServiceCost', order: 'desc' | 'asc' | null }
+const sortState = ref({ field: '', order: '' });
+
+// 点击表头排序(后端排序)
+async function handleSort(field) {
+ let newOrder;
+ if (sortState.value.field !== field) {
+ // 首次点击该列,默认降序(金额大的排前面)
+ newOrder = 'desc';
+ } else if (sortState.value.order === 'desc') {
+ // 再次点击切换为升序
+ newOrder = 'asc';
+ } else {
+ // 第三次点击切换回降序(保持排序始终有方向)
+ newOrder = 'desc';
+ }
+ sortState.value = { field, order: newOrder };
+
+ // 调用后端排序
+ queryLoading.value = true;
+ try {
+ const params = {
+ ...localQueryForm,
+ sortField: field,
+ sortOrder: newOrder
+ };
+ const res = await serviceApplicationsApi.statistics(params);
+ if (res.data && Array.isArray(res.data)) {
+ tableData.value = res.data.map(item => ({
+ ...item,
+ quarterlyServiceDuration: Number(item.quarterlyServiceDuration) || 0,
+ quarterlyServiceCost: Number(item.quarterlyServiceCost) || 0,
+ annualServiceDuration: Number(item.annualServiceDuration) || 0,
+ annualServiceCost: Number(item.annualServiceCost) || 0
+ }));
+ } else {
+ tableData.value = [];
+ }
+ } catch (error) {
+ console.error('排序失败', error);
+ message.error('排序失败');
+ } finally {
+ queryLoading.value = false;
+ }
+}
+
+// 获取排序图标
+function getSortIcon(field) {
+ if (sortState.value.field !== field) {
+ return '⇅';
+ }
+ if (sortState.value.order === 'asc') {
+ return '↑';
+ }
+ if (sortState.value.order === 'desc') {
+ return '↓';
+ }
+ return '⇅';
+}
+
// 计算汇总数据
const summaryData = computed(() => {
@@ -191,6 +261,8 @@ function formatCurrency(value) {
// 查询数据
async function handleQuery() {
queryLoading.value = true;
+ // 重置排序状态
+ sortState.value = { field: '', order: '' };
try {
const params = {
...localQueryForm
@@ -368,4 +440,21 @@ onMounted(() => {
.report-row:last-child .report-cell {
border-bottom: none;
}
+
+/* 可排序列样式 */
+.report-cell.sortable {
+ cursor: pointer;
+ user-select: none;
+ transition: background-color 0.2s;
+}
+
+.report-cell.sortable:hover {
+ background-color: #003399;
+}
+
+.sort-icon {
+ margin-left: 4px;
+ font-size: 12px;
+ opacity: 0.85;
+}
\ No newline at end of file
diff --git a/src/views/business/erp/cost/firm-reports-form.vue b/src/views/business/erp/cost/firm-reports-form.vue
index 63ebb00..742eae2 100644
--- a/src/views/business/erp/cost/firm-reports-form.vue
+++ b/src/views/business/erp/cost/firm-reports-form.vue
@@ -399,17 +399,21 @@
calculatedPublicWelfareCost.value = Math.min(publicWelfareCost, remainingAllowedCost).toFixed(2);
- const actualTotalCost = annualActualCost.value + parseFloat(calculatedPublicWelfareCost.value);
- const ratio = (actualTotalCost / totalRevenue) * 100;
+ // 预计成本收入比 = 本季度预计公益成本 / 累计营业收入
+ const ratio = (parseFloat(calculatedPublicWelfareCost.value) / totalRevenue) * 100;
form.costIncomeRatio = ratio.toFixed(2);
} else {
calculatedPublicWelfareCost.value = publicWelfareCost.toFixed(2);
- form.costIncomeRatio = costRatio.value.toFixed(2);
+ // 预计成本收入比 = 本季度预计公益成本 / 累计营业收入
+ const ratio = (publicWelfareCost / totalRevenue) * 100;
+ form.costIncomeRatio = ratio.toFixed(2);
}
} else {
showCostWarning.value = false;
calculatedPublicWelfareCost.value = publicWelfareCost.toFixed(2);
- form.costIncomeRatio = costRatio.value.toFixed(2);
+ // 预计成本收入比 = 本季度预计公益成本 / 累计营业收入
+ const ratio = (publicWelfareCost / totalRevenue) * 100;
+ form.costIncomeRatio = ratio.toFixed(2);
}
} else {
showCostWarning.value = false;
@@ -484,15 +488,10 @@
// 修改当前季度的预上报公益成本为允许的最大值
saveData.publicWelfareCost = parseFloat(calculatedPublicWelfareCost.value);
- // 重新计算全年累计比例
+ // 重新计算本季预计占比(单季预计成本 / 累计营业收入)
const totalRevenue = safeParseFloat(saveData.revenue) + safeParseFloat(annualIncomeInfo.value.revenue);
- const annualTotalCost = annualActualCost.value + safeParseFloat(saveData.publicWelfareCost);
- let ratio = totalRevenue > 0 ? ((annualTotalCost / totalRevenue) * 100) : 0;
+ const ratio = totalRevenue > 0 ? ((safeParseFloat(saveData.publicWelfareCost) / totalRevenue) * 100) : 0;
- // 上限25%
- if (ratio > 25) {
- ratio = 25;
- }
saveData.costIncomeRatio = ratio.toFixed(2);
}
diff --git a/src/views/business/erp/service/service-applications-form.vue b/src/views/business/erp/service/service-applications-form.vue
index 9ae8f75..a144566 100644
--- a/src/views/business/erp/service/service-applications-form.vue
+++ b/src/views/business/erp/service/service-applications-form.vue
@@ -93,12 +93,12 @@
-
+
-
+
@@ -214,6 +214,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
证明材料
@@ -224,7 +238,7 @@
+
+
+
@@ -372,12 +375,14 @@ import dayjs from 'dayjs';
dataIndex: 'serviceStart',
ellipsis: true,
width: 100,
+ customRender: ({ text }) => text ? dayjs(text).format('YYYY-MM-DD HH:mm') : '',
},
{
title: '服务结束时间',
dataIndex: 'serviceEnd',
ellipsis: true,
width: 100,
+ customRender: ({ text }) => text ? dayjs(text).format('YYYY-MM-DD HH:mm') : '',
},
{
title: '服务时长(小时)',
@@ -450,6 +455,12 @@ import dayjs from 'dayjs';
dataIndex: 'associationAuditUserName',
ellipsis: true,
},
+ {
+ title: '备案编号',
+ dataIndex: 'filingNo',
+ ellipsis: true,
+ width: 150,
+ },
{
title: '操作',
@@ -472,6 +483,7 @@ import dayjs from 'dayjs';
firmAuditStatus: undefined, // 执业机构审核状态
firmAuditTimeRange: undefined, // 执业机构审核时间范围
associationAuditStatus: undefined, // 协会审核状态
+ filingNo: undefined, // 备案编号
selfFirmFilter: undefined, // 本人本所筛选条件
};
// 查询表单form
@@ -1487,19 +1499,18 @@ async function requestDelete(data){
return canReject;
} else if (isCtoRole.value || isFirmAdmin.value) {
- // CTO角色和行政人员角色:协会审核状态必须是驳回(4)且执业机构审核状态不能是驳回(4)
- if (record.associationAuditStatus !== 4) {
- console.log('驳回按钮不显示:协会审核状态不是驳回', record.associationAuditStatus);
- return false;
- }
+ // CTO角色和行政人员角色:
+ // 情况1:协会审核状态为驳回(4)且执业机构审核状态不能是驳回(4)
+ // 情况2:执业机构已审核通过(3)且协会审核状态为未提交(0/null/undefined)
+ const isAssociationRejected = record.associationAuditStatus === 4 && record.firmAuditStatus !== 4;
+ const isFirmApprovedNotReported = record.firmAuditStatus === 3 && (record.associationAuditStatus === 0 || record.associationAuditStatus === null || record.associationAuditStatus === undefined);
- // 执业机构审核状态不能是驳回(4)
- if (record.firmAuditStatus === 4) {
- console.log('驳回按钮不显示:执业机构审核状态是驳回', record.firmAuditStatus);
- return false;
+ if (isAssociationRejected || isFirmApprovedNotReported) {
+ return true;
}
- return true;
+ console.log('驳回按钮不显示:不满足(协会已驳回且律所未驳回),也不满足(律所已审核且协会未提交)');
+ return false;
}
return false;
diff --git a/src/views/business/erp/service/service-applications-report-list.vue b/src/views/business/erp/service/service-applications-report-list.vue
index 16cfe3f..ea2d1b5 100644
--- a/src/views/business/erp/service/service-applications-report-list.vue
+++ b/src/views/business/erp/service/service-applications-report-list.vue
@@ -290,12 +290,14 @@ import { getRoleInfo } from '/@/utils/role-util';
dataIndex: 'serviceStart',
ellipsis: true,
width: 100,
+ customRender: ({ text }) => text ? dayjs(text).format('YYYY-MM-DD HH:mm') : '',
},
{
title: '服务结束时间',
dataIndex: 'serviceEnd',
ellipsis: true,
width: 100,
+ customRender: ({ text }) => text ? dayjs(text).format('YYYY-MM-DD HH:mm') : '',
},
{
title: '服务时长(小时)',
diff --git a/src/views/mobile/service/create.vue b/src/views/mobile/service/create.vue
index 32ac68c..8e4eeea 100644
--- a/src/views/mobile/service/create.vue
+++ b/src/views/mobile/service/create.vue
@@ -118,11 +118,13 @@
@@ -131,11 +133,13 @@
@@ -671,8 +675,8 @@ async function handleFileUpload(event) {
}
for (let file of files) {
- if (file.size > 10 * 1024 * 1024) {
- message.error(`文件 ${file.name} 超过10MB限制`)
+ if (file.size > 50 * 1024 * 1024) {
+ message.error(`文件 ${file.name} 超过50MB限制`)
continue
}
@@ -1373,4 +1377,24 @@ onMounted(async () => {
font-size: 14px;
}
}
+
+/* 时间选择器优化(移动端滚动体验) */
+:deep(.ant-picker-time-panel) {
+ touch-action: pan-y;
+ -webkit-overflow-scrolling: touch;
+}
+
+:deep(.ant-picker-time-panel-column) {
+ -webkit-overflow-scrolling: touch;
+ overflow-y: auto;
+}
+
+:deep(.ant-picker-time-panel-cell-inner) {
+ font-size: 16px;
+ padding: 4px 0;
+}
+
+:deep(.ant-picker-dropdown) {
+ max-width: 100vw;
+}
\ No newline at end of file
diff --git a/src/views/mobile/service/detail.vue b/src/views/mobile/service/detail.vue
index fbc695a..49e8f84 100644
--- a/src/views/mobile/service/detail.vue
+++ b/src/views/mobile/service/detail.vue
@@ -159,7 +159,7 @@
服务结束时间
- 所属部门: {{ departmentName }}
+ 执业机构: {{ departmentName }}
{{ dayInfo }}
@@ -16,22 +16,13 @@
{{ lastLoginInfo }}
{{ heartSentence }}
-
-
-
+