Browse Source

fix:处罚和权限

master
“wangzihua” 3 months ago
parent
commit
513d3842de
  1. 9
      src/api/business/penalty-apply/penalty-apply-api.js
  2. 66
      src/views/business/erp/penalty-apply/penalty-apply-list.vue
  3. 2
      src/views/business/erp/service/ceo-service-detail.vue
  4. 3
      src/views/business/erp/service/law-firm-statistics.vue
  5. 6
      src/views/business/erp/service/service-applications-form.vue
  6. 130
      src/views/business/erp/service/service-applications-list.vue
  7. 8
      vite.config.js

9
src/api/business/penalty-apply/penalty-apply-api.js

@ -5,7 +5,7 @@
* @Date: 2026-01-07 21:36:44
* @Copyright 1.0
*/
import { postRequest, getRequest } from '/@/lib/axios';
import { postRequest, getRequest, getDownload } from '/@/lib/axios';
export const penaltyApplyApi = {
@ -45,4 +45,11 @@ export const penaltyApplyApi = {
return postRequest('/penaltyApply/batchDelete', idList);
},
/**
* 无处罚证明下载 @author wzh
*/
exportWordCertificate: (id) => {
return getDownload(`/wordCertificate/export/${id}`);
},
};

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

@ -51,12 +51,6 @@
</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" />
@ -80,9 +74,8 @@
<template v-if="column.dataIndex === 'action'">
<div class="smart-table-operate">
<a-space>
<a-button type="link" size="small" @click="showAuditModal(record)" :disabled="record.status !== 1">审批</a-button>
<a-button type="link" size="small" @click="handleDownload(record)" v-if="record.status === 3">下载</a-button>
<a-button type="link" size="small" danger @click="onDelete(record)">删除</a-button>
<a-button type="link" size="small" @click="showAuditModal(record)" :disabled="record.status !== 1" v-if="isCeo">审批</a-button>
<a-button type="link" size="small" @click="handleDownload(record)" v-if="record.status === 3 && isUser">下载</a-button>
</a-space>
</div>
</template>
@ -135,6 +128,7 @@
import { message, Modal } from 'ant-design-vue';
import { SmartLoading } from '/@/components/framework/smart-loading';
import { penaltyApplyApi } from '/@/api/business/penalty-apply/penalty-apply-api';
import { loginApi } from '/@/api/system/login-api';
import { PAGE_SIZE_OPTIONS } from '/@/constants/common-const';
import { REVIEW_ENUM } from '/@/constants/system/review-const';
import { smartSentry } from '/@/lib/smart-sentry';
@ -203,6 +197,15 @@ import PenaltyApplyForm from './penalty-apply-form.vue';
//
const total = ref(0);
//
const loginInfo = ref(null);
// CEO
const isCeo = ref(false);
// User
const isUser = ref(false);
//
function resetQuery() {
let pageSize = queryForm.pageSize;
@ -243,7 +246,39 @@ import PenaltyApplyForm from './penalty-apply-form.vue';
}
onMounted(queryData);
onMounted(() => {
getLoginInfo();
queryData();
});
//
async function getLoginInfo() {
try {
const res = await loginApi.getLoginInfo();
loginInfo.value = res.data;
checkUserRole(); //
console.log('登录信息:', res.data);
} catch (error) {
console.error('获取登录信息失败:', error);
}
}
//
function checkUserRole() {
if (loginInfo.value) {
//
const userRole = loginInfo.value.roleCode || loginInfo.value.roleName || '';
const roleLower = userRole.toLowerCase();
// CEO
isCeo.value = roleLower === 'ceo';
// User
isUser.value = roleLower === 'user';
console.log('用户角色:', userRole, 'isCeo:', isCeo.value, 'isUser:', isUser.value);
}
}
// ---------------------------- / ----------------------------
const formRef = ref();
@ -345,9 +380,14 @@ import PenaltyApplyForm from './penalty-apply-form.vue';
// ---------------------------- ----------------------------
//
function handleDownload(record) {
// API
console.log('下载无处罚证明:', record);
message.info('下载功能待实现');
try {
// APIgetDownload
penaltyApplyApi.exportWordCertificate(record.id);
message.success('下载请求已发送');
} catch (error) {
console.error('下载失败:', error);
message.error('下载失败,请稍后重试');
}
}
// ---------------------------- ----------------------------

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

@ -267,7 +267,7 @@ 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';
import TableOperator from '/@/components/support/table-operator/index.vue';
const router = useRouter();
const route = useRoute();

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

@ -106,6 +106,9 @@
<script setup>
import { ref, reactive, onMounted } from 'vue';
import { useRouter } from 'vue-router';
//
const router = useRouter();
import { SearchOutlined, ReloadOutlined } from '@ant-design/icons-vue';
import { message } from 'ant-design-vue';
import { serviceApplicationsApi } from '/@/api/business/service-applications/service-applications-api';

6
src/views/business/erp/service/service-applications-form.vue

