You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
417 lines
11 KiB
417 lines
11 KiB
<template>
|
|
<div class="legal-tech-edit-container" v-loading="loading">
|
|
<div class="page-header">
|
|
<h2>{{ isEdit ? '编辑法制与技术材料' : '新增法制与技术材料' }}</h2>
|
|
</div>
|
|
|
|
<el-form ref="formRef" :model="form" :rules="rules" label-width="120px" class="form-container">
|
|
<el-form-item label="执法单位:" prop="lawEnforcementAgencyId">
|
|
<el-select
|
|
v-model="form.lawEnforcementAgencyId"
|
|
filterable
|
|
placeholder="请选择执法单位"
|
|
class="form-input"
|
|
@change="handleDeptChange"
|
|
>
|
|
<el-option
|
|
v-for="item in deptOptions"
|
|
:key="item.deptId"
|
|
:label="item.deptName"
|
|
:value="String(item.deptId)"
|
|
/>
|
|
</el-select>
|
|
<div class="form-tip">温馨提示:开展非现场执法,同1个单位,仅需提交1次法制和技术材料</div>
|
|
</el-form-item>
|
|
|
|
<div class="section-title">法制材料</div>
|
|
<el-form-item label="附件:" prop="legalMaterials">
|
|
<div class="upload-area">
|
|
<el-upload
|
|
drag
|
|
:http-request="(opts) => handleFileUpload(opts, 'legal')"
|
|
:show-file-list="true"
|
|
:file-list="legalFileList"
|
|
:on-remove="(file) => handleFileRemove(file, 'legal')"
|
|
:before-upload="beforeUpload"
|
|
accept=".pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx"
|
|
:limit="1"
|
|
:on-exceed="handleExceed"
|
|
>
|
|
<div class="upload-box">
|
|
<el-icon class="upload-icon"><FolderOpened /></el-icon>
|
|
<p>点击或将文件拖拽到这里上传</p>
|
|
<p class="upload-tip">文件格式:word、excel、ppt、PDF等文档,大小不超过200M</p>
|
|
</div>
|
|
</el-upload>
|
|
</div>
|
|
</el-form-item>
|
|
|
|
<div class="section-title">技术材料</div>
|
|
<el-form-item label="附件:" prop="technicalMaterials">
|
|
<div class="upload-area">
|
|
<el-upload
|
|
drag
|
|
:http-request="(opts) => handleFileUpload(opts, 'technical')"
|
|
:show-file-list="true"
|
|
:file-list="technicalFileList"
|
|
:on-remove="(file) => handleFileRemove(file, 'technical')"
|
|
:before-upload="beforeUpload"
|
|
accept=".pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx"
|
|
:limit="1"
|
|
:on-exceed="handleExceed"
|
|
>
|
|
<div class="upload-box">
|
|
<el-icon class="upload-icon"><FolderOpened /></el-icon>
|
|
<p>点击或将文件拖拽到这里上传</p>
|
|
<p class="upload-tip">文件格式:word、excel、ppt、PDF等文档,大小不超过200M</p>
|
|
</div>
|
|
</el-upload>
|
|
</div>
|
|
</el-form-item>
|
|
|
|
<el-form-item class="form-actions">
|
|
<el-button @click="handleCancel">取消</el-button>
|
|
<el-button type="primary" @click="handleSubmit" :loading="submitLoading">提交</el-button>
|
|
</el-form-item>
|
|
</el-form>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, reactive, onMounted, computed } from 'vue';
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
import { ElMessage, ElForm, FormRules } from 'element-plus';
|
|
import type { UploadFile, UploadRequestOptions, UploadUserFile } from 'element-plus';
|
|
import { FolderOpened } from '@element-plus/icons-vue';
|
|
import { getLegalTechRecordsDetail, saveOrEditLegalTechRecords, selectLawEnforcementAgency } from '@/api/nos/index';
|
|
import type { SaveOrEditLegalTechRecordsRequest, LawEnforcementAgencyOption } from '@/api/nos/type';
|
|
import request from '@/utils/request';
|
|
|
|
const route = useRoute();
|
|
const router = useRouter();
|
|
const formRef = ref<InstanceType<typeof ElForm>>();
|
|
|
|
const loading = ref(false);
|
|
const submitLoading = ref(false);
|
|
|
|
const recordId = computed(() => {
|
|
const id = route.params.id;
|
|
return Array.isArray(id) ? id[0] : id;
|
|
});
|
|
const isEdit = computed(() => !!recordId.value);
|
|
|
|
const form = reactive({
|
|
lawEnforcementAgency: '',
|
|
lawEnforcementAgencyId: '',
|
|
legalMaterials: '',
|
|
technicalMaterials: ''
|
|
});
|
|
|
|
const deptOptions = ref<LawEnforcementAgencyOption[]>([]);
|
|
|
|
const legalFileList = ref<UploadUserFile[]>([]);
|
|
const technicalFileList = ref<UploadUserFile[]>([]);
|
|
|
|
const rules: FormRules = {
|
|
lawEnforcementAgencyId: [{ required: true, message: '请选择执法单位', trigger: 'change' }],
|
|
legalMaterials: [{ required: true, message: '请上传法制材料附件', trigger: 'change' }],
|
|
technicalMaterials: [{ required: true, message: '请上传技术材料附件', trigger: 'change' }]
|
|
};
|
|
|
|
const handleDeptChange = (deptId: string) => {
|
|
const selected = deptOptions.value.find((item) => String(item.deptId) === String(deptId));
|
|
form.lawEnforcementAgency = selected?.deptName || '';
|
|
};
|
|
|
|
const loadDeptOptions = async () => {
|
|
try {
|
|
const res: any = await selectLawEnforcementAgency();
|
|
deptOptions.value = res.data || [];
|
|
} catch (error) {
|
|
console.error('加载执法单位失败:', error);
|
|
ElMessage.error('加载执法单位失败');
|
|
}
|
|
};
|
|
|
|
const MAX_FILE_SIZE = 200 * 1024 * 1024;
|
|
const ALLOWED_FILE_EXT_RE = /\.(pdf|doc|docx|xls|xlsx|ppt|pptx)$/i;
|
|
|
|
const beforeUpload = (file: File) => {
|
|
if (!ALLOWED_FILE_EXT_RE.test(file.name)) {
|
|
ElMessage.warning('仅支持上传 word、excel、ppt、PDF 格式文件');
|
|
return false;
|
|
}
|
|
if (file.size > MAX_FILE_SIZE) {
|
|
ElMessage.warning('文件大小不能超过 200M');
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
|
|
const handleExceed = () => {
|
|
ElMessage.warning('只能上传一个文件,请先删除已上传的文件');
|
|
};
|
|
|
|
const handleFileUpload = async (options: UploadRequestOptions, type: 'legal' | 'technical') => {
|
|
const formData = new FormData();
|
|
formData.append('file', options.file);
|
|
|
|
try {
|
|
const res: any = await request({
|
|
//baseURL: enfBaseURL,
|
|
url: '/app-enf/common/file/upload',
|
|
method: 'post',
|
|
data: formData,
|
|
headers: { 'Content-Type': 'multipart/form-data' }
|
|
});
|
|
|
|
if (res.code !== 200 || !res.data) {
|
|
throw new Error(res.msg || '上传失败');
|
|
}
|
|
|
|
const fileUrl = res.data;
|
|
const fileObj = {
|
|
name: options.file.name,
|
|
url: fileUrl,
|
|
uid: options.file.uid
|
|
};
|
|
|
|
if (type === 'legal') {
|
|
form.legalMaterials = fileUrl;
|
|
legalFileList.value = [fileObj];
|
|
formRef.value?.validateField('legalMaterials');
|
|
} else {
|
|
form.technicalMaterials = fileUrl;
|
|
technicalFileList.value = [fileObj];
|
|
formRef.value?.validateField('technicalMaterials');
|
|
}
|
|
|
|
options.onSuccess?.(res);
|
|
ElMessage.success('上传成功');
|
|
} catch (error) {
|
|
console.error('附件上传失败:', error);
|
|
ElMessage.error('附件上传失败,请重试');
|
|
options.onError?.(error as any);
|
|
}
|
|
};
|
|
|
|
const handleFileRemove = (file: UploadFile, type: 'legal' | 'technical') => {
|
|
if (type === 'legal') {
|
|
form.legalMaterials = '';
|
|
legalFileList.value = [];
|
|
formRef.value?.validateField('legalMaterials');
|
|
} else {
|
|
form.technicalMaterials = '';
|
|
technicalFileList.value = [];
|
|
formRef.value?.validateField('technicalMaterials');
|
|
}
|
|
};
|
|
|
|
const fetchDetail = async () => {
|
|
if (!isEdit.value) return;
|
|
|
|
loading.value = true;
|
|
try {
|
|
const res: any = await getLegalTechRecordsDetail(recordId.value);
|
|
const data = res.data;
|
|
if (data) {
|
|
form.lawEnforcementAgency = data.lawEnforcementAgency || '';
|
|
form.lawEnforcementAgencyId = data.lawEnforcementAgencyId ? String(data.lawEnforcementAgencyId) : '';
|
|
form.legalMaterials = data.legalMaterials || '';
|
|
form.technicalMaterials = data.technicalMaterials || '';
|
|
|
|
if (form.legalMaterials) {
|
|
legalFileList.value = [{
|
|
name: extractFileName(form.legalMaterials),
|
|
url: form.legalMaterials,
|
|
uid: Date.now()
|
|
}];
|
|
}
|
|
|
|
if (form.technicalMaterials) {
|
|
technicalFileList.value = [{
|
|
name: extractFileName(form.technicalMaterials),
|
|
url: form.technicalMaterials,
|
|
uid: Date.now() + 1
|
|
}];
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('获取详情失败:', error);
|
|
ElMessage.error('获取详情失败');
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
};
|
|
|
|
const extractFileName = (val: string) => {
|
|
if (!val) return '';
|
|
const raw = val.trim();
|
|
const isOssId = /^[0-9]+$/.test(raw);
|
|
if (isOssId) return raw;
|
|
try {
|
|
const withoutQuery = raw.split('?')[0].split('#')[0];
|
|
const parts = withoutQuery.split('/');
|
|
return parts[parts.length - 1] || raw;
|
|
} catch {
|
|
return raw;
|
|
}
|
|
};
|
|
|
|
const handleCancel = () => {
|
|
router.back();
|
|
};
|
|
|
|
const handleSubmit = async () => {
|
|
if (!formRef.value) return;
|
|
|
|
const isValid = await formRef.value.validate().catch(() => false);
|
|
if (!isValid) return;
|
|
|
|
submitLoading.value = true;
|
|
try {
|
|
const payload: SaveOrEditLegalTechRecordsRequest = {
|
|
lawEnforcementAgency: form.lawEnforcementAgency,
|
|
lawEnforcementAgencyId: form.lawEnforcementAgencyId,
|
|
legalMaterials: form.legalMaterials,
|
|
technicalMaterials: form.technicalMaterials
|
|
};
|
|
|
|
if (isEdit.value) {
|
|
payload.id = recordId.value;
|
|
}
|
|
|
|
const res: any = await saveOrEditLegalTechRecords(payload);
|
|
if (res.code === 200) {
|
|
ElMessage.success(isEdit.value ? '编辑成功' : '新增成功');
|
|
router.back();
|
|
} else {
|
|
ElMessage.error(res.msg || '操作失败');
|
|
}
|
|
} catch (error) {
|
|
console.error('提交失败:', error);
|
|
ElMessage.error('操作失败,请重试');
|
|
} finally {
|
|
submitLoading.value = false;
|
|
}
|
|
};
|
|
|
|
onMounted(async () => {
|
|
await loadDeptOptions();
|
|
fetchDetail();
|
|
});
|
|
</script>
|
|
|
|
<style scoped>
|
|
.legal-tech-edit-container {
|
|
padding: 20px;
|
|
background: #f5f7fa;
|
|
min-height: calc(100vh - 100px);
|
|
}
|
|
|
|
.page-header {
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.page-header h2 {
|
|
font-size: 20px;
|
|
font-weight: bold;
|
|
color: #303133;
|
|
margin: 0;
|
|
}
|
|
|
|
.form-container {
|
|
background: #fff;
|
|
border-radius: 8px;
|
|
padding: 32px 24px;
|
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
.form-input {
|
|
width: 100%;
|
|
max-width: 600px;
|
|
}
|
|
|
|
.form-tip {
|
|
font-size: 12px;
|
|
color: #909399;
|
|
margin-top: 8px;
|
|
line-height: 1.4;
|
|
}
|
|
|
|
.section-title {
|
|
font-size: 16px;
|
|
font-weight: bold;
|
|
color: #303133;
|
|
margin: 24px 0 16px;
|
|
padding-left: 12px;
|
|
position: relative;
|
|
}
|
|
|
|
.section-title::before {
|
|
content: '';
|
|
position: absolute;
|
|
left: 0;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
width: 4px;
|
|
height: 16px;
|
|
background-color: #409eff;
|
|
border-radius: 2px;
|
|
}
|
|
|
|
.upload-area {
|
|
width: 100%;
|
|
max-width: 400px;
|
|
}
|
|
|
|
:deep(.el-upload-dragger) {
|
|
padding: 0;
|
|
border: none;
|
|
background: transparent;
|
|
}
|
|
|
|
.upload-box {
|
|
border: 1px dashed #d9d9d9;
|
|
border-radius: 4px;
|
|
padding: 30px 20px;
|
|
text-align: center;
|
|
transition: all 0.3s;
|
|
background: #fafafa;
|
|
}
|
|
|
|
.upload-box:hover {
|
|
border-color: #409eff;
|
|
background: #f0f5ff;
|
|
}
|
|
|
|
.upload-icon {
|
|
font-size: 40px;
|
|
color: #409eff;
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.upload-box p {
|
|
color: #606266;
|
|
margin: 8px 0;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.upload-tip {
|
|
font-size: 12px !important;
|
|
color: #909399 !important;
|
|
}
|
|
|
|
.form-actions {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
gap: 12px;
|
|
padding-top: 32px;
|
|
margin-top: 16px;
|
|
border-top: 1px solid #ebeef5;
|
|
}
|
|
|
|
:deep(.el-form-item__label) {
|
|
font-weight: bold;
|
|
}
|
|
</style>
|
|
|