Browse Source

添加企业执法记录查询功能,优化文件上传组件,调整样式和逻辑

master
parent
commit
4edd55cc73
  1. 19
      src/api/enterpriseinspections/index.ts
  2. 20
      src/components/UploadFile/src/FileUploader.vue
  3. 11
      src/views/enterpriseinspections/EnterpriseInspectionsForm.vue
  4. 13
      src/views/enterpriseinspections/detail.vue
  5. 74
      src/views/enterprises/index.vue
  6. 216
      src/views/enterprises/update.vue

19
src/api/enterpriseinspections/index.ts

@ -55,5 +55,22 @@ export const EnterpriseInspectionsApi = {
// 变更人员ID // 变更人员ID
passOn: async (data: any) => { passOn: async (data: any) => {
return await request.post({ url: `/system/enterprise-inspections/passOn`, data }) return await request.post({ url: `/system/enterprise-inspections/passOn`, data })
} },
/**
*
*/
getListByEnterpriseId: async (params: any) => {
return await request.get({
url: `/system/enterprise-inspections/inspectionsByEnterpriseId`,
params
})
},
/**
*
*/
getLogDetail:async (id: any) => {
return await request.get({
url: `/system/inspections-log/get?id=${id}`,
})
},
} }

20
src/components/UploadFile/src/FileUploader.vue

