Browse Source

服务修改,签约修改

master
wang 2 months ago
parent
commit
63cb3f97e5
  1. BIN
      dist.zip
  2. 34
      src/api/business/letter/letter-api.js
  3. 10
      src/api/business/service-applications/service-applications-api.js
  4. 2
      src/constants/support/file-const.js
  5. 2
      src/layout/components/side-help-doc/index.vue
  6. 431
      src/views/business/erp/letter/letter-list.vue
  7. 139
      src/views/business/erp/service/service-applications-form.vue
  8. 19
      src/views/business/erp/service/service-applications-list.vue
  9. 1276
      src/views/business/erp/service/service-applications-report-list.vue
  10. 20
      src/views/mobile/service/create.vue
  11. 30
      src/views/mobile/service/detail.vue
  12. 2
      src/views/system/home/components/agreement.vue
  13. 12
      vite.config.js

BIN
dist.zip

Binary file not shown.

34
src/api/business/letter/letter-api.js

@ -5,7 +5,7 @@
* @Date: 2025-12-22 17:43:06
* @Copyright 1
*/
import { postRequest, getRequest } from '/@/lib/axios';
import { postRequest, getRequest, getDownload } from '/@/lib/axios';
export const letterApi = {
@ -33,10 +33,40 @@ export const letterApi = {
/**
* 查看承诺书详情 @author wzh
*/
isLetter: (letterId) => {
detail: (letterId) => {
return getRequest(`/letter/detail/${letterId}`);
},
/**
* 检查用户是否已签署承诺书 @author wzh
*/
isLetter: (userId) => {
return getRequest(`/letter/isLetter/${userId}`);
},
/**
* 查询所有承诺书 @author wzh
*/
queryAllBook: () => {
return getRequest('/letter/queryAllBook');
},
/**
* 下载承诺书文件 @author wzh
*/
downloadLetter: (letterId) => {
return getDownload(`/letter/download/${letterId}`);
},
/**
* 上传承诺书证明文件 @author wzh
*/
uploadProof: (formData) => {
return postRequest('/letter/uploadProof', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
});
},
};

10
src/api/business/service-applications/service-applications-api.js

@ -9,13 +9,19 @@ import { postRequest, getRequest,getDownload, postDownload } from '/@/lib/axios'
export const serviceApplicationsApi = {
/**
* 分页查询 @author wzh
* 服务申报页面报告查询 @author wzh
*/
queryPageReport : (param) => {
return postRequest('/serviceApplications/queryPageReport', param);
},
/**
* 服务审批分页查询 @author wzh
*/
queryPage : (param) => {
return postRequest('/serviceApplications/queryPage', param);
},
/**
* 增加 @author wzh
*/

2
src/constants/support/file-const.js

@ -23,7 +23,7 @@ export const FILE_FOLDER_TYPE_ENUM = {
},
FEEDBACK: {
value: 4,
desc: '意见反馈',
desc: '承诺书',
},
};
export default {

2
src/layout/components/side-help-doc/index.vue

@ -20,7 +20,7 @@
<a href="http://8.148.67.92:9000/file/public/notice/c620241c460a4634afdb4b4cebf271d8_20260204121215.docx" target="_blank">
<file-outlined style="margin-right: 5px;" />
合肥市律师公益法律服务管理系统 全角色操作手册.docx
合肥市律师公益法律服务管理系统操作手册.docx
</a>
</div>

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

@ -50,10 +50,46 @@
</a-form>
<!---------- 查询表单form end ----------->
<!---------- 承诺书列表显示区域 begin ----------->
<a-card v-if="!isCeo" size="small" :bordered="false" :hoverable="true" style="margin-bottom: 16px;">
<template #title>
<span>承诺书列表</span>
</template>
<div style="display: flex; flex-wrap: wrap; gap: 16px;">
<div
v-for="item in noticeList"
:key="item.bookId || item.noticeId || item.id"
style="display: flex; align-items: center; padding: 8px 12px; background: #f5f5f5; border-radius: 4px; cursor: pointer;"
@click="downloadNoticeAttachment(item)"
:title="hasAttachment(item) ? '点击下载' : '暂无附件'"
>
<FileTextOutlined style="font-size: 16px; color: #1890ff; margin-right: 8px;" />
<span style="color: #1890ff; font-size: 14px;">{{ item.bookName || item.title }}</span>
<DownloadOutlined v-if="hasAttachment(item)" style="font-size: 12px; color: #1890ff; margin-left: 4px;" />
</div>
</div>
</a-card>
<!---------- 承诺书列表显示区域 end ----------->
<a-card size="small" :bordered="false" :hoverable="true">
<!---------- 表格操作行 begin ----------->
<a-row class="smart-table-btn-block">
<div class="smart-table-operate-block">
<!-- 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;">
<UploadOutlined />
上传律师承诺书
</a-button>
<a-button type="primary" @click="handleFirmUpload" :loading="proofUploadLoading" v-if="isFirmRole" style="margin-left: 8px;">
<UploadOutlined />
上传律所承诺书
</a-button>
</div>
<div class="smart-table-setting-block">
<TableOperator v-model="columns" :tableId="null" :refresh="queryData" />
@ -106,6 +142,43 @@
@cancel="handleAgreementCancel"
/>
<!-- 上传证明文件弹框 -->
<a-modal
v-model:visible="showUploadModal"
:title="letterType === 'user' ? '上传律师承诺书' : '上传律所承诺书'"
@cancel="showUploadModal = false"
:confirm-loading="proofUploadLoading"
@ok="handleUpload"
>
<a-form layout="vertical">
<a-form-item label="上传文件" required>
<a-upload
:file-list="proofFileList"
:customRequest="handleCustomUpload"
:max-count="1"
accept=".jpg,.jpeg,.png"
@change="handleFileChange"
>
<a-button>
<UploadOutlined />
选择文件
</a-button>
</a-upload>
<div v-if="proofFileList.length > 0" style="margin-top: 8px; color: #52c41a; font-size: 12px;">
已选择文件: {{ proofFileList[0].name }}
</div>
<div style="margin-top: 8px; color: #999; font-size: 12px;">
支持格式图片JPG/PNG文件大小不超过10MB
</div>
</a-form-item>
</a-form>
</a-modal>
<!-- 图片预览弹框 -->
<a-modal :footer="null" :open="previewVisible" @cancel="handleCancelPreview">
<img :src="previewUrl" alt="预览图片" style="width: 100%; max-height: 80vh; object-fit: contain;" />
</a-modal>
</a-card>
</template>
<script setup>
@ -114,8 +187,12 @@ import { message, Modal } from 'ant-design-vue';
import { SmartLoading } from '/@/components/framework/smart-loading';
import { letterApi } from '/@/api/business/letter/letter-api';
import { employeeApi } from '/@/api/system/employee-api';
import { noticeApi } from '/@/api/business/oa/notice-api';
import { fileApi } from '/@/api/support/file-api';
import { PAGE_SIZE_OPTIONS } from '/@/constants/common-const';
import { loginApi } from '/@/api/system/login-api';
import { smartSentry } from '/@/lib/smart-sentry';
import { FILE_FOLDER_TYPE_ENUM } from '/@/constants/support/file-const';
import TableOperator from '/@/components/support/table-operator/index.vue';
import LetterForm from './letter-form.vue';
import AgreementModal from '/@/views/system/home/components/agreement.vue';
@ -124,13 +201,13 @@ import AgreementModal from '/@/views/system/home/components/agreement.vue';
const columns = ref([
{
title: '承诺书名称',
dataIndex: 'letterName',
title: '用户名称',
dataIndex: 'userName',
ellipsis: true,
},
{
title: '用户名称',
dataIndex: 'userName',
title: '承诺书类型',
dataIndex: 'letterName',
ellipsis: true,
},
{
@ -153,18 +230,246 @@ import AgreementModal from '/@/views/system/home/components/agreement.vue';
//
async function viewDetail(record) {
try {
// letterId
currentLetterId.value = record.letterId;
showAgreementModal.value = true;
//
if (!record.fileUrl) {
message.warning('该承诺书没有附件文件');
return;
}
// 使fileUrl
const fileUrl = record.fileUrl;
//
const fileName = record.letterName || '';
const fileExtension = fileName.split('.').pop() || '';
showImagePreview(fileUrl);
} catch (error) {
console.error('预览承诺书失败:', error);
message.error('预览承诺书失败,请稍后重试');
}
}
//
const previewVisible = ref(false);
const previewUrl = ref('');
function showImagePreview(url) {
previewUrl.value = url;
previewVisible.value = true;
}
function handleCancelPreview() {
previewVisible.value = false;
previewUrl.value = '';
}
// ---------------------------- ----------------------------
//
const proofFileList = ref([]);
const proofUploadLoading = ref(false);
const letterType = ref('user'); //
const showUploadModal = ref(false);
const uploadedFileId = ref(null);
//
function beforeUploadProof(file) {
//
const isImage = file.type === 'image/jpeg' || file.type === 'image/jpg' || file.type === 'image/png';
if (!isImage) {
message.error('只能上传PDF、Word文档或图片文件!');
return false;
}
// 10MB
const isLt10M = file.size / 1024 / 1024 < 10;
if (!isLt10M) {
message.error('文件大小不能超过10MB!');
return false;
}
return true;
}
//
async function handleLawyerUpload() {
try {
//
const hasSigned = await checkUserSigned();
if (hasSigned) {
message.warning('您已经签署过律师承诺书,无需重复上传');
return;
}
//
letterType.value = 'user';
showUploadModal.value = true;
proofFileList.value = [];
} catch (error) {
console.error('查看承诺书详情失败:', error);
//
Modal.error({
title: '错误',
content: '获取承诺书详情失败,请稍后重试',
okText: '确定',
console.error('检查签约状态失败:', error);
message.error('检查签约状态失败,请稍后重试');
}
}
//
async function handleFirmUpload() {
try {
//
const hasSigned = await checkUserSigned();
if (hasSigned) {
message.warning('您已经签署过律所承诺书,无需重复上传');
return;
}
//
letterType.value = 'cto';
showUploadModal.value = true;
proofFileList.value = [];
} catch (error) {
console.error('检查签约状态失败:', error);
message.error('检查签约状态失败,请稍后重试');
}
}
//
function handleFileChange(info) {
let fileList = [...info.fileList];
//
fileList = fileList.slice(-1);
// originFileObj
fileList = fileList.map(file => {
if (file.response) {
// response
file.url = file.response.url;
}
return file;
});
proofFileList.value = fileList;
}
// -
async function handleCustomUpload(options) {
try {
const formData = new FormData();
formData.append('file', options.file);
const uploadResult = await fileApi.uploadFile(formData, FILE_FOLDER_TYPE_ENUM.FEEDBACK.value);
if (uploadResult.code === 0 && uploadResult.data) {
// onSuccessfile.response
options.onSuccess(uploadResult.data);
// response便handleUpload
if (proofFileList.value.length > 0) {
proofFileList.value[0].response = uploadResult;
}
} else {
// onError
options.onError(new Error(uploadResult.msg || '上传失败'));
}
} catch (error) {
// onError
options.onError(error);
}
}
//
async function handleUpload() {
if (proofFileList.value.length === 0) {
message.warning('请选择要上传的证明文件');
return;
}
try {
proofUploadLoading.value = true;
// customRequest
const file = proofFileList.value[0];
if (!file.response || !file.response.data) {
message.warning('文件尚未上传完成,请稍后重试');
return;
}
// ID -
const fileId = file.response.data.fileId;
if (!fileId) {
message.error('获取文件ID失败,请重新上传文件');
return;
}
// ID
const saveResult = await letterApi.add({
attachmentIds: fileId,
letterType: letterType.value,
fileUrl: file.response.data.fileUrl
});
if (saveResult.code === 0) {
// data
message.success(saveResult.data || '承诺书保存成功');
//
proofFileList.value = [];
//
queryData();
//
showUploadModal.value = false;
} else {
message.error(saveResult.msg || '保存承诺书失败');
}
} catch (error) {
console.error('保存承诺书失败:', error);
message.error('保存失败,请稍后重试');
} finally {
proofUploadLoading.value = false;
}
}
//
function hasAttachment(notice) {
//
return !!(notice.attachment || notice.fileKey || notice.fileId ||
notice.attachmentId || notice.fileUrl || notice.attachmentUrl);
}
// key
function getAttachmentFileKey(notice) {
// key
return notice.attachment || notice.fileKey || notice.fileId ||
notice.attachmentId || notice.fileUrl || notice.attachmentUrl;
}
//
async function downloadNoticeAttachment(notice) {
try {
SmartLoading.show();
// key
let fileKey = getAttachmentFileKey(notice);
if (!fileKey) {
message.warning('该公告没有附件文件');
return;
}
// 使file-api
await fileApi.downLoadFile(fileKey);
message.success('附件下载成功');
} catch (error) {
console.error('下载公告附件失败:', error);
message.error('下载附件失败,请稍后重试');
} finally {
SmartLoading.hide();
}
}
@ -202,6 +507,96 @@ import AgreementModal from '/@/views/system/home/components/agreement.vue';
//
const total = ref(0);
// ---------------------------- ----------------------------
// CEO
const isCeo = ref(false);
//
const isLawyerRole = ref(false);
//
const isFirmRole = ref(false);
//
async function getLoginInfo() {
try {
const res = await loginApi.getLoginInfo();
const loginInfo = res.data;
//
if (loginInfo) {
const roleCode = loginInfo.roleCode || '';
const userType = loginInfo.userType || '';
const departmentName = loginInfo.departmentName || '';
// roleCodeuserType
const roleLower = roleCode.toLowerCase();
isCeo.value = roleLower === 'ceo';
// user
isLawyerRole.value = roleLower === 'user' || userType === 'user';
// cto
isFirmRole.value = roleLower === 'cto' || userType === 'cto';
}
} catch (e) {
console.error('获取登录信息失败:', e);
}
}
//
async function checkUserSigned() {
try {
//
const loginRes = await loginApi.getLoginInfo();
const loginInfo = loginRes.data;
if (!loginInfo || !loginInfo.employeeId) {
console.error('无法获取当前用户ID');
return false;
}
// 使
const res = await letterApi.isLetter(loginInfo.employeeId);
if (res.code === 0 && res.data !== undefined) {
// truefalse
return res.data === true;
}
return false;
} catch (error) {
console.error('检查用户签约状态失败:', error);
// 退agreementSignFlag
try {
const loginRes = await loginApi.getLoginInfo();
const loginInfo = loginRes.data;
if (loginInfo) {
const agreementSignFlag = loginInfo.agreementSignFlag;
return agreementSignFlag === true;
}
} catch (fallbackError) {
console.error('回退检查用户签约状态失败:', fallbackError);
}
return false;
}
}
// ---------------------------- ----------------------------
//
const noticeList = ref([]);
//
async function queryNoticeData() {
try {
// 使
const result = await letterApi.queryAllBook();
if (result.data) {
noticeList.value = result.data;
}
} catch (error) {
console.error('查询承诺书数据失败:', error);
}
}
//
async function loadAllEmployees() {
if (employeeList.value.length > 0) {
@ -287,10 +682,18 @@ import AgreementModal from '/@/views/system/home/components/agreement.vue';
}
onMounted(() => {
onMounted(async () => {
//
await getLoginInfo();
queryData();
//
loadAllEmployees();
// CEO
if (!isCeo.value) {
queryNoticeData();
}
});
//

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

@ -93,12 +93,12 @@
<a-row :gutter="24">
<a-col :span="8">
<a-form-item label="服务开始时间" name="serviceStart" label-align="left">
<a-date-picker show-time format="YYYY-MM-DD HH:00:00" valueFormat="YYYY-MM-DD HH:00:00" v-model:value="form.serviceStart" style="width: 100%" placeholder="服务开始时间" :disabled="readonlyMode" />
<a-date-picker show-time format="YYYY-MM-DD HH:mm:ss" valueFormat="YYYY-MM-DD HH:mm:ss" v-model:value="form.serviceStart" style="width: 100%" placeholder="服务开始时间" :disabled="readonlyMode" />
</a-form-item>
</a-col>
<a-col :span="8">
<a-form-item label="服务结束时间" name="serviceEnd" label-align="left">
<a-date-picker show-time format="YYYY-MM-DD HH:00:00" valueFormat="YYYY-MM-DD HH:00:00" v-model:value="form.serviceEnd" style="width: 100%" placeholder="服务结束时间" :disabled="readonlyMode" />
<a-date-picker show-time format="YYYY-MM-DD HH:mm:ss" valueFormat="YYYY-MM-DD HH:mm:ss" v-model:value="form.serviceEnd" style="width: 100%" placeholder="服务结束时间" :disabled="readonlyMode" />
</a-form-item>
</a-col>
<a-col :span="8">
@ -107,9 +107,18 @@
<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-input-number
style="width: 100%"
v-model:value="form.serviceDuration"
placeholder="服务时长(小时)"
:disabled="readonlyMode"
:min="0"
:precision="1"
:parser="value => value.replace(/[^\d.]/g, '')"
@blur="handleServiceDurationBlur"
/>
</a-form-item>
<div style="font-size: 12px; color: #f00d0dff; margin-top: -12px; margin-bottom: 12px;">:不足30分钟不含本数不计入时长超过30分钟不足1个小时的含本数按照一个小时填报</div>
<div style="font-size: 12px; color: #f00d0dff; margin-top: -12px; margin-bottom: 12px;">:不足30分钟含30分钟按照0.5小时填报超过30分钟不足1小时的1小时按照1小时填报</div>
</a-col>
</a-row>
</template>
@ -130,7 +139,16 @@
<span>服务时长小时</span>
<span style="color: #999; font-size: 12px; margin-left: 4px;">请在{{ currentActivity.price }}范围内填写</span>
</template>
<a-input-number style="width: 100%" v-model:value="form.serviceDuration" placeholder="服务时长(小时)" :disabled="readonlyMode" />
<a-input-number
style="width: 100%"
v-model:value="form.serviceDuration"
placeholder="服务时长(小时)"
:disabled="readonlyMode"
:min="0"
:precision="2"
:parser="value => value.replace(/[^\d.]/g, '')"
@blur="handleServiceDurationBlur"
/>
</a-form-item>
</a-col>
@ -558,6 +576,40 @@
let form = reactive({ ...formDefault });
//
function formatServiceDuration(minutes) {
if (minutes <= 30) {
return 0.5; // 300.5
} else if (minutes <= 60) {
return 1; // 30601
} else {
// 1
const hours = Math.floor(minutes / 60);
const remainingMinutes = minutes % 60;
if (remainingMinutes === 0) {
return hours; //
} else if (remainingMinutes <= 30) {
return hours + 0.5; // 300.5
} else {
return hours + 1; // 301
}
}
}
//
function validateServiceDuration(hours) {
if (hours === undefined || hours === null || isNaN(hours) || hours < 0) {
return undefined;
}
//
const totalMinutes = Math.round(hours * 60);
// 使
return formatServiceDuration(totalMinutes);
}
//
watch(
() => [form.serviceStart, form.serviceEnd],
@ -567,9 +619,11 @@
const start = dayjs(startTime);
const end = dayjs(endTime);
if (end.isAfter(start)) {
// 2
//
const durationMinutes = end.diff(start, 'minute');
form.serviceDuration = parseFloat((durationMinutes / 60).toFixed(2));
//
form.serviceDuration = formatServiceDuration(durationMinutes);
} else {
form.serviceDuration = undefined;
message.warning('服务结束时间必须晚于开始时间');
@ -582,6 +636,20 @@
{ immediate: true }
);
//
watch(
() => form.serviceDuration,
(newValue, oldValue) => {
// undefinednull
if (newValue === undefined || newValue === null) {
return;
}
//
},
{ immediate: true }
);
//
watch(
() => form.activityNameId,
@ -700,6 +768,18 @@
return Promise.reject('你填写的此类公益活动时长超出该活动要求的100-200小时,请按规范要求填报具体时长');
}
}
//
if (value !== undefined && value !== null) {
//
const inputMinutes = Math.round(value * 60);
const formattedDuration = formatServiceDuration(inputMinutes);
//
if (Math.abs(formattedDuration - value) > 0.01) {
}
}
return Promise.resolve();
}
}
@ -823,6 +903,11 @@
message.success('保存成功');
emits('reloadList');
onClose();
//
setTimeout(() => {
window.location.reload();
}, 1000);
} catch (err) {
smartSentry.captureError(err);
} finally {
@ -871,6 +956,46 @@
show,
});
// blur
function handleServiceDurationBlur() {
const value = form.serviceDuration;
// valuenullundefined
if (value === null || value === undefined) {
return;
}
//
if (isNaN(value) || value < 0) {
//
form.serviceDuration = undefined;
message.warning('请输入有效的服务时长');
return;
}
//
if (value > 50) {
form.serviceDuration = 50;
message.warning('服务时长不能超过50小时');
return;
}
//
//
const inputMinutes = Math.round(value * 60);
// 使
const formattedDuration = formatServiceDuration(inputMinutes);
//
if (Math.abs(formattedDuration - value) > 0.01) {
//
message.info(`服务时长已自动调整为符合规则的值:${formattedDuration}小时`);
//
form.serviceDuration = formattedDuration;
}
}
// URL
function getFileUrl(file) {

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

@ -1,5 +1,5 @@
<!--
* 服务申报
* 服务审批
*
* @Author: wzh
* @Date: 2025-12-20 14:44:06
@ -45,12 +45,6 @@
</a-select-option>
</a-select>
</a-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">
@ -81,13 +75,13 @@
<a-row class="smart-table-btn-block">
<div class="smart-table-operate-block">
<!-- 新建申报按钮非协会角色且非CEO角色显示 -->
<!-- 新建申报按钮非协会角色且非CEO角色显示
<a-button v-if="!isAssociationRole && !isCeo" @click="showForm" type="primary">
<template #icon>
<PlusOutlined />
</template>
新建申报
</a-button>
</a-button>-->
<!-- 批量提交按钮非CEO角色显示 -->
<a-button v-if="!isCeo" @click="batchSubmit" type="primary" :disabled="selectedRowKeyList.length == 0">
@ -123,13 +117,13 @@
批量上报
</a-button>
<a-button v-if="!isCeo" @click="confirmBatchDelete" type="primary" danger :disabled="!canBatchDelete()">
<!--<a-button v-if="!isCeo" @click="confirmBatchDelete" type="primary" danger :disabled="!canBatchDelete()">
<template #icon>
<DeleteOutlined />
</template>
批量删除
</a-button>
<!--<a-button @click="showImportModal" type="primary">
<a-button @click="showImportModal" type="primary">
<template #icon>
<ImportOutlined />
</template>
@ -161,11 +155,8 @@
<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>

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

File diff suppressed because it is too large

20
src/views/mobile/service/create.vue

@ -150,7 +150,7 @@
class="form-input"
placeholder="服务时长(小时)"
/>
<div style="font-size: 12px; color: #f00d0d; margin-top: 6px;">:不足30分钟不含本数不计入时长超过30分钟不足1个小时的含本数按照一个小时填报</div>
<div style="font-size: 12px; color: #f00d0d; margin-top: 6px;">:不足30分钟不含本数按照0.5小时填报超过30分钟不足1个小时的含本数按照一个小时填报</div>
</div>
</template>
@ -195,25 +195,7 @@
/>
</div>
<!-- 服务时长 -->
<div class="form-item">
<label class="form-label required">服务时长小时</label>
<input
v-model="form.serviceDuration"
class="form-input"
placeholder="服务时长(小时)"
/>
<div style="font-size: 12px; color: #f00d0d; margin-top: 6px;">:服务时长必须在100-200小时范围内</div>
</div>
</template>
<!-- 加载中状态 -->
<template v-else key="loading-template">
<div class="form-item">
<div style="text-align: center; padding: 20px; color: #999;">
加载中...
</div>
</div>
</template>
</div>

30
src/views/mobile/service/detail.vue

@ -159,8 +159,8 @@
<label class="form-label">服务开始时间</label>
<a-date-picker
show-time
format="YYYY-MM-DD HH:00:00"
valueFormat="YYYY-MM-DD HH:00:00"
format="YYYY-MM-DD HH:mm:ss"
valueFormat="YYYY-MM-DD HH:mm:ss"
v-model:value="form.serviceStart"
class="form-input"
placeholder="服务开始时间"
@ -173,8 +173,8 @@
<label class="form-label">服务结束时间</label>
<a-date-picker
show-time
format="YYYY-MM-DD HH:00:00"
valueFormat="YYYY-MM-DD HH:00:00"
format="YYYY-MM-DD HH:mm:ss"
valueFormat="YYYY-MM-DD HH:mm:ss"
v-model:value="form.serviceEnd"
class="form-input"
placeholder="服务结束时间"
@ -194,7 +194,7 @@
placeholder="服务时长(小时)"
:readonly="readonlyMode"
/>
<div style="font-size: 12px; color: #f00d0d; margin-top: 6px;">:不足30分钟不含本数不计入时长超过30分钟不足1个小时的含本数按照一个小时填报</div>
<div style="font-size: 12px; color: #f00d0d; margin-top: 6px;">:不足30分钟不含本数按照0.5小时填报超过30分钟不足1个小时的含本数按照一个小时填报</div>
</div>
</template>
@ -241,26 +241,6 @@
/>
</div>
<!-- 服务时长 -->
<div class="form-item">
<label class="form-label">服务时长小时</label>
<input
v-model="form.serviceDuration"
class="form-input"
placeholder="服务时长(小时)"
:readonly="readonlyMode"
/>
<div style="font-size: 12px; color: #f00d0d; margin-top: 6px;">:服务时长必须在100-200小时范围内</div>
</div>
</template>
<!-- 加载中状态 -->
<template v-else>
<div class="form-item">
<div style="text-align: center; padding: 20px; color: #999;">
加载中...
</div>
</div>
</template>
</div>

2
src/views/system/home/components/agreement.vue

@ -89,7 +89,7 @@ async function getLetterDetail(letterId) {
loading.value = true;
// 使/letter/detail/{letterId}
const result = await letterApi.isLetter(letterId);
const result = await letterApi.detail(letterId);
if (result.data) {
Object.assign(noticeDetail, result.data);

12
vite.config.js

@ -35,20 +35,20 @@ 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/, ''), // 重写路径
},
'/mobile/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