|
|
|
|
<template>
|
|
|
|
|
<div class="mobile-create-page">
|
|
|
|
|
<!-- 头部导航 -->
|
|
|
|
|
<div class="page-header">
|
|
|
|
|
<div class="header-left">
|
|
|
|
|
<button class="back-btn" @click="handleBack">
|
|
|
|
|
<span>←</span>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="header-title">
|
|
|
|
|
新建申报
|
|
|
|
|
</div>
|
|
|
|
|
<div class="header-right">
|
|
|
|
|
<!-- 占位 -->
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 表单内容 -->
|
|
|
|
|
<div class="form-content">
|
|
|
|
|
<!-- 基础信息 -->
|
|
|
|
|
<div class="form-section">
|
|
|
|
|
<div class="section-title">一、基础信息</div>
|
|
|
|
|
|
|
|
|
|
<!-- 姓名 -->
|
|
|
|
|
<div class="form-item">
|
|
|
|
|
<label class="form-label">姓名</label>
|
|
|
|
|
<input
|
|
|
|
|
v-model="form.actualName"
|
|
|
|
|
class="form-input"
|
|
|
|
|
placeholder="员工姓名"
|
|
|
|
|
disabled
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 执业证号 -->
|
|
|
|
|
<div class="form-item">
|
|
|
|
|
<label class="form-label">执业证号</label>
|
|
|
|
|
<input
|
|
|
|
|
v-model="form.certificateNumber"
|
|
|
|
|
class="form-input"
|
|
|
|
|
placeholder="执业证号"
|
|
|
|
|
disabled
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 执业机构 -->
|
|
|
|
|
<div class="form-item">
|
|
|
|
|
<label class="form-label">执业机构</label>
|
|
|
|
|
<input
|
|
|
|
|
v-model="form.firmName"
|
|
|
|
|
class="form-input"
|
|
|
|
|
placeholder="执业机构"
|
|
|
|
|
disabled
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 职务 -->
|
|
|
|
|
<div class="form-item">
|
|
|
|
|
<label class="form-label required">职务</label>
|
|
|
|
|
<select v-model="form.positionId" class="form-select">
|
|
|
|
|
<option value="">请选择职务</option>
|
|
|
|
|
<option
|
|
|
|
|
v-for="position in positionList"
|
|
|
|
|
:key="position.positionId"
|
|
|
|
|
:value="position.positionId"
|
|
|
|
|
>
|
|
|
|
|
{{ position.positionName }}
|
|
|
|
|
</option>
|
|
|
|
|
</select>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 服务信息 -->
|
|
|
|
|
<div class="form-section">
|
|
|
|
|
<div class="section-title">二、服务信息</div>
|
|
|
|
|
|
|
|
|
|
<!-- 活动类型 -->
|
|
|
|
|
<div class="form-item">
|
|
|
|
|
<label class="form-label required">活动类型</label>
|
|
|
|
|
<select
|
|
|
|
|
v-model="form.activityCategoryId"
|
|
|
|
|
class="form-select"
|
|
|
|
|
@change="onActivityCategoryChange"
|
|
|
|
|
>
|
|
|
|
|
<option value="">请选择活动类型</option>
|
|
|
|
|
<option
|
|
|
|
|
v-for="category in activityCategoryList"
|
|
|
|
|
:key="category.categoryId"
|
|
|
|
|
:value="category.categoryId"
|
|
|
|
|
>
|
|
|
|
|
{{ category.categoryName }}
|
|
|
|
|
</option>
|
|
|
|
|
</select>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 活动名称 -->
|
|
|
|
|
<div class="form-item">
|
|
|
|
|
<label class="form-label required">活动名称</label>
|
|
|
|
|
<select
|
|
|
|
|
v-model="form.activityNameId"
|
|
|
|
|
class="form-select"
|
|
|
|
|
>
|
|
|
|
|
<option value="">请选择活动名称</option>
|
|
|
|
|
<option
|
|
|
|
|
v-for="activity in activityList"
|
|
|
|
|
:key="activity.goodsId"
|
|
|
|
|
:value="activity.goodsId"
|
|
|
|
|
>
|
|
|
|
|
{{ activity.goodsName }}
|
|
|
|
|
</option>
|
|
|
|
|
</select>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- dict类型:显示服务时长、服务开始时间和服务结束时间 -->
|
|
|
|
|
<template v-if="currentActivityType === 'DICT'" key="dict-template">
|
|
|
|
|
<!-- 服务开始时间 -->
|
|
|
|
|
<div class="form-item">
|
|
|
|
|
<label class="form-label required">服务开始时间</label>
|
|
|
|
|
<a-date-picker
|
|
|
|
|
show-time
|
|
|
|
|
format="YYYY-MM-DD HH:00:00"
|
|
|
|
|
valueFormat="YYYY-MM-DD HH:00:00"
|
|
|
|
|
v-model:value="form.serviceStart"
|
|
|
|
|
class="form-input"
|
|
|
|
|
placeholder="服务开始时间"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 服务结束时间 -->
|
|
|
|
|
<div class="form-item">
|
|
|
|
|
<label class="form-label required">服务结束时间</label>
|
|
|
|
|
<a-date-picker
|
|
|
|
|
show-time
|
|
|
|
|
format="YYYY-MM-DD HH:00:00"
|
|
|
|
|
valueFormat="YYYY-MM-DD HH:00:00"
|
|
|
|
|
v-model:value="form.serviceEnd"
|
|
|
|
|
class="form-input"
|
|
|
|
|
placeholder="服务结束时间"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 服务时长 -->
|
|
|
|
|
<div class="form-item">
|
|
|
|
|
<label class="form-label required">
|
|
|
|
|
服务时长(小时)
|
|
|
|
|
<span style="color: #999; font-size: 12px; margin-left: 4px;">可通过时间选择也可手动填写</span>
|
|
|
|
|
</label>
|
|
|
|
|
<input
|
|
|
|
|
v-model="form.serviceDuration"
|
|
|
|
|
class="form-input"
|
|
|
|
|
placeholder="服务时长(小时)"
|
|
|
|
|
/>
|
|
|
|
|
<div style="font-size: 12px; color: #f00d0d; margin-top: 6px;">注:不足30分钟(不含本数)的,按照0.5小时填报,超过30分钟不足1个小时的(含本数),按照一个小时填报</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<!-- time类型:显示案件编号输入框,没有服务开始时间和服务结束时间 -->
|
|
|
|
|
<template v-else-if="currentActivityType === 'TIME'" key="time-template">
|
|
|
|
|
<!-- 案件编号 -->
|
|
|
|
|
<div class="form-item">
|
|
|
|
|
<label class="form-label required">案件编号</label>
|
|
|
|
|
<input
|
|
|
|
|
v-model="form.recordNo"
|
|
|
|
|
class="form-input"
|
|
|
|
|
placeholder="请输入案件编号"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 服务时长 -->
|
|
|
|
|
<div class="form-item">
|
|
|
|
|
<label class="form-label required">
|
|
|
|
|
服务时长(小时)
|
|
|
|
|
<span v-if="currentActivity.value?.price && currentActivity.value.price.includes('-')" style="color: #999; font-size: 12px; margin-left: 4px;">请在{{ currentActivity.value.price }}范围内填写</span>
|
|
|
|
|
</label>
|
|
|
|
|
<input
|
|
|
|
|
v-model="form.serviceDuration"
|
|
|
|
|
class="form-input"
|
|
|
|
|
placeholder="服务时长(小时)"
|
|
|
|
|
disabled
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<!-- amount类型:显示金额输入框 -->
|
|
|
|
|
<template v-else-if="currentActivityType === 'AMOUT'" key="amount-template">
|
|
|
|
|
<!-- 金额 -->
|
|
|
|
|
<div class="form-item">
|
|
|
|
|
<label class="form-label required">金额</label>
|
|
|
|
|
<input
|
|
|
|
|
type="number"
|
|
|
|
|
step="0.01"
|
|
|
|
|
v-model="form.workloadScore"
|
|
|
|
|
class="form-input"
|
|
|
|
|
placeholder="请输入金额"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 活动信息 -->
|
|
|
|
|
<div class="form-section">
|
|
|
|
|
<div class="section-title">三、活动信息</div>
|
|
|
|
|
|
|
|
|
|
<!-- 参加人数(受益人数) -->
|
|
|
|
|
<div class="form-item">
|
|
|
|
|
<label class="form-label required">参加人数(受益人数)</label>
|
|
|
|
|
<input
|
|
|
|
|
type="number"
|
|
|
|
|
v-model="form.beneficiaryCount"
|
|
|
|
|
class="form-input"
|
|
|
|
|
placeholder="参加人数(受益人数)"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 组织单位名称 -->
|
|
|
|
|
<div class="form-item">
|
|
|
|
|
<label class="form-label required">组织单位名称</label>
|
|
|
|
|
<input
|
|
|
|
|
v-model="form.organizerName"
|
|
|
|
|
class="form-input"
|
|
|
|
|
placeholder="组织单位名称"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 服务对象负责人/联系人姓名 -->
|
|
|
|
|
<div class="form-item">
|
|
|
|
|
<label class="form-label required">服务对象负责人/联系人姓名</label>
|
|
|
|
|
<input
|
|
|
|
|
v-model="form.organizerContact"
|
|
|
|
|
class="form-input"
|
|
|
|
|
placeholder="服务对象负责人/联系人姓名"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 联系方式 -->
|
|
|
|
|
<div class="form-item">
|
|
|
|
|
<label class="form-label required">联系方式</label>
|
|
|
|
|
<input
|
|
|
|
|
v-model="form.organizerPhone"
|
|
|
|
|
class="form-input"
|
|
|
|
|
placeholder="联系方式"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 服务内容 -->
|
|
|
|
|
<div class="form-item">
|
|
|
|
|
<label class="form-label required">服务内容描述</label>
|
|
|
|
|
<textarea
|
|
|
|
|
v-model="form.serviceContent"
|
|
|
|
|
class="form-textarea"
|
|
|
|
|
placeholder="请输入服务内容描述"
|
|
|
|
|
rows="4"
|
|
|
|
|
></textarea>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 证明材料 -->
|
|
|
|
|
<div class="form-section">
|
|
|
|
|
<div class="section-title">四、证明材料</div>
|
|
|
|
|
|
|
|
|
|
<div class="form-item">
|
|
|
|
|
<label class="form-label required">
|
|
|
|
|
证明材料
|
|
|
|
|
<span style="font-size: 12px; color: #f00d0d; margin-left: 4px;"> 注:(请上传活动方案、活动记录、照片、新闻报道等材料)支持图片(JPG/PNG)、文档(PDF/Word/PPT)格式,单文件最大10MB,最多上传5个文件</span>
|
|
|
|
|
</label>
|
|
|
|
|
|
|
|
|
|
<input
|
|
|
|
|
type="file"
|
|
|
|
|
class="file-input"
|
|
|
|
|
multiple
|
|
|
|
|
accept=".jpg,.jpeg,.png,.pdf,.doc,.docx,.ppt,.pptx"
|
|
|
|
|
@change="handleFileUpload"
|
|
|
|
|
:disabled="uploadedFiles.length >= 5"
|
|
|
|
|
/>
|
|
|
|
|
<!-- 文件列表 -->
|
|
|
|
|
<div class="file-list" v-if="uploadedFiles.length > 0">
|
|
|
|
|
<div
|
|
|
|
|
v-for="file in uploadedFiles"
|
|
|
|
|
:key="file.id"
|
|
|
|
|
class="file-item"
|
|
|
|
|
>
|
|
|
|
|
<span class="file-name">{{ file.name || file.fileName || '未命名文件' }}</span>
|
|
|
|
|
<button
|
|
|
|
|
class="remove-btn"
|
|
|
|
|
@click="removeFile(file.id)"
|
|
|
|
|
>
|
|
|
|
|
删除
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div v-else-if="form.attachmentIds && form.attachmentIds.trim()">
|
|
|
|
|
<div class="form-tip">证明材料已上传,但文件列表为空</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 操作按钮 -->
|
|
|
|
|
<div class="action-buttons">
|
|
|
|
|
<button
|
|
|
|
|
class="btn btn-secondary"
|
|
|
|
|
@click="handleSave"
|
|
|
|
|
:disabled="loading"
|
|
|
|
|
>
|
|
|
|
|
保存草稿
|
|
|
|
|
</button>
|
|
|
|
|
<button
|
|
|
|
|
class="btn btn-primary"
|
|
|
|
|
@click="handleSubmit"
|
|
|
|
|
:disabled="loading"
|
|
|
|
|
>
|
|
|
|
|
提交
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 承诺书弹框 -->
|
|
|
|
|
<AgreementModal
|
|
|
|
|
v-if="showAgreementModal"
|
|
|
|
|
:visible="showAgreementModal"
|
|
|
|
|
@confirm="handleAgreementConfirm"
|
|
|
|
|
@cancel="handleAgreementCancel"
|
|
|
|
|
/>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
import { ref, onMounted, reactive, watch, nextTick } from 'vue'
|
|
|
|
|
import { useRouter, useRoute } from 'vue-router'
|
|
|
|
|
import { message } from 'ant-design-vue'
|
|
|
|
|
import dayjs from 'dayjs'
|
|
|
|
|
import { loginApi } from '/@/api/system/login-api'
|
|
|
|
|
import { serviceApplicationsApi } from '/@/api/business/service-applications/service-applications-api'
|
|
|
|
|
import { positionApi } from '/@/api/system/position-api'
|
|
|
|
|
import { categoryApi } from '/@/api/business/category/category-api'
|
|
|
|
|
import { goodsApi } from '/@/api/business/goods/goods-api'
|
|
|
|
|
import { fileApi } from '/@/api/support/file-api'
|
|
|
|
|
import { letterApi } from '/@/api/business/letter/letter-api'
|
|
|
|
|
import { FILE_FOLDER_TYPE_ENUM } from '/@/constants/support/file-const'
|
|
|
|
|
import AgreementModal from '../components/agreement-modal.vue'
|
|
|
|
|
|
|
|
|
|
// 路由和加载状态
|
|
|
|
|
const router = useRouter()
|
|
|
|
|
const route = useRoute()
|
|
|
|
|
const loading = ref(false)
|
|
|
|
|
|
|
|
|
|
// 承诺书弹框状态
|
|
|
|
|
const showAgreementModal = ref(false)
|
|
|
|
|
const agreementSigned = ref(true)
|
|
|
|
|
|
|
|
|
|
// 标记是否为编辑模式(加载已有数据)
|
|
|
|
|
const isEditMode = ref(false)
|
|
|
|
|
|
|
|
|
|
// 表单数据
|
|
|
|
|
const form = reactive({
|
|
|
|
|
applicationId: undefined, //申报ID
|
|
|
|
|
userId: undefined, //姓名ID
|
|
|
|
|
actualName: undefined, //员工姓名
|
|
|
|
|
certificateNumber: undefined,
|
|
|
|
|
firmId: undefined, //执业机构ID
|
|
|
|
|
departmentName: undefined, //部门名称
|
|
|
|
|
serviceStart: undefined, //服务开始时间
|
|
|
|
|
serviceEnd: undefined, //服务结束时间
|
|
|
|
|
serviceDuration: undefined, //服务时长(小时)
|
|
|
|
|
positionId: undefined, //职务ID
|
|
|
|
|
activityCategoryId: undefined, //活动类型
|
|
|
|
|
activityNameId: undefined, //活动名称
|
|
|
|
|
recordNo: undefined, //案件编号
|
|
|
|
|
workloadScore: undefined, //金额
|
|
|
|
|
serviceType: undefined, //申报服务类型(使用timeType)
|
|
|
|
|
beneficiaryCount: undefined, //参加人数(受益人数)
|
|
|
|
|
organizerName: undefined, //组织单位名称
|
|
|
|
|
organizerContact: undefined, //服务对象负责人/联系人姓名
|
|
|
|
|
organizerPhone: undefined, //联系方式
|
|
|
|
|
serviceContent: undefined, //服务内容
|
|
|
|
|
firmAuditStatus: undefined, //执业机构审核状态
|
|
|
|
|
firmAuditOpinion: undefined, //执业机构审核意见
|
|
|
|
|
firmAuditUser: undefined, //执业机构审核人ID
|
|
|
|
|
firmAuditUserName: undefined, //执业机构审核人姓名
|
|
|
|
|
firmAuditTime: undefined, //执业机构审核时间
|
|
|
|
|
associationAuditStatus: undefined, //协会审核状态
|
|
|
|
|
associationAuditOpinion: undefined, //协会审核意见
|
|
|
|
|
associationAuditUser: undefined, //协会审核人ID
|
|
|
|
|
associationAuditUserName: undefined, //协会审核人姓名
|
|
|
|
|
associationAuditTime: undefined, //协会审核时间
|
|
|
|
|
recordStatus: undefined, //备案状态:0-未备案,1-已备案
|
|
|
|
|
recordTime: undefined, //备案时间
|
|
|
|
|
status: 0, //申报状态:0-草稿,1-待执业机构审核,2-待协会审核,3-审核通过,4-审核不通过
|
|
|
|
|
updateTime: undefined, //更新时间
|
|
|
|
|
attachmentIds: undefined, //附件ID列表,逗号分隔
|
|
|
|
|
firmName: undefined, //执业机构名称
|
|
|
|
|
activityName: undefined //活动名称
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 当前选中的活动和活动类型
|
|
|
|
|
const currentActivity = ref({});
|
|
|
|
|
const currentActivityType = ref('');
|
|
|
|
|
|
|
|
|
|
// 监听服务开始时间和结束时间变化,自动计算服务时长
|
|
|
|
|
watch(
|
|
|
|
|
() => [form.serviceStart, form.serviceEnd],
|
|
|
|
|
([startTime, endTime]) => {
|
|
|
|
|
// 只有在非编辑模式下或当前活动类型为DICT时才自动计算服务时长
|
|
|
|
|
if ((!isEditMode.value || currentActivityType.value === 'DICT') && (startTime && endTime)) {
|
|
|
|
|
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));
|
|
|
|
|
} else {
|
|
|
|
|
form.serviceDuration = undefined;
|
|
|
|
|
message.warning('服务结束时间必须晚于开始时间');
|
|
|
|
|
}
|
|
|
|
|
} else if (!isEditMode.value && (!startTime || !endTime)) {
|
|
|
|
|
// 只有在非编辑模式下才清空服务时长
|
|
|
|
|
form.serviceDuration = undefined;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{ immediate: true }
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// 下拉选项数据
|
|
|
|
|
const positionList = ref([])
|
|
|
|
|
const activityCategoryList = ref([])
|
|
|
|
|
const activityList = ref([])
|
|
|
|
|
const uploadedFiles = ref([])
|
|
|
|
|
|
|
|
|
|
// 获取用户信息并填充表单
|
|
|
|
|
async function getUserInfo() {
|
|
|
|
|
try {
|
|
|
|
|
const res = await loginApi.getLoginInfo()
|
|
|
|
|
const userInfo = res.data
|
|
|
|
|
|
|
|
|
|
// 填充用户信息(与PC端逻辑一致)
|
|
|
|
|
form.userId = userInfo.employeeId // 申报律师ID
|
|
|
|
|
form.actualName = userInfo.actualName || ''
|
|
|
|
|
form.certificateNumber = userInfo.licenseNumber || ''
|
|
|
|
|
form.firmId = userInfo.departmentId // 执业机构ID
|
|
|
|
|
form.firmName = userInfo.departmentName || ''
|
|
|
|
|
|
|
|
|
|
// 检查用户签约状态(与PC端逻辑一致)
|
|
|
|
|
console.log('用户签约状态 agreementSignFlag:', userInfo.agreementSignFlag)
|
|
|
|
|
agreementSigned.value = userInfo.agreementSignFlag === true
|
|
|
|
|
showAgreementModal.value = !agreementSigned.value
|
|
|
|
|
return userInfo.agreementSignFlag
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('获取用户信息失败:', error)
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 协议确认 - 签署承诺书
|
|
|
|
|
async function handleAgreementConfirm() {
|
|
|
|
|
try {
|
|
|
|
|
await letterApi.add()
|
|
|
|
|
message.success('承诺书签署成功')
|
|
|
|
|
showAgreementModal.value = false
|
|
|
|
|
agreementSigned.value = true
|
|
|
|
|
} catch (error) {
|
|
|
|
|
message.error('承诺书签署失败,请重新登录')
|
|
|
|
|
console.error('承诺书签署失败:', error)
|
|
|
|
|
// 签署失败,退出登录
|
|
|
|
|
localStorage.removeItem('token')
|
|
|
|
|
localStorage.removeItem('userInfo')
|
|
|
|
|
// 延迟跳转到登录页
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
router.push('/mobile/login')
|
|
|
|
|
}, 1500)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 协议取消
|
|
|
|
|
function handleAgreementCancel() {
|
|
|
|
|
message.warning('您需要同意平台协议才能使用系统')
|
|
|
|
|
showAgreementModal.value = false
|
|
|
|
|
// 退出登录
|
|
|
|
|
localStorage.removeItem('token')
|
|
|
|
|
localStorage.removeItem('userInfo')
|
|
|
|
|
// 延迟跳转到登录页
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
router.push('/mobile/login')
|
|
|
|
|
}, 1500)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取下拉选项数据
|
|
|
|
|
async function getSelectOptions() {
|
|
|
|
|
try {
|
|
|
|
|
// 获取职务列表 - 使用现有的接口
|
|
|
|
|
const positionRes = await positionApi.queryList()
|
|
|
|
|
positionList.value = positionRes.data || []
|
|
|
|
|
|
|
|
|
|
// 获取活动类型列表 - 使用现有的接口
|
|
|
|
|
const categoryRes = await categoryApi.queryCategoryTree({
|
|
|
|
|
categoryType: 1 // 商品分类
|
|
|
|
|
})
|
|
|
|
|
activityCategoryList.value = categoryRes.data || []
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('获取选项数据失败:', error)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 活动类型改变事件
|
|
|
|
|
async function onActivityCategoryChange() {
|
|
|
|
|
if (form.activityCategoryId) {
|
|
|
|
|
try {
|
|
|
|
|
console.log('开始获取活动列表,活动类型ID:', form.activityCategoryId)
|
|
|
|
|
// 根据活动类型获取活动名称列表 - 使用现有的接口
|
|
|
|
|
const activityRes = await goodsApi.queryGoodsList({
|
|
|
|
|
categoryId: form.activityCategoryId,
|
|
|
|
|
shelvesFlag: true, // 只查询上架的活动
|
|
|
|
|
pageNum: 1,
|
|
|
|
|
pageSize: 100 // 获取足够多的数据
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
console.log('获取活动列表成功:', activityRes.data?.list?.length || 0, '条记录')
|
|
|
|
|
// 将活动列表转换为下拉选项格式,保存完整的活动信息
|
|
|
|
|
activityList.value = activityRes.data?.list?.map(item => ({
|
|
|
|
|
label: item.goodsName,
|
|
|
|
|
value: item.goodsId,
|
|
|
|
|
goodsId: item.goodsId,
|
|
|
|
|
timeType: item.timeType,
|
|
|
|
|
...item
|
|
|
|
|
})) || []
|
|
|
|
|
|
|
|
|
|
// 保留现有的活动名称ID和活动名称,不要清空
|
|
|
|
|
if (form.activityNameId) {
|
|
|
|
|
const activityExists = activityList.value.some(item => item.goodsId === form.activityNameId)
|
|
|
|
|
console.log('检查活动是否存在:', form.activityNameId, '=>', activityExists)
|
|
|
|
|
|
|
|
|
|
if (!activityExists) {
|
|
|
|
|
// 如果当前活动不在新列表中,才清空
|
|
|
|
|
form.activityNameId = ''
|
|
|
|
|
form.activityName = ''
|
|
|
|
|
console.log('活动不在新列表中,清空选择')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('获取活动列表失败:', error)
|
|
|
|
|
activityList.value = []
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
activityList.value = []
|
|
|
|
|
form.activityNameId = ''
|
|
|
|
|
form.activityName = ''
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 监听活动名称变化,更新活动类型和设置默认服务时长
|
|
|
|
|
watch(
|
|
|
|
|
() => form.activityNameId,
|
|
|
|
|
(activityNameId, oldActivityNameId) => {
|
|
|
|
|
console.log('activityNameId变化:', { new: activityNameId, old: oldActivityNameId })
|
|
|
|
|
console.log('isEditMode:', isEditMode.value)
|
|
|
|
|
console.log('activityList长度:', activityList.value.length)
|
|
|
|
|
|
|
|
|
|
if (activityNameId) {
|
|
|
|
|
// 尝试使用严格相等和宽松相等来查找活动
|
|
|
|
|
const selectedActivity = activityList.value.find(activity => activity.goodsId === activityNameId || activity.goodsId == activityNameId);
|
|
|
|
|
console.log('找到的活动:', selectedActivity)
|
|
|
|
|
|
|
|
|
|
if (selectedActivity) {
|
|
|
|
|
currentActivity.value = selectedActivity;
|
|
|
|
|
currentActivityType.value = selectedActivity.timeType || '';
|
|
|
|
|
// 将timeType放入serviceType字段中传递给后端
|
|
|
|
|
form.serviceType = selectedActivity.timeType || '';
|
|
|
|
|
form.activityName = selectedActivity.goodsName;
|
|
|
|
|
|
|
|
|
|
console.log('更新后的currentActivityType:', currentActivityType.value)
|
|
|
|
|
console.log('当前form.serviceDuration:', form.serviceDuration)
|
|
|
|
|
|
|
|
|
|
// 根据活动类型设置默认服务时长
|
|
|
|
|
// 只有在非编辑模式下(即新建模式)才设置默认服务时长
|
|
|
|
|
if (!isEditMode.value) {
|
|
|
|
|
if (selectedActivity.timeType === 'TIME') {
|
|
|
|
|
// 检查活动是否有固定小时数(使用price字段)
|
|
|
|
|
if (selectedActivity.price) {
|
|
|
|
|
// 如果价格包含范围(有-),让用户自己填写
|
|
|
|
|
if (selectedActivity.price.includes('-')) {
|
|
|
|
|
form.serviceDuration = undefined;
|
|
|
|
|
} else {
|
|
|
|
|
// 固定使用活动中的小时数
|
|
|
|
|
form.serviceDuration = parseFloat(selectedActivity.price);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// 默认值
|
|
|
|
|
form.serviceDuration = 25;
|
|
|
|
|
}
|
|
|
|
|
} else if (selectedActivity.timeType === 'AMOUT') {
|
|
|
|
|
form.serviceDuration = undefined;
|
|
|
|
|
} else if (selectedActivity.timeType === 'DICT') {
|
|
|
|
|
// DICT类型:清空服务时长,让用户通过选择时间或手动填写
|
|
|
|
|
form.serviceDuration = undefined;
|
|
|
|
|
}
|
|
|
|
|
console.log('设置后的form.serviceDuration:', form.serviceDuration)
|
|
|
|
|
} else {
|
|
|
|
|
console.log('编辑模式下,保留原有的form.serviceDuration:', form.serviceDuration)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.log('活动名称变化,更新后的活动类型:', currentActivityType.value);
|
|
|
|
|
} else {
|
|
|
|
|
console.log('未找到对应的活动,activityList:', activityList.value)
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
currentActivity.value = {};
|
|
|
|
|
currentActivityType.value = '';
|
|
|
|
|
form.serviceType = '';
|
|
|
|
|
form.activityName = '';
|
|
|
|
|
console.log('activityNameId为空,重置所有值')
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{ immediate: true }
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 活动名称改变事件
|
|
|
|
|
function onActivityNameChange() {
|
|
|
|
|
// 由watch监听器处理
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 文件上传处理
|
|
|
|
|
async function handleFileUpload(event) {
|
|
|
|
|
const files = event.target.files
|
|
|
|
|
if (files.length + uploadedFiles.value.length > 5) {
|
|
|
|
|
message.error('最多只能上传5个文件')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (let file of files) {
|
|
|
|
|
if (file.size > 10 * 1024 * 1024) {
|
|
|
|
|
message.error(`文件 ${file.name} 超过10MB限制`)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 立即上传文件
|
|
|
|
|
try {
|
|
|
|
|
const fileFormData = new FormData()
|
|
|
|
|
fileFormData.append('file', file)
|
|
|
|
|
|
|
|
|
|
console.log('开始上传文件:', file.name)
|
|
|
|
|
const uploadRes = await fileApi.uploadFile(fileFormData, FILE_FOLDER_TYPE_ENUM.COMMON.value)
|
|
|
|
|
|
|
|
|
|
if (uploadRes.code === 0 && uploadRes.data) {
|
|
|
|
|
console.log('文件上传成功:', file.name, '文件ID:', uploadRes.data.fileId)
|
|
|
|
|
uploadedFiles.value.push({
|
|
|
|
|
id: uploadRes.data.fileId,
|
|
|
|
|
name: file.name,
|
|
|
|
|
file: file,
|
|
|
|
|
fileId: uploadRes.data.fileId,
|
|
|
|
|
status: 'success'
|
|
|
|
|
})
|
|
|
|
|
message.success(`文件 ${file.name} 上传成功`)
|
|
|
|
|
} else {
|
|
|
|
|
throw new Error(uploadRes.msg || '上传失败')
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('文件上传失败:', file.name, error)
|
|
|
|
|
message.error(`文件 ${file.name} 上传失败: ${error.message}`)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 清空input
|
|
|
|
|
event.target.value = ''
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 删除文件
|
|
|
|
|
function removeFile(fileId) {
|
|
|
|
|
uploadedFiles.value = uploadedFiles.value.filter(file => file.id !== fileId)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 保存草稿
|
|
|
|
|
async function handleSave() {
|
|
|
|
|
// 表单验证
|
|
|
|
|
if (!form.positionId) {
|
|
|
|
|
message.error('请选择职务')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!form.activityCategoryId) {
|
|
|
|
|
message.error('请选择活动类型')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!form.activityNameId) {
|
|
|
|
|
message.error('请选择活动名称')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 根据活动类型验证不同字段
|
|
|
|
|
if (currentActivityType.value === 'DICT' || !currentActivityType.value) {
|
|
|
|
|
// DICT类型:验证服务开始时间、服务结束时间和服务时长
|
|
|
|
|
if (!form.serviceStart) {
|
|
|
|
|
message.error('请选择服务开始时间')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!form.serviceEnd) {
|
|
|
|
|
message.error('请选择服务结束时间')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!form.serviceDuration) {
|
|
|
|
|
message.error('请填写服务时长')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
} else if (currentActivityType.value === 'TIME') {
|
|
|
|
|
// TIME类型:验证案件编号和服务时长
|
|
|
|
|
if (!form.recordNo) {
|
|
|
|
|
message.error('请填写案件编号')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!form.serviceDuration) {
|
|
|
|
|
message.error('请填写服务时长')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果活动有小时范围,验证用户填写的时长是否在范围内
|
|
|
|
|
if (currentActivity.value.price && currentActivity.value.price.includes('-')) {
|
|
|
|
|
const [min, max] = currentActivity.value.price.split('-').map(Number);
|
|
|
|
|
if (form.serviceDuration < min || form.serviceDuration > max) {
|
|
|
|
|
message.error(`你填写的此类公益活动时长超出该活动要求的${currentActivity.value.price}小时,请按规范要求填报具体时长`)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (currentActivityType.value === 'AMOUT') {
|
|
|
|
|
// AMOUT类型:验证金额和服务时长
|
|
|
|
|
if (!form.workloadScore) {
|
|
|
|
|
message.error('请填写金额')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!form.serviceDuration) {
|
|
|
|
|
message.error('请填写服务时长')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (form.serviceDuration < 100 || form.serviceDuration > 200) {
|
|
|
|
|
message.error('你填写的此类公益活动时长超出该活动要求的100-200小时,请按规范要求填报具体时长')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!form.beneficiaryCount) {
|
|
|
|
|
message.error('请填写参加人数(受益人数)')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!form.organizerName) {
|
|
|
|
|
message.error('请填写组织单位名称')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!form.organizerContact) {
|
|
|
|
|
message.error('请填写服务对象负责人/联系人姓名')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!form.organizerPhone) {
|
|
|
|
|
message.error('请填写联系方式')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!form.serviceContent) {
|
|
|
|
|
message.error('请填写服务内容描述')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (uploadedFiles.value.length === 0) {
|
|
|
|
|
message.error('请上传证明材料')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
loading.value = true
|
|
|
|
|
try {
|
|
|
|
|
// 1. 获取已上传文件的ID列表
|
|
|
|
|
const fileIds = uploadedFiles.value.map(file => file.id).filter(id => id)
|
|
|
|
|
|
|
|
|
|
console.log('保存草稿,文件ID列表:', fileIds)
|
|
|
|
|
|
|
|
|
|
// 2. 调用保存草稿接口 - 使用现有的接口
|
|
|
|
|
const res = await serviceApplicationsApi.add({
|
|
|
|
|
...form,
|
|
|
|
|
attachmentIds: fileIds.join(','), // 将文件ID列表转换为逗号分隔的字符串
|
|
|
|
|
// 添加必要的参数
|
|
|
|
|
status: 4 // 草稿状态
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
if (res.code === 0) {
|
|
|
|
|
message.success('保存成功')
|
|
|
|
|
router.push('/mobile/service')
|
|
|
|
|
} else {
|
|
|
|
|
message.error(res.msg || '保存失败')
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('保存草稿失败:', error)
|
|
|
|
|
} finally {
|
|
|
|
|
loading.value = false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 提交
|
|
|
|
|
async function handleSubmit() {
|
|
|
|
|
// 表单验证
|
|
|
|
|
if (!form.positionId) {
|
|
|
|
|
message.error('请选择职务')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!form.activityCategoryId) {
|
|
|
|
|
message.error('请选择活动类型')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!form.activityNameId) {
|
|
|
|
|
message.error('请选择活动名称')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 根据活动类型验证不同字段
|
|
|
|
|
if (currentActivityType.value === 'DICT' || !currentActivityType.value) {
|
|
|
|
|
// DICT类型:验证服务开始时间、服务结束时间和服务时长
|
|
|
|
|
if (!form.serviceStart) {
|
|
|
|
|
message.error('请选择服务开始时间')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!form.serviceEnd) {
|
|
|
|
|
message.error('请选择服务结束时间')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!form.serviceDuration) {
|
|
|
|
|
message.error('请填写服务时长')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
} else if (currentActivityType.value === 'TIME') {
|
|
|
|
|
// TIME类型:验证案件编号和服务时长
|
|
|
|
|
if (!form.recordNo) {
|
|
|
|
|
message.error('请填写案件编号')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!form.serviceDuration) {
|
|
|
|
|
message.error('请填写服务时长')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果活动有小时范围,验证用户填写的时长是否在范围内
|
|
|
|
|
if (currentActivity.value.price && currentActivity.value.price.includes('-')) {
|
|
|
|
|
const [min, max] = currentActivity.value.price.split('-').map(Number);
|
|
|
|
|
if (form.serviceDuration < min || form.serviceDuration > max) {
|
|
|
|
|
message.error(`你填写的此类公益活动时长超出该活动要求的${currentActivity.value.price}小时,请按规范要求填报具体时长`)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (currentActivityType.value === 'AMOUT') {
|
|
|
|
|
// AMOUT类型:验证金额和服务时长
|
|
|
|
|
if (!form.workloadScore) {
|
|
|
|
|
message.error('请填写金额')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!form.serviceDuration) {
|
|
|
|
|
message.error('请填写服务时长')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (form.serviceDuration < 100 || form.serviceDuration > 200) {
|
|
|
|
|
message.error('你填写的此类公益活动时长超出该活动要求的100-200小时,请按规范要求填报具体时长')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!form.beneficiaryCount) {
|
|
|
|
|
message.error('请填写参加人数(受益人数)')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!form.organizerName) {
|
|
|
|
|
message.error('请填写组织单位名称')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!form.organizerContact) {
|
|
|
|
|
message.error('请填写服务对象负责人/联系人姓名')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!form.organizerPhone) {
|
|
|
|
|
message.error('请填写联系方式')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!form.serviceContent) {
|
|
|
|
|
message.error('请填写服务内容描述')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (uploadedFiles.value.length === 0) {
|
|
|
|
|
message.error('请上传证明材料')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
loading.value = true
|
|
|
|
|
try {
|
|
|
|
|
// 1. 获取已上传文件的ID列表
|
|
|
|
|
const fileIds = uploadedFiles.value.map(file => file.id).filter(id => id)
|
|
|
|
|
|
|
|
|
|
console.log('提交申报,文件ID列表:', fileIds)
|
|
|
|
|
|
|
|
|
|
// 2. 调用提交接口 - 使用现有的接口
|
|
|
|
|
const res = await serviceApplicationsApi.submit({
|
|
|
|
|
...form,
|
|
|
|
|
attachmentIds: fileIds.join(',') // 将文件ID列表转换为逗号分隔的字符串
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
if (res.code === 0) {
|
|
|
|
|
message.success('提交成功')
|
|
|
|
|
router.push('/mobile/service')
|
|
|
|
|
} else {
|
|
|
|
|
message.error(res.msg || '提交失败')
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('提交失败:', error)
|
|
|
|
|
} finally {
|
|
|
|
|
loading.value = false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 返回
|
|
|
|
|
function handleBack() {
|
|
|
|
|
router.back()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 根据attachmentIds获取文件列表
|
|
|
|
|
async function getFileListByAttachmentIds(attachmentIds) {
|
|
|
|
|
try {
|
|
|
|
|
if (!attachmentIds || !attachmentIds.trim()) {
|
|
|
|
|
uploadedFiles.value = []
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.log('开始获取文件列表,attachmentIds:', attachmentIds)
|
|
|
|
|
|
|
|
|
|
// 直接传递attachmentIds字符串,后端接口接收字符串参数
|
|
|
|
|
const result = await fileApi.getFileList(attachmentIds)
|
|
|
|
|
console.log('文件列表API返回结果:', result)
|
|
|
|
|
|
|
|
|
|
if (result.code === 0 && result.data && result.data.length > 0) {
|
|
|
|
|
// 将返回的文件列表转换为前端需要的格式
|
|
|
|
|
uploadedFiles.value = result.data.map(file => ({
|
|
|
|
|
id: file.fileId,
|
|
|
|
|
name: file.fileName,
|
|
|
|
|
fileId: file.fileId,
|
|
|
|
|
status: 'success'
|
|
|
|
|
}))
|
|
|
|
|
console.log('文件列表加载成功,文件数量:', uploadedFiles.value.length)
|
|
|
|
|
console.log('文件详情:', uploadedFiles.value)
|
|
|
|
|
} else {
|
|
|
|
|
uploadedFiles.value = []
|
|
|
|
|
console.log('文件列表为空或返回错误')
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('获取文件列表失败:', error)
|
|
|
|
|
uploadedFiles.value = []
|
|
|
|
|
message.error('获取文件列表失败')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 加载草稿数据
|
|
|
|
|
async function loadDraftData(applicationId) {
|
|
|
|
|
loading.value = true
|
|
|
|
|
isEditMode.value = true // 标记为编辑模式
|
|
|
|
|
try {
|
|
|
|
|
const res = await serviceApplicationsApi.queryDetail(applicationId)
|
|
|
|
|
if (res.code === 0) {
|
|
|
|
|
// 将草稿数据合并到表单中
|
|
|
|
|
Object.assign(form, res.data)
|
|
|
|
|
console.log('草稿数据加载成功:', res.data)
|
|
|
|
|
console.log('草稿数据 - 活动类型ID:', form.activityCategoryId)
|
|
|
|
|
console.log('草稿数据 - 活动名称ID:', form.activityNameId)
|
|
|
|
|
console.log('草稿数据 - 活动名称:', form.activityName)
|
|
|
|
|
|
|
|
|
|
// 确保活动类型列表已加载
|
|
|
|
|
await getSelectOptions()
|
|
|
|
|
|
|
|
|
|
// 如果有活动类型ID,获取对应的活动列表
|
|
|
|
|
if (form.activityCategoryId) {
|
|
|
|
|
console.log('草稿数据有活动类型ID,开始获取活动列表:', form.activityCategoryId)
|
|
|
|
|
await onActivityCategoryChange()
|
|
|
|
|
|
|
|
|
|
// 获取活动列表后,根据活动名称ID更新currentActivity和currentActivityType
|
|
|
|
|
if (form.activityNameId && activityList.value.length > 0) {
|
|
|
|
|
// 尝试使用严格相等和宽松相等来查找活动
|
|
|
|
|
const selectedActivity = activityList.value.find(activity => activity.goodsId === form.activityNameId || activity.goodsId == form.activityNameId)
|
|
|
|
|
if (selectedActivity) {
|
|
|
|
|
currentActivity.value = selectedActivity
|
|
|
|
|
currentActivityType.value = selectedActivity.timeType || ''
|
|
|
|
|
form.serviceType = selectedActivity.timeType || ''
|
|
|
|
|
console.log('更新后的活动类型:', currentActivityType.value)
|
|
|
|
|
console.log('更新后的活动信息:', currentActivity.value)
|
|
|
|
|
console.log('表单中的服务时长:', form.serviceDuration)
|
|
|
|
|
console.log('表单中的案件编号:', form.recordNo)
|
|
|
|
|
} else {
|
|
|
|
|
console.log('未找到对应的活动,活动名称ID:', form.activityNameId)
|
|
|
|
|
console.log('活动列表:', activityList.value)
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
console.log('活动名称ID或活动列表为空:', form.activityNameId, activityList.value.length)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 强制更新一次表单,确保模板能够正确渲染
|
|
|
|
|
// 等待Vue的响应式系统更新完成
|
|
|
|
|
await nextTick()
|
|
|
|
|
console.log('模板渲染后的currentActivityType:', currentActivityType.value)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果有附件ID,则加载文件列表
|
|
|
|
|
if (res.data.attachmentIds) {
|
|
|
|
|
await getFileListByAttachmentIds(res.data.attachmentIds)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
message.error(res.msg || '加载草稿数据失败')
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('加载草稿数据失败:', error)
|
|
|
|
|
} finally {
|
|
|
|
|
loading.value = false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
isEditMode.value = false // 重置为新建模式
|
|
|
|
|
getUserInfo()
|
|
|
|
|
getSelectOptions()
|
|
|
|
|
|
|
|
|
|
// 检查是否有applicationId参数(编辑草稿模式)
|
|
|
|
|
const applicationId = route.query.applicationId
|
|
|
|
|
if (applicationId) {
|
|
|
|
|
console.log('编辑草稿模式,applicationId:', applicationId)
|
|
|
|
|
loadDraftData(applicationId)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
.mobile-create-page {
|
|
|
|
|
min-height: 100vh;
|
|
|
|
|
background-color: #f5f5f5;
|
|
|
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 头部导航 */
|
|
|
|
|
.page-header {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
height: 44px;
|
|
|
|
|
background: linear-gradient(135deg, #1890ff 0%, #096dd9 100%);
|
|
|
|
|
color: white;
|
|
|
|
|
padding: 0 16px;
|
|
|
|
|
position: sticky;
|
|
|
|
|
top: 0;
|
|
|
|
|
z-index: 100;
|
|
|
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.back-btn {
|
|
|
|
|
background: none;
|
|
|
|
|
border: none;
|
|
|
|
|
color: white;
|
|
|
|
|
font-size: 20px;
|
|
|
|
|
padding: 8px;
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
transition: background-color 0.3s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.back-btn:active {
|
|
|
|
|
background-color: rgba(255, 255, 255, 0.2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.header-title {
|
|
|
|
|
font-size: 17px;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
flex: 1;
|
|
|
|
|
text-align: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 表单内容 */
|
|
|
|
|
.form-content {
|
|
|
|
|
padding: 16px;
|
|
|
|
|
padding-bottom: 80px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form-section {
|
|
|
|
|
background: white;
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
padding: 16px;
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
|
|
|
|
border: 1px solid #e8e8e8;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.section-title {
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
color: #333;
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
padding-bottom: 8px;
|
|
|
|
|
border-bottom: 1px solid #f0f0f0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form-item {
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form-label {
|
|
|
|
|
display: block;
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
color: #555;
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form-label.required::after {
|
|
|
|
|
content: '*';
|
|
|
|
|
color: #ff4d4f;
|
|
|
|
|
margin-left: 4px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form-input,
|
|
|
|
|
.form-select,
|
|
|
|
|
.form-textarea {
|
|
|
|
|
width: 100%;
|
|
|
|
|
padding: 10px 12px;
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
border: 1px solid #d9d9d9;
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
transition: all 0.3s;
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form-input:focus,
|
|
|
|
|
.form-select:focus,
|
|
|
|
|
.form-textarea:focus {
|
|
|
|
|
outline: none;
|
|
|
|
|
border-color: #1890ff;
|
|
|
|
|
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form-textarea {
|
|
|
|
|
resize: vertical;
|
|
|
|
|
min-height: 80px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form-tip {
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
color: #999;
|
|
|
|
|
margin-top: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.file-input {
|
|
|
|
|
display: block;
|
|
|
|
|
width: 100%;
|
|
|
|
|
padding: 10px;
|
|
|
|
|
border: 1px dashed #d9d9d9;
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
background-color: #fafafa;
|
|
|
|
|
transition: all 0.3s;
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.file-input:hover {
|
|
|
|
|
border-color: #1890ff;
|
|
|
|
|
background-color: #e6f7ff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.file-input:disabled {
|
|
|
|
|
cursor: not-allowed;
|
|
|
|
|
opacity: 0.6;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.file-list {
|
|
|
|
|
margin-top: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.file-item {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
padding: 8px 12px;
|
|
|
|
|
background-color: #fafafa;
|
|
|
|
|
border: 1px solid #e8e8e8;
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.file-name {
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
color: #555;
|
|
|
|
|
flex: 1;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
margin-right: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.remove-btn {
|
|
|
|
|
background-color: #ff4d4f;
|
|
|
|
|
color: white;
|
|
|
|
|
border: none;
|
|
|
|
|
padding: 4px 12px;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
transition: background-color 0.3s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.remove-btn:hover {
|
|
|
|
|
background-color: #ff7875;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 操作按钮 */
|
|
|
|
|
.action-buttons {
|
|
|
|
|
display: flex;
|
|
|
|
|
gap: 12px;
|
|
|
|
|
padding: 16px;
|
|
|
|
|
background-color: white;
|
|
|
|
|
position: fixed;
|
|
|
|
|
bottom: 0;
|
|
|
|
|
left: 0;
|
|
|
|
|
right: 0;
|
|
|
|
|
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.08);
|
|
|
|
|
border-top: 1px solid #e8e8e8;
|
|
|
|
|
z-index: 100;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.btn {
|
|
|
|
|
flex: 1;
|
|
|
|
|
padding: 12px;
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
border: none;
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
transition: all 0.3s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.btn-primary {
|
|
|
|
|
background: linear-gradient(135deg, #1890ff 0%, #096dd9 100%);
|
|
|
|
|
color: white;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.btn-primary:hover {
|
|
|
|
|
opacity: 0.9;
|
|
|
|
|
transform: translateY(-1px);
|
|
|
|
|
box-shadow: 0 4px 12px rgba(24, 144, 255, 0.3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.btn-primary:disabled {
|
|
|
|
|
opacity: 0.6;
|
|
|
|
|
cursor: not-allowed;
|
|
|
|
|
transform: none;
|
|
|
|
|
box-shadow: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.btn-secondary {
|
|
|
|
|
background-color: #f0f0f0;
|
|
|
|
|
color: #666;
|
|
|
|
|
border: 1px solid #d9d9d9;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.btn-secondary:hover {
|
|
|
|
|
background-color: #e8e8e8;
|
|
|
|
|
transform: translateY(-1px);
|
|
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.btn-secondary:disabled {
|
|
|
|
|
opacity: 0.6;
|
|
|
|
|
cursor: not-allowed;
|
|
|
|
|
transform: none;
|
|
|
|
|
box-shadow: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 响应式设计 */
|
|
|
|
|
@media (max-width: 375px) {
|
|
|
|
|
.form-content {
|
|
|
|
|
padding: 12px;
|
|
|
|
|
padding-bottom: 70px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.section-title {
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form-label {
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form-input,
|
|
|
|
|
.form-select,
|
|
|
|
|
.form-textarea {
|
|
|
|
|
padding: 8px 10px;
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.btn {
|
|
|
|
|
padding: 10px;
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|