@ -27,11 +27,11 @@
<img :src="file.url" class="upload-image" /> <img :src="file.url" class="upload-image" />
<div class="upload-handle" @click.stop> <div class="upload-handle" @click.stop>
<div class="handle-icon" @click="imagePreview(file.url!)"> <div class="handle-icon" @click="imagePreview(file.url!)">
<Icon icon="ep:zoom-in" :size="30" /> <Icon icon="ep:zoom-in" :size="24" />
<span>查看</span> <span>放大</span>
</div> </div>
<div class="handle-icon" @click="handleRemove(file)"> <div class="handle-icon" @click="handleRemove(file)">
<Icon icon="ep:delete" :size="30" /> <Icon icon="ep:delete" :size="24" />
<span>删除</span> <span>删除</span>
</div> </div>
</div> </div>
@ -82,7 +82,8 @@ const props = defineProps({
fileType: propTypes.array.def(['image/jpeg', 'image/png', 'image/gif']), // ==> ["image/jpeg", "image/png", "image/gif"] fileType: propTypes.array.def(['image/jpeg', 'image/png', 'image/gif']), // ==> ["image/jpeg", "image/png", "image/gif"]
height: propTypes.string.def('150px'), // ==> 150px height: propTypes.string.def('150px'), // ==> 150px
width: propTypes.string.def('150px'), // ==> 150px width: propTypes.string.def('150px'), // ==> 150px
borderRadius: propTypes.string.def('8px') // ==> 8px borderRadius: propTypes.string.def('8px'), // ==> 8px
disable: propTypes.bool.def(false)
}) })
const showPlus = ref(false) const showPlus = ref(false)
const { uploadUrl, httpRequest } = useUpload() const { uploadUrl, httpRequest } = useUpload()
@ -138,6 +139,16 @@ watch(
{ immediate: true, deep: true } { immediate: true, deep: true }
) )
watch(
() => props.disable,
(val) => {
if (val) {
showPlus.value = true
}
},
{ immediate: true, deep: true }
)
const emitUpdateModelValue = (fileList: any) => { const emitUpdateModelValue = (fileList: any) => {
emit('update:modelValue', fileList) emit('update:modelValue', fileList)
} }
@ -284,6 +295,7 @@ defineExpose({
align-items: center; align-items: center;
justify-content: center; justify-content: center;
color: aliceblue; color: aliceblue;
font-size: 14px;
&:hover { &:hover {
color: var(--el-color-primary); color: var(--el-color-primary);
transition: var(--el-transition-duration-fast); transition: var(--el-transition-duration-fast);

11
src/views/enterpriseinspections/EnterpriseInspectionsForm.vue

@ -22,16 +22,21 @@
</Dialog> </Dialog>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import {EnterpriseInspectionsApi} from '@/api/enterpriseinspections'
/** 企业检查记录表,用于记录与企业相关的环保检查信息。 表单 */ /** 企业检查记录表,用于记录与企业相关的环保检查信息。 表单 */
defineOptions({ name: 'EnterpriseInspectionsForm' }) defineOptions({ name: 'EnterpriseInspectionsForm' })
const dialogVisible = ref(false) // const dialogVisible = ref(false) //
const detail = ref() const detail = ref({
id: undefined
})
/** 打开弹窗 */ /** 打开弹窗 */
const open = async (param: any) => { const open = async (params: any) => {
detail.value = param EnterpriseInspectionsApi.getLogDetail(params.id).then(res=>{
detail.value = res
})
dialogVisible.value = true dialogVisible.value = true
} }

13
src/views/enterpriseinspections/detail.vue

@ -37,7 +37,7 @@
@click=" @click="
push({ push({
path: `/enterprises/update`, path: `/enterprises/update`,
query: { id: detailData.enterpriseId } query: { id: detailData.enterpriseId, view: true }
}) })
" "
>详情 >详情
@ -77,7 +77,12 @@
<el-table-column label="执法时间" prop="createTime" :formatter="dateFormatter" /> <el-table-column label="执法时间" prop="createTime" :formatter="dateFormatter" />
<el-table-column label="结果反馈" align="center" width="100px"> <el-table-column label="结果反馈" align="center" width="100px">
<template #default="scope"> <template #default="scope">
<el-button link v-if="scope.row.status > 1" type="primary" @click="viewDetail(scope.row)"> <el-button
link
v-if="scope.row.status > 1"
type="primary"
@click="viewDetail(scope.row.id)"
>
详情 详情
</el-button> </el-button>
<span v-if="scope.row.status === 1">-</span> <span v-if="scope.row.status === 1">-</span>
@ -141,8 +146,8 @@ const getDetail = async () => {
) )
} }
const viewDetail = async (row) => { const viewDetail = async (id) => {
unref(detailRef).open(row) unref(detailRef).open({ id })
} }
const getList = async () => { const getList = async () => {

74
src/views/enterprises/index.vue

@ -47,17 +47,22 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="" prop="registrationNumber"> <el-form-item label="" prop="registrationNumber">
<el-select v-model="queryParams.registrationNumber" placeholder="请选择执法人员" filterable clearable> <el-select
<el-option v-model="queryParams.registrationNumber"
v-for="item in userList" placeholder="请选择执法人员"
:key="item.id" filterable
:label="item.realName" clearable
:value="item.id" >
popper-class="user-wrapper" <el-option
> v-for="item in userList"
<el-avatar :src="item.avatar" :size="30" /> <span>{{ item.realName }}</span> :key="item.id"
</el-option> :label="item.realName"
</el-select> :value="item.id"
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>
<el-form-item label="" prop="establishmentDate"> <el-form-item label="" prop="establishmentDate">
<el-date-picker <el-date-picker
@ -70,7 +75,6 @@
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
/> />
</el-form-item> </el-form-item>
<el-form-item class="btnClass"> <el-form-item class="btnClass">
<el-button @click="handleQuery" type="primary" plain> <el-button @click="handleQuery" type="primary" plain>
<Icon icon="ep:search" class="mr-5px" /> 查询 <Icon icon="ep:search" class="mr-5px" /> 查询
@ -112,7 +116,9 @@
</el-table-column> </el-table-column>
<el-table-column label="行业类别" width="300"> <el-table-column label="行业类别" width="300">
<template #default="scope"> <template #default="scope">
{{ getDictLabel(DICT_TYPE.ENTERPRISES_TYPE, scope.row.type) }} <span v-if="scope.row.tagListName">
{{ scope.row.tagListName.map((i) => i.label).join('、') }}
</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="执法人员" width="200"> <el-table-column label="执法人员" width="200">
@ -128,10 +134,10 @@
/> />
<el-table-column label="操作选项" align="center" width="120px"> <el-table-column label="操作选项" align="center" width="120px">
<template #default="scope"> <template #default="scope">
<el-button <el-button
link link
type="primary" type="primary"
@click=" @click="
push({ push({
path: 'update', path: 'update',
query: { query: {
@ -139,18 +145,19 @@
} }
}) })
" "
v-hasPermi="['system:enterprise:update']" v-hasPermi="['system:enterprise:update']"
> >
编辑 编辑
</el-button> </el-button>
<el-button <el-button
link link
type="primary" type="primary"
@click=" @click="
push({ push({
path: 'detail', path: 'update',
query: { query: {
id: scope.row.id id: scope.row.id,
view: true
} }
}) })
" "
@ -258,25 +265,20 @@ const handleExport = async () => {
} }
} }
/** 查询搜索项列表 */ /** 查询搜索项列表 */
const getSearchOption = async () => { const getSearchOption = async () => {
userList.value = await getSimpleUserZGList({}) userList.value = await getSimpleUserZGList({})
const res = await TagLibraryApi.tagLibraryList('hy') const res = await TagLibraryApi.tagLibraryList('hy')
typeList.value = res[0].children.map((t) => { typeList.value = res[0].children.map((t) => {
return { return {
label: t.tagName, label: t.tagName,
value: t.id value: t.id
} }
}) })
} }
getSearchOption() getSearchOption()
/** 初始化 **/ /** 初始化 **/
onMounted(() => { onMounted(() => {
getList() getList()

216
src/views/enterprises/update.vue

@ -7,10 +7,15 @@
<el-form :rules="formRules" :model="formData" ref="formRef" label-width="100px"> <el-form :rules="formRules" :model="formData" ref="formRef" label-width="100px">
<section class="base-form"> <section class="base-form">
<el-form-item label="企业名称" prop="enterprisesName"> <el-form-item label="企业名称" prop="enterprisesName">
<el-input v-model="formData.enterprisesName" placeholder="请输入企业名称" /> <el-input
v-model="formData.enterprisesName"
placeholder="请输入企业名称"
:readonly="isView"
/>
</el-form-item> </el-form-item>
<el-form-item label="所属区域" prop="region"> <el-form-item label="所属区域" prop="region">
<el-select v-model="formData.region" placeholder="请选择所属区域" clearable> <el-input v-if="isView" :readonly="isView" v-model="formData.region" />
<el-select v-model="formData.region" placeholder="请选择所属区域" clearable v-else>
<el-option <el-option
v-for="dict in getStrDictOptions(DICT_TYPE.ENTERPRISES_AREA)" v-for="dict in getStrDictOptions(DICT_TYPE.ENTERPRISES_AREA)"
:key="dict.value" :key="dict.value"
@ -20,11 +25,13 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="企业地址" prop="address"> <el-form-item label="企业地址" prop="address">
<el-input v-if="isView" :readonly="isView" v-model="formData.address" />
<el-input <el-input
v-model="formData.address" v-model="formData.address"
placeholder="请选择企业地址" placeholder="请选择企业地址"
readonly readonly
@click="getGaps" @click="getGaps"
v-else
> >
<template #append> <template #append>
<Icon icon="ep:position" @click.stop="getGaps" /> <Icon icon="ep:position" @click.stop="getGaps" />
@ -32,7 +39,9 @@
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item label="行业类别" prop="tagIds"> <el-form-item label="行业类别" prop="tagIds">
<el-input v-if="isView" :readonly="isView" v-model="formData.tagIds" />
<el-select <el-select
v-else
v-model="formData.tagIds" v-model="formData.tagIds"
placeholder="请选择行业类型" placeholder="请选择行业类型"
clearable clearable
@ -56,19 +65,37 @@
maxlength="500" maxlength="500"
show-word-limit show-word-limit
resize="none" resize="none"
:readonly="isView"
/> />
</el-form-item> </el-form-item>
<el-form-item label="环保负责人" prop="contactName"> <el-form-item label="环保负责人" prop="contactName">
<el-input v-model="formData.contactName" placeholder="请输入负责人名称" /> <el-input
v-model="formData.contactName"
placeholder="请输入负责人名称"
:readonly="isView"
/>
</el-form-item> </el-form-item>
<el-form-item label="联系方式" prop="environmentalContactPhone"> <el-form-item label="联系方式" prop="environmentalContactPhone">
<el-input <el-input
v-model="formData.environmentalContactPhone" v-model="formData.environmentalContactPhone"
placeholder="请输入负责人联系方式" placeholder="请输入负责人联系方式"
:readonly="isView"
/> />
</el-form-item> </el-form-item>
<el-form-item label="企业照片" prop="photo" class="form-photo"> <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 <FileUploader
v-else
v-model="formData.photo" v-model="formData.photo"
:limit="6" :limit="6"
height="148px" height="148px"
@ -78,7 +105,9 @@
</el-form-item> </el-form-item>
<section class="form-sub-title"> 执法配置</section> <section class="form-sub-title"> 执法配置</section>
<el-form-item label="执法人员" prop="userId"> <el-form-item label="执法人员" prop="userId">
<el-input v-if="isView" readonly v-model="formData.inviterName" />
<el-select <el-select
v-else
v-model="formData.userId" v-model="formData.userId"
placeholder="请选择执法人员" placeholder="请选择执法人员"
filterable filterable
@ -103,6 +132,7 @@
placeholder="请输入执法半径" placeholder="请输入执法半径"
controls-position="right" controls-position="right"
class="!w-100%" class="!w-100%"
:readonly="isView"
> >
<template #suffix> <template #suffix>
<span></span> <span></span>
@ -122,12 +152,24 @@
:key="index" :key="index"
@click="editProve(prove.id)" @click="editProve(prove.id)"
> >
<el-image <section class="image-wrapper">
:src="prove.files[0].url" <el-image
:preview-src-list="prove.files[0]" :src="prove.files[0].url"
:initial-index="0" :preview-src-list="prove.files[0]"
class="border-rounded-6px h-130px mb-12px" :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(prove.id)" v-if="!isView">
<Icon icon="ep:delete" :size="24" />
删除
</section>
</section>
</section>
<section class="flex flex-col gap-4px items-center"> <section class="flex flex-col gap-4px items-center">
<span class="font-bold"> <span class="font-bold">
{{ getDictLabel(DICT_TYPE.ENTERPRISES_QUA, prove.qualificationName) }} {{ getDictLabel(DICT_TYPE.ENTERPRISES_QUA, prove.qualificationName) }}
@ -139,19 +181,50 @@
<span v-else>永久</span> <span v-else>永久</span>
</section> </section>
</section> </section>
<section class="add-prove" @click="addProve"> <section class="add-prove" @click="addProve" v-if="!isView">
<Icon icon="ep:plus" :size="30" /> <Icon icon="ep:plus" :size="30" />
</section> </section>
</section> </section>
</section> </section>
</section> </section>
<section class="flex items-center justify-center gap-20px"> <section class="flex items-center justify-center gap-20px" v-if="!isView">
<el-button @click="submit" type="primary">保存信息</el-button> <el-button @click="submit" type="primary">保存信息</el-button>
<el-button @click="router.go(-1)">返回列表</el-button> <el-button @click="router.go(-1)">返回列表</el-button>
</section> </section>
</content-wrap> </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" /> <GpsDialog ref="GpsDialogRef" @success="setGps" />
<ProveForm ref="proveFormRef" @add-prove="setProve" @success="getProveList" /> <ProveForm ref="proveFormRef" @add-prove="setProve" @success="getProveList" />
<InspectionForm ref="inspectionRef" />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -160,10 +233,12 @@ import { TagLibraryApi } from '@/api/system/taglibrary'
import { getEnterpriseManager } from '@/api/system/user' import { getEnterpriseManager } from '@/api/system/user'
import GpsDialog from './components/getGpsByAmap.vue' import GpsDialog from './components/getGpsByAmap.vue'
import ProveForm from '@/views/qualification/prove.vue' import ProveForm from '@/views/qualification/prove.vue'
import { formatDate } from '@/utils/formatTime' import { dateFormatter, formatDate } from '@/utils/formatTime'
import { EnterprisesApi } from '@/api/enterprises' import { EnterprisesApi } from '@/api/enterprises'
import { EnterpriseQualificationApi } from '@/api/qualification' 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' }) defineOptions({ name: 'UpdateEnterprises' })
// //
@ -176,6 +251,7 @@ const proveFormRef = ref()
const route = useRoute() const route = useRoute()
const loading = ref(false) const loading = ref(false)
const formRef = ref() const formRef = ref()
const isView = ref(false)
const formData = ref({ const formData = ref({
id: undefined, id: undefined,
departmentId: undefined, departmentId: undefined,
@ -265,6 +341,16 @@ const formRules = reactive({
} as any) } as any)
const fileUploadRef = ref() const fileUploadRef = ref()
const proveList: any = 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 () => { const getSelectOption = async () => {
userList.value = await getEnterpriseManager() userList.value = await getEnterpriseManager()
@ -342,6 +428,7 @@ const setProve = (prove) => {
} }
const editProve = (id) => { const editProve = (id) => {
if (isView) return
unref(proveFormRef).open({ id }) unref(proveFormRef).open({ id })
} }
@ -351,6 +438,10 @@ const getDetail = () => {
formData.value.photo = formData.value.files formData.value.photo = formData.value.files
formData.value.gpsLocation = formData.value.gpsLocation.split(',') formData.value.gpsLocation = formData.value.gpsLocation.split(',')
formData.value.tagIds = res.tagObjList.map((i) => i.id) 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(',')
}
}) })
} }
@ -368,13 +459,77 @@ const getProveList = () => {
}) })
} }
const deleteProve = (id: any) => {
EnterpriseQualificationApi.deleteEnterpriseQualification(id).then(() => {
message.success('删除成功')
getProveList()
})
}
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() getSelectOption()
onMounted(() => { onMounted(() => {
if (route.query.id) { if (route.query.id) {
formData.value.id = route.query.id formData.value.id = route.query.id
getDetail() getDetail()
getProveList() getProveList()
} }
if (route.query.view) {
isView.value = true
logParams.enterpriseId = route.query.id
getLogList()
}
}) })
</script> </script>
@ -454,6 +609,41 @@ onMounted(() => {
border-radius: 8px; border-radius: 8px;
overflow: hidden; overflow: hidden;
padding: 12px; 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 { .add-prove {
width: 200px; width: 200px;

Loading…
Cancel
Save