<template> <content-wrap> <section class="view-wrapper" v-loading="loading"> <section class="flex-1"> <section class="mb-40px"> <section class="title-wrapper"> 基本信息</section> <el-form :rules="formRules" :model="formData" ref="formRef" label-width="100px"> <section class="base-form"> <el-form-item label="企业名称" prop="enterprisesName"> <el-input v-model="formData.enterprisesName" placeholder="请输入企业名称" :readonly="isView" /> </el-form-item> <el-form-item label="所属区域" prop="region"> <el-input v-if="isView" :readonly="isView" v-model="formData.region" /> <el-select v-model="formData.region" placeholder="请选择所属区域" clearable v-else> <el-option v-for="dict in getStrDictOptions(DICT_TYPE.ENTERPRISES_AREA)" :key="dict.value" :label="dict.label" :value="dict.value" /> </el-select> </el-form-item> <el-form-item label="企业地址" prop="address"> <el-input v-if="isView" :readonly="isView" v-model="formData.address" /> <el-input v-model="formData.address" placeholder="请选择企业地址" readonly @click="getGaps" v-else > <template #append> <Icon icon="ep:position" @click.stop="getGaps" /> </template> </el-input> </el-form-item> <el-form-item label="行业类别" prop="tagIds"> <el-input v-if="isView" :readonly="isView" v-model="formData.tagIds" /> <el-select v-else v-model="formData.tagIds" placeholder="请选择行业类型" clearable multiple collapse-tags collapse-tags-tooltip > <el-option v-for="dict in typeList" :key="dict.value" :label="dict.label" :value="dict.value" /> </el-select> </el-form-item> <el-form-item label="企业介绍" class="form-textarea" prop="introduction"> <el-input v-model="formData.introduction" placeholder="请输入企业介绍" type="textarea" maxlength="500" show-word-limit resize="none" :readonly="isView" /> </el-form-item> <el-form-item label="环保负责" prop="contactName"> <el-input v-model="formData.contactName" placeholder="请输入环保负责人名称" :readonly="isView" /> </el-form-item> <el-form-item label="联系方式" prop="environmentalContactPhone"> <el-input v-model="formData.environmentalContactPhone" placeholder="请输入环保负责人联系方式" :readonly="isView" /> </el-form-item> <el-form-item label="企业照片" prop="photo" class="form-photo"> <section v-if="isView" class="flex gap-20px"> <el-image v-for="(p, index) in formData.photo" :src="p.url" :key="index" :preview-src-list="formData.photo.map((i) => i.url)" :initial-index="index" fit="contain" class="w-148px h-148px border-solid border-1 border-color-#ccc border-rounded-8px" /> </section> <FileUploader v-else v-model="formData.photo" :limit="6" height="148px" width="148px" ref="fileUploadRef" /> </el-form-item> <section class="form-sub-title"> 执法配置</section> <el-form-item label="执法人员" prop="userId"> <el-input v-if="isView" readonly v-model="formData.inviterName" /> <el-select v-else v-model="formData.userId" placeholder="请选择执法人员" filterable clearable > <el-option v-for="item in userList" :key="item.userId" :label="item.realName" :value="item.userId" popper-class="user-wrapper" > <el-avatar :src="item.avatar" :size="30" /> <span>{{ item.realName }}</span> </el-option> </el-select> </el-form-item> <el-form-item label="签到半径" prop="signRadius"> <el-input-number v-model="formData.signRadius" :min="10" :step="1" placeholder="请输入执法半径" controls-position="right" class="!w-100%" :readonly="isView" > <template #suffix> <span>米</span> </template> </el-input-number> </el-form-item> </section> </el-form> </section> </section> <section> <section class="title-wrapper"> 相关资质 </section> <section class="prove-wrapper"> <section class="prove" v-for="(prove, index) in proveList" :key="index" @click="editProve(prove.id)" > <section class="image-wrapper"> <el-image :src="prove.files[0].url" :preview-src-list="prove.files[0]" :initial-index="0" class="h-100% w-100%" /> <section class="operation"> <section class="item" @click.stop="imagePreview(prove.files[0].url)"> <Icon icon="ep:zoom-in" :size="24" /> 放大 </section> <section class="item" @click.stop="deleteProve({ id: prove.id, index })" v-if="!isView" > <Icon icon="ep:delete" :size="24" /> 删除 </section> </section> </section> <section class="flex flex-col gap-4px items-center"> <span class="font-bold"> {{ getDictLabel(DICT_TYPE.ENTERPRISES_QUA, prove.qualificationName) }} </span> <span class="text-14px">{{ prove.enterpriseAuth }}</span> <span class="text-14px color-#606266" v-if="prove.qualificationName != 99"> {{ formatDate(prove.expiryDate, 'YYYY年M月D日') }}到期 </span> <span v-else>永久</span> </section> </section> <section class="add-prove" @click="addProve" v-if="!isView"> <Icon icon="ep:plus" :size="30" /> </section> </section> </section> </section> <section class="flex items-center justify-center gap-20px" v-if="!isView"> <el-button @click="submit" type="primary">保存信息</el-button> <el-button @click="router.go(-1)">返回列表</el-button> </section> </content-wrap> <content-wrap v-if="isView" title="执法记录"> <section class="flex flex-col gap-20px"> <el-table :data="logList" v-loading="logLoading" :span-method="logSpanMethod" border> <el-table-column label="任务名称" prop="title" /> <el-table-column label="执法人员" prop="inspectNames" /> <el-table-column label="进度状态"> <template #default="{ row }"> <dict-tag :value="row.status" :type="DICT_TYPE.INSPECTIONS_STATUS" /> </template> </el-table-column> <el-table-column label="执法时间" prop="time" :formatter="dateFormatter" /> <el-table-column label="结果反馈" width="100" align="center"> <template #default="{ row }"> <span v-if="row.status === 1">-</span> <el-link type="primary" v-else @click="showInspection(row.inspectionsId)" >详情 </el-link> </template> </el-table-column> </el-table> <el-pagination :total="logTotal" :show-page-size="false" layout="total, prev, pager, next" v-model:current-page="logParams.pageNo" v-model:page-size="logParams.pageSize" @change="getLogList" class="ml-auto" /> </section> </content-wrap> <GpsDialog ref="GpsDialogRef" @success="setGps" /> <ProveForm ref="proveFormRef" @add-prove="setProve" @success="getProveList" /> <InspectionForm ref="inspectionRef" /> </template> <script setup lang="ts"> import { getStrDictOptions, DICT_TYPE, getDictLabel } from '@/utils/dict' import { TagLibraryApi } from '@/api/system/taglibrary' import { getEnterpriseManager } from '@/api/system/user' import GpsDialog from './components/getGpsByAmap.vue' import ProveForm from '@/views/qualification/prove.vue' import { dateFormatter, formatDate } from '@/utils/formatTime' import { EnterprisesApi } from '@/api/enterprises' import { EnterpriseQualificationApi } from '@/api/qualification' import { createImageViewer } from '@/components/ImageViewer' import { EnterpriseInspectionsApi } from '@/api/enterpriseinspections' import InspectionForm from '@/views/enterpriseinspections/EnterpriseInspectionsForm.vue' /** 企业 表单 */ defineOptions({ name: 'UpdateEnterprises' }) //行业类别 const typeList = ref([] as any) const userList = ref([] as any) const message = useMessage() const GpsDialogRef = ref() const router = useRouter() const proveFormRef = ref() const route = useRoute() const loading = ref(false) const formRef = ref() const isView = ref(false) const formData = ref({ id: undefined, departmentId: undefined, userId: undefined, type: undefined, region: undefined, enterprisesName: undefined, address: undefined, contactName: undefined, enterprisesStatus: undefined, environmentalContactPhone: undefined, registrationNumber: undefined, introduction: undefined, establishmentDate: undefined, gpsLocation: undefined, searchQuery: undefined, managerDeptId: undefined, ides: undefined, startUserSelectAssignees: undefined, enterpriseUserId: undefined, tagIds: undefined, photo: [] as any, signRadius: 30 } as any) const formRules = reactive({ type: [{ required: true, message: '企业类型不能为空', trigger: 'change' }], enterprisesName: [{ required: true, message: '企业名称不能为空', trigger: 'blur' }], contactName: [{ required: true, message: '负责人不能为空', trigger: 'blur' }], environmentalContactPhone: [ { required: true, message: '企业环保负责人联系电话不能为空', trigger: 'blur' } ], userId: [ { required: true, message: '请选择执法人员', trigger: 'change' } ], signRadius: [ { required: true, message: '请输入执法半径', trigger: 'change' } ], photo: [ { required: true, validator: (rule, value, callback) => { if (value.length > 0) { callback() } else { callback(new Error('企业照片不能为空')) } }, trigger: 'change' } ], introduction: [ { required: true, message: '请输入企业介绍', trigger: 'change' } ], address: [ { required: true, message: '请输入企业地址', trigger: 'change' } ], tagIds: [ { required: true, message: '请选择行业类别', trigger: 'change' } ], region: [ { required: true, message: '请选择所属区域', trigger: 'change' } ] } as any) const fileUploadRef = ref() const proveList: any = ref([]) const logList = ref([]) const logTotal = ref(0) const logLoading = ref(false) const logSpanArr: any = ref([]) const inspectionRef = ref() const logParams: any = reactive({ pageSize: 5, pageNo: 1, enterpriseId: undefined }) /** 查询搜索项列表 */ const getSelectOption = async () => { userList.value = await getEnterpriseManager() const res = await TagLibraryApi.tagLibraryList('hy') typeList.value = res[0].children.map((t) => { return { label: t.tagName, value: t.id } }) } const setGps = (gps: any) => { formData.value.gpsLocation = [gps.location.lat, gps.location.lng] formData.value.address = `${gps.district}${gps.address}` } const getGaps = () => { if (formData.value.gpsLocation) { unref(GpsDialogRef).open({ name: formData.value.enterprisesName, address: formData.value.address, location: { lat: formData.value.gpsLocation[0], lng: formData.value.gpsLocation[1] } }) } else { unref(GpsDialogRef).open() } } const addProve = () => { unref(proveFormRef).open({ enterpriseId: formData.value.id }) } const submit = async () => { const validate = await unref(formRef).validate() if (!validate) return loading.value = true await unref(fileUploadRef).handlerUpload() if (formData.value.id) { const data = { ...formData.value, fileIds: formData.value.photo.map((i) => i.id), gpsLocation: formData.value.gpsLocation.join(',') } EnterprisesApi.updateEnterprises(data).then(() => { message.success('保存成功') loading.value = false getDetail() }) } else { const data = { ...formData.value, fileIds: formData.value.photo.map((i) => i.id), gpsLocation: formData.value.gpsLocation.join(','), qualis: proveList.value.map((p) => { return { ...p, files: p.files.map((f) => f.id) } }) } EnterprisesApi.createEnterprises(data).then((res) => { formData.value.id = res message.success('保存成功') loading.value = false }) } } const setProve = (prove) => { proveList.value.push(prove) } const editProve = (id) => { if (isView) return unref(proveFormRef).open({ id }) } const getDetail = () => { EnterprisesApi.enterpriseDetail(formData.value.id).then((res) => { formData.value = res formData.value.photo = formData.value.files formData.value.gpsLocation = formData.value.gpsLocation.split(',') formData.value.tagIds = res.tagObjList.map((i) => i.id) if (isView) { formData.value.region = getDictLabel(DICT_TYPE.ENTERPRISES_AREA, formData.value.region) formData.value.tagIds = res.tagObjList.map((i) => i.tagName).join(',') } }) } const getProveList = () => { EnterpriseQualificationApi.getEnterpriseQualificationPage({ pageSize: -1, enterpriseId: formData.value.id }).then((res) => { proveList.value = res.list.map((i) => { return { ...i, files: i.qualificationFiles } }) }) } const deleteProve = (params) => { if (params.id) { EnterpriseQualificationApi.deleteEnterpriseQualification(params.id).then(() => { message.success('删除成功') getProveList() }) } else { proveList.value.splice(params.index, 1) message.success('删除成功') } } const getLogList = () => { logLoading.value = true EnterpriseInspectionsApi.getListByEnterpriseId(logParams).then((res) => { logLoading.value = false logTotal.value = res.total logList.value = res.list getSpanArr(logList.value) }) } // 查看图片 const imagePreview = (imgUrl: string) => { createImageViewer({ zIndex: 9999999, urlList: [imgUrl] }) } const logSpanMethod = ({ row, column, rowIndex, columnIndex }) => { if (columnIndex == 0) { const _row = logSpanArr.value[rowIndex] const _col = _row > 0 ? 1 : 0 return { rowspan: _row, colspan: _col } } } const showInspection = (id) => { unref(inspectionRef).open({ id }) } const getSpanArr = (data) => { logSpanArr.value = [] let pos = 0 for (var i = 0; i < data.length; i++) { if (i === 0) { logSpanArr.value.push(1) pos = 0 } else { // 判断当前元素与上一个元素是否相同 inAccessCode(批次字段) if (data[i].taskId === data[i - 1].taskId) { logSpanArr.value[pos] += 1 logSpanArr.value.push(0) } else { logSpanArr.value.push(1) pos = i } } } } getSelectOption() onMounted(() => { if (route.query.id) { formData.value.id = route.query.id getDetail() getProveList() } if (route.query.view) { isView.value = true logParams.enterpriseId = route.query.id getLogList() } }) </script> <style lang="scss" scoped> .view-wrapper { display: flex; flex-flow: row nowrap; gap: 40px; .title-wrapper { font-size: 16px; line-height: 140%; font-weight: 700; margin-bottom: 40px; } .form-photo { grid-column: span 2; } .base-form { display: grid; grid-template-columns: repeat(2, 1fr); gap: 40px; .el-form-item--large { margin-bottom: 0; } .form-textarea { grid-row: span 2; ::v-deep(.el-textarea) { height: 100%; .el-textarea__inner { height: 100%; white-space: pre-wrap; &::-webkit-scrollbar { width: 4px; } &::-webkit-scrollbar-thumb { background-color: #ccc; border-radius: 10px; } &::-webkit-scrollbar-track { background-color: transparent; } &::-webkit-scrollbar-button { display: none; height: 2px; } } } } .form-sub-title { font-size: 16px; line-height: 140%; font-weight: 700; grid-column: span 2; } :deep( .el-input-number.is-controls-right[class*='large'] [class*='decrease'], .el-input-number.is-controls-right[class*='large'] [class*='increase'] ) { --el-input-number-controls-height: 50%; } :deep(.el-input__suffix-inner > :first-child) { margin-right: 8px; } :deep(.el-input-number .el-input__inner) { text-align: left; } } .prove-wrapper { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; .prove { width: 200px; height: 238px; border: 1px solid #ccc; border-radius: 8px; overflow: hidden; padding: 12px; .image-wrapper { position: relative; height: 130px; margin-bottom: 12px; border-radius: 6px; overflow: hidden; &:hover { .operation { opacity: 1; } } .operation { cursor: pointer; opacity: 0; position: absolute; inset: 0; background-color: rgba(0, 0, 0, 0.7); display: flex; justify-content: center; align-items: center; gap: 20px; color: #fff; font-size: 14px; transition: var(--el-transition-time); .item { display: flex; flex-flow: column nowrap; align-items: center; gap: 8px; &:hover { color: var(--el-color-primary); } } } } } .add-prove { width: 200px; height: 238px; border: 1px dashed #ccc; border-radius: 8px; display: flex; justify-content: center; align-items: center; color: #ccc; transition: all 0.2s; &:hover { color: var(--el-color-primary); border-color: var(--el-color-primary); cursor: pointer; } } } } </style>