@ -70,7 +70,11 @@
</a-form-item>
</a-col>
<a-col :span="8">
<a-form-item label="服务时长(小时)" name="serviceDuration">
<a-form-item name="serviceDuration">
<template #label>
<span>服务时长小时</span>
<span style="color: #999; font-size: 12px; margin-left: 4px;">可通过时间选择也可手动填写</span>
</template>
<a-input-number style="width: 100%" v-model:value="form.serviceDuration" placeholder="服务时长(小时)" :disabled="readonlyMode" />
</a-form-item>
<div style="font-size: 12px; color: #f00d0dff; margin-top: -12px; margin-bottom: 12px;">:不足30分钟不含本数不计入时长超过30分钟不足1个小时的含本数按照一个小时填报</div>

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

@ -12,7 +12,7 @@
<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="请选择执业机构" />
<DepartmentTreeSelect style="width: 250px" v-model:value="queryForm.firmId" placeholder="请选择执业机构" />
</a-form-item>
<a-form-item label="律师名称" class="smart-query-form-item">
<a-select
@ -38,14 +38,20 @@
<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="执业机构审核状态" v-if="isAssociationRole" class="smart-query-form-item">
<a-form-item label="执业机构审核状态" v-if="isCtoRole" 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-form-item label="本人本所" v-if="isCtoRole" class="smart-query-form-item">
<a-select style="width: 150px" v-model:value="queryForm.selfFirmFilter" placeholder="请选择筛选条件">
<a-select-option value="self">本人</a-select-option>
<a-select-option value="firm">本所</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="协会审核状态" v-if="isCeo" 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 }}
@ -117,7 +123,7 @@
批量上报
</a-button>
<a-button v-if="!isCeo" @click="confirmBatchDelete" type="primary" danger :disabled="selectedRowKeyList.length == 0">
<a-button v-if="!isCeo" @click="confirmBatchDelete" type="primary" danger :disabled="!canBatchDelete()">
<template #icon>
<DeleteOutlined />
</template>
@ -153,11 +159,14 @@
<template v-if="column.dataIndex === 'action'">
<div class="smart-table-operate">
<a-button @click="showDetail(record)" type="link">详情</a-button>
<!-- 执业机构审核状态为拒绝时只显示详情按钮 -->
<template v-if="record.firmAuditStatus !== 4">
<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>
</template>
</div>
</template>
</template>
@ -225,6 +234,8 @@
v-model:value="rejectForm.rejectReason"
placeholder="请输入驳回原因"
rows="4"
:maxlength="200"
show-count
style="resize: vertical;"
/>
</a-form-item>
@ -287,6 +298,7 @@
</template>
<script setup>
import { reactive, ref, onMounted } from 'vue';
import { useRoute } from 'vue-router';
import { message, Modal } from 'ant-design-vue';
import { SmartLoading } from '/@/components/framework/smart-loading';
import { serviceApplicationsApi } from '/@/api/business/service-applications/service-applications-api';
@ -306,6 +318,7 @@ import { loginApi } from '/@/api/system/login-api';
title: '执业机构',
dataIndex: 'departmentName',
ellipsis: true,
width: 180,
},
{
title: '律师名称',
@ -316,16 +329,19 @@ import { loginApi } from '/@/api/system/login-api';
title: '职务名称',
dataIndex: 'positionName',
ellipsis: true,
width: 100,
},
{
title: '服务开始时间',
dataIndex: 'serviceStart',
ellipsis: true,
width: 100,
},
{
title: '服务结束时间',
dataIndex: 'serviceEnd',
ellipsis: true,
width: 100,
},
{
title: '服务时长(小时)',
@ -412,6 +428,7 @@ import { loginApi } from '/@/api/system/login-api';
managerName: undefined, //
firmAuditStatus: undefined, //
associationAuditStatus: undefined, //
selfFirmFilter: undefined, //
};
// form
const queryForm = reactive({ ...queryFormState });
@ -452,6 +469,9 @@ import { loginApi } from '/@/api/system/login-api';
// CEOCEO
const isCeo = ref(false);
//
const isFirmRole = ref(false);
//
async function getLoginInfo() {
try {
@ -484,6 +504,12 @@ import { loginApi } from '/@/api/system/login-api';
roleLower.includes('律协') ||
roleLower.includes('律师协会');
//
isFirmRole.value = roleLower.includes('律所') ||
roleLower.includes('firm') ||
roleLower.includes('lawyer') ||
roleLower.includes('律师');
// CEOCEO
isCeo.value = roleLower === 'ceo';
@ -622,8 +648,8 @@ import { loginApi } from '/@/api/system/login-api';
//
Modal.confirm({
title: '批量上报确认',
content: `确定要将选中的 ${selectedRowKeyList.value.length} 条记录上报到协会审核吗?`,
onOk: handleBatchReport,
content: `确定要将选中的 ${canReportRecords.length}符合条件的记录上报到协会审核吗?`,
onOk: () => handleBatchReport(canReportRecords),
okText: '确定上报',
cancelText: '取消'
});
@ -631,31 +657,27 @@ import { loginApi } from '/@/api/system/login-api';
//
function canReportRecord(record) {
// CTO3
// 04
// 3
// 0
return record.firmAuditStatus === 3 &&
(record.associationAuditStatus === 0 || record.associationAuditStatus === 4);
record.associationAuditStatus === 0;
}
//
async function handleBatchReport() {
async function handleBatchReport(validRecords) {
try {
SmartLoading.show();
console.log('批量上报参数:', selectedRowKeyList.value);
// ID
const idList = validRecords.map(record => record.applicationId).map(id => Number(id));
// ValidateList<Long> idListID
// ID
const validIds = selectedRowKeyList.value.filter(id => id && !isNaN(id));
if (validIds.length === 0) {
message.warning('请选择要上报的记录');
if (idList.length === 0) {
message.warning('没有符合条件的记录可以上报');
SmartLoading.hide();
return;
}
// ValidateList<Long> ID
const idList = validIds.map(id => Number(id));
console.log('批量上报参数:', idList);
const res = await serviceApplicationsApi.batchSubmitAsFirm(idList);
@ -721,12 +743,36 @@ import { loginApi } from '/@/api/system/login-api';
queryData();
}
//
function processSelfFirmFilter(params) {
const processedParams = { ...params };
//
if (loginInfo.value && params.selfFirmFilter) {
if (params.selfFirmFilter === 'self') {
//
processedParams.userId = loginInfo.value.userId;
} else if (params.selfFirmFilter === 'firm') {
//
processedParams.firmId = loginInfo.value.departmentId;
}
// 'all'
}
//
delete processedParams.selfFirmFilter;
return processedParams;
}
//
async function queryData() {
tableLoading.value = true;
try {
//
let query = processQueryParams({ ...queryForm });
//
query = processSelfFirmFilter(query);
let queryResult = await serviceApplicationsApi.queryPage(query);
tableData.value = queryResult.data.list;
total.value = queryResult.data.total;
@ -738,16 +784,17 @@ import { loginApi } from '/@/api/system/login-api';
}
onMounted(async () => {
//
const route = useRoute();
onMounted(async () => {
await getLoginInfo();
// sessionStorageserviceFirmId
const firmId = sessionStorage.getItem('serviceFirmId');
// URLfirmId
const firmId = route.query.firmId;
if (firmId) {
// firmId
queryForm.firmId = firmId;
// sessionStoragefirmId使
sessionStorage.removeItem('serviceFirmId');
}
//
@ -892,6 +939,25 @@ function showAuditModal(record) {
selectedRowKeyList.value = selectedRowKeys;
}
//
function canBatchDelete() {
if (selectedRowKeyList.value.length === 0) {
return false;
}
//
const selectedRecords = tableData.value.filter(record =>
selectedRowKeyList.value.includes(record.applicationId)
);
//
const allUnsubmitted = selectedRecords.every(record =>
record.firmAuditStatus === 0
);
return allUnsubmitted;
}
//
function confirmBatchDelete() {
if (selectedRowKeyList.value.length === 0) {
@ -904,19 +970,19 @@ function showAuditModal(record) {
selectedRowKeyList.value.includes(record.applicationId)
);
//
//
const invalidRecords = selectedRecords.filter(record =>
record.firmAuditStatus !== 0 && record.firmAuditStatus !== 4
record.firmAuditStatus !== 0
);
if (invalidRecords.length > 0) {
message.warning('只能删除未提交或拒绝状态的数据');
message.warning('只能删除未提交状态的数据');
return;
}
Modal.confirm({
title: '提示',
content: '确定要批量删除这些未提交或拒绝状态的数据吗?',
content: '确定要批量删除这些未提交状态的数据吗?',
okText: '删除',
okType: 'danger',
onOk() {
@ -1148,12 +1214,18 @@ function showAuditModal(record) {
return canReject;
} else if (isCtoRole.value) {
// CTO4
// CTO44
if (record.associationAuditStatus !== 4) {
console.log('驳回按钮不显示:协会审核状态不是驳回', record.associationAuditStatus);
return false;
}
// 4
if (record.firmAuditStatus === 4) {
console.log('驳回按钮不显示:执业机构审核状态是驳回', record.firmAuditStatus);
return false;
}
return true;
}

8
vite.config.js

@ -35,14 +35,14 @@ export default {
proxy: {
// 代理API路径
'/api': {
//target: 'http://8.148.67.92:8080/', // 目标服务器地址
target: 'http://127.0.0.1:8080/',
target: 'http://8.148.67.92:8080/', // 目标服务器地址
//target: 'http://127.0.0.1:8080/',
changeOrigin: true, // 是否修改请求头中的 Origin 字段
rewrite: (path) => path.replace(/^\/api/, ''), // 重写路径
},
'/login': {
//target: 'http://8.148.67.92:8080/', // 目标服务器地址
target: 'http://127.0.0.1:8080/',
target: 'http://8.148.67.92:8080/', // 目标服务器地址
//target: 'http://127.0.0.1:8080/',
changeOrigin: true, // 是否修改请求头中的 Origin 字段
rewrite: (path) => path.replace(/^\/api/, ''), // 重写路径
},

Loading…
Cancel
Save