Merge branch 'master' of http://139.196.74.78:10010/r/jagzwxm/ja_web
23 files modified
1 files added
| | |
| | | params, |
| | | }) |
| | | } |
| | | |
| | | // 更新出库状态 |
| | | export const fwDeviceUpdateTrackStatusApi = params => { |
| | | return request({ |
| | | url: `/drone-fw/device/fwDevice/updateTrackStatus`, |
| | | method: 'post', |
| | | params, |
| | | }) |
| | | } |
| | |
| | | {{ getDictLabel(row.status, dictObj.deviceStatus) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="yxzt" show-overflow-tooltip width="116" label="出库状态"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.trackStatus, trackStatusOptions) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作" class-name="operation-btns"> |
| | | <template v-slot="{ row }"> |
| | | <el-link @click="handleView(row)">查看</el-link> |
| | | <el-link @click="handleEdit(row)">编辑</el-link> |
| | | <el-link @click="outbound(row)">出库</el-link> |
| | | <el-link v-if="row.trackStatus === 0" @click="outbound(row)">出库</el-link> |
| | | <el-link v-else @click="returnDevice(row)">归还</el-link> |
| | | <el-link @click="scrap(row)" v-if="row.status !== 3">报废</el-link> |
| | | <!-- <el-link @click="handleDelete(row)" type="danger">删除</el-link>--> |
| | | </template> |
| | |
| | | import { onMounted, ref } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { exportFwDeviceApi, fwDevicePageApi, fwDeviceRemoveApi } from '@/views/basicManage/deviceStock/fwDevice' |
| | | import { fwDeviceUpdateTrackStatusApi } from '@/views/basicManage/deviceStock/fwDeviceTrackApi' |
| | | import FormDiaLog from './FormDiaLog.vue' |
| | | import { getDictionaryByCode } from '@/api/system/dictbiz' |
| | | import { getDeptTree } from '@/api/system/dept' |
| | |
| | | provide('dictObj', dictObj) |
| | | provide('deptTree', deptTree) |
| | | |
| | | // 出库状态 |
| | | const trackStatusOptions = ref([ |
| | | { dictKey: 0, dictValue: '未出库' }, |
| | | { dictKey: 1, dictValue: '已出库' } |
| | | ]) |
| | | |
| | | // 获取列表 |
| | | async function getList() { |
| | | const range = dateRangeFormat(dateRange.value) |
| | |
| | | outboundDialogRef.value?.open({ mode: 'edit', row: { ...row } }) |
| | | } |
| | | |
| | | // 归还 |
| | | async function returnDevice(row) { |
| | | await ElMessageBox.confirm(`确认归还吗?`, '提示', { |
| | | type: 'warning', |
| | | customClass: 'command-page-view-message-box', |
| | | confirmButtonClass: 'command-message-box-confirm', |
| | | cancelButtonClass: 'command-message-box-cancel', |
| | | }) |
| | | const payload = { |
| | | deviceId: row.id |
| | | } |
| | | await fwDeviceUpdateTrackStatusApi(payload) |
| | | ElMessage.success('归还成功') |
| | | getList() |
| | | } |
| | | |
| | | function scrap(row) { |
| | | scrapDialogRef.value?.open({ mode: 'edit', row: { ...row } }) |
| | | } |
| | |
| | | .detail-container { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | height: 680px; |
| | | max-height: 680px; |
| | | |
| | | .detail-left { |
| | | margin-right: 20px; |
| | |
| | | .label { |
| | | display: inline-block; |
| | | width: 88px; |
| | | flex-shrink: 0; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 500; |
| | | font-size: 14px; |
| | |
| | | |
| | | .val { |
| | | margin-left: 12px; |
| | | flex: 1; |
| | | overflow: hidden; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | |
| | | text-align: left; |
| | | font-style: normal; |
| | | text-transform: none; |
| | | } |
| | | |
| | | .val-long { |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | th.el-table__cell { |
| | | height: 40px; |
| | | border-bottom: 1px solid #DBDFF1 !important; |
| | | border-bottom: 1px solid #E5E6EB !important; |
| | | |
| | | .cell { |
| | | padding: 0 0 0 16px; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | | color: #9292C1; |
| | | color: #86909C; |
| | | text-align: left; |
| | | font-style: normal; |
| | | text-transform: none; |
| | |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | | color: #383874; |
| | | color: #4E5969; |
| | | text-align: left; |
| | | font-style: normal; |
| | | text-transform: none; |
| | |
| | | |
| | | &:active { |
| | | color: #FFFFFF !important; |
| | | background: #5B6BFF !important; |
| | | background: #4C34FF !important; |
| | | |
| | | span { |
| | | color: #fff !important; |
| | |
| | | //padding: 0 !important; |
| | | //padding-left: 20px !important; |
| | | color: #FFFFFF !important; |
| | | background: #5B6BFF !important; |
| | | background: #4C34FF !important; |
| | | |
| | | .is-icon-close { |
| | | //margin: 0 10px; |
| New file |
| | |
| | | import request from '@/axios' |
| | | |
| | | // 设备分页查询 |
| | | export function getEquipmentPage(params) { |
| | | return request({ |
| | | url: '/drone-gd/workOrder/gdManageDevice/page', |
| | | method: 'get', |
| | | params |
| | | // params: { descs: 'create_time', ...params }, |
| | | }) |
| | | } |
| | | |
| | | // 设备提交 |
| | | export function submitExternalEquipment(data) { |
| | | return request({ |
| | | url: '/drone-gd/workOrder/gdManageDevice/submitExternal', |
| | | method: 'post', |
| | | data |
| | | }) |
| | | } |
| | | |
| | | // 设备删除 |
| | | export function removeEquipment(data) { |
| | | return request({ |
| | | url: `/drone-gd/workOrder/gdManageDevice/remove?ids=${data.ids}`, |
| | | method: 'post', |
| | | }) |
| | | } |
| | | |
| | | // 设备详情查询 |
| | | export function getEquipmentDetail(params) { |
| | | return request({ |
| | | url: '/drone-gd/workOrder/gdManageDevice/detail', |
| | | method: 'get', |
| | | params |
| | | }) |
| | | } |
| | |
| | | destroy-on-close |
| | | :close-on-click-modal="false" |
| | | > |
| | | <el-row class="detail-row-view" v-if="dialogType === 'view'"> |
| | | <el-col :span="12"> |
| | | <div class="label">飞手姓名</div> |
| | | <div class="val">{{ formData.flyerName }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">飞手电话</div> |
| | | <div class="val">{{ formData.flyerPhone }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">飞行时长</div> |
| | | <div class="val">{{ formData.flightHours }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">技术特长</div> |
| | | <div class="val">{{ getDictLabel(formData.technicalStrength, dictObj.technicalStrength) }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">擅长机型</div> |
| | | <div class="val">{{ getDictLabel(formData.skilledUavType, dictObj.skilledUavType) }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">擅长任务类型</div> |
| | | <div class="val">{{ getDictLabel(formData.skilledTaskType, dictObj.skilledTaskType) }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">项目经验</div> |
| | | <div class="val">{{ formData.projectExperience }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">飞手证书</div> |
| | | <div class="val"> |
| | | <el-image |
| | | v-for="(item, index) in formData.certification" |
| | | :key="index" |
| | | :src="item" |
| | | :preview-src-list="formData.certification" |
| | | class="gd-image" |
| | | style="width: 100px; height: 100px; margin-right: 10px;" |
| | | /> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-form |
| | | ref="formRef" |
| | | :model="formData" |
| | | :rules="rules" |
| | | class="gd-form" |
| | | label-width="160px" |
| | | v-else |
| | | > |
| | | <el-row> |
| | | <el-col :span="12"> |
| | |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24" v-if="dialogType === 'view'"> |
| | | <!-- <el-col :span="24" v-if="dialogType === 'view'"> |
| | | <el-form-item label="飞手证书" prop="certification"> |
| | | <el-image |
| | | v-for="(item, index) in formData.certification" |
| | |
| | | style="width: 100px; height: 100px; margin-right: 10px;" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-col> --> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button color="#F2F3F5" @click="handleClose">取消</el-button> |
| | | <el-button v-if="dialogType !== 'view'" color="#F2F3F5" @click="handleClose">取消</el-button> |
| | | <el-button |
| | | v-if="dialogType !== 'view'" |
| | | type="primary" |
| | |
| | | import { ref, reactive, computed, watch, inject } from 'vue' |
| | | import { submitFlyingHand } from './flyingHandApi' |
| | | import { ElMessage } from 'element-plus' |
| | | import { getDictLabel } from '@ztzf/utils' |
| | | |
| | | import { fieldRules } from '@ztzf/utils' |
| | | |
| | |
| | | const dialogTitle = computed(() => { |
| | | switch (props.dialogType) { |
| | | case 'add': |
| | | return '添加飞手信息' |
| | | return '新增' |
| | | case 'edit': |
| | | return '编辑飞手信息' |
| | | return '编辑' |
| | | case 'view': |
| | | return '查看飞手信息' |
| | | return '查看' |
| | | default: |
| | | return '飞手信息' |
| | | } |
| | |
| | | <basic-container> |
| | | <el-form ref="queryParamsRef" :model="searchParams" class="gd-search-form"> |
| | | <el-form-item label="飞手姓名" prop="flyerName"> |
| | | <el-select |
| | | <el-input |
| | | class="gd-input gray" |
| | | v-model="searchParams.flyerName" |
| | | placeholder="请输入飞手姓名" |
| | | clearable |
| | | /> |
| | | <!-- <el-select |
| | | class="gd-select gray" |
| | | popper-class="gd-select-popper" |
| | | v-model="searchParams.flyerName" |
| | |
| | | :label="item.name" |
| | | :value="item.id" |
| | | /> |
| | | </el-select> |
| | | </el-select> --> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="擅长机型" prop="skilledUavType"> |
| | |
| | | <template v-slot="{ row }"> |
| | | <el-link type="primary" @click="openForm('view', row)">查看</el-link> |
| | | <!-- <el-link type="primary" @click="openForm('edit', row)">编辑</el-link>--> |
| | | <el-link type="primary" @click="handleDelete(row)" v-if="!['1', '2'].includes(row.innovationStatus)">删除</el-link> |
| | | <el-link type="primary" @click="handleDelete(row)" v-if="!['1', '2'].includes(row.innovationStatus) && row.isTheSameDepartment">删除</el-link> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | gdApplicationInnovationPageApi, |
| | | gdApplicationInnovationRemoveApi, |
| | | } from '@/views/orderView/orderDataManage/appInnovation/appInnovationApi' |
| | | |
| | | import { useStore } from 'vuex' |
| | | const store = useStore() |
| | | const userDepartment = store.state.user.userInfo?.dept_id |
| | | // 初始化查询参数 |
| | | const initSearchParams = () => ({ |
| | | caseName: '', // 案例名称 |
| | |
| | | loading.value = true |
| | | try { |
| | | const res = await gdApplicationInnovationPageApi(searchParams.value) |
| | | res?.data?.data?.records.forEach(item => { |
| | | item.isTheSameDepartment = String(item.createDept) === String(userDepartment) |
| | | }) |
| | | list.value = res?.data?.data?.records ?? [] |
| | | total.value = res?.data?.data?.total ?? 0 |
| | | } finally { |
| | |
| | | destroy-on-close |
| | | :close-on-click-modal="false" |
| | | > |
| | | <div class="detail-container" v-if="dialogReadonly"> |
| | | <div class="detail-container detail-container1" v-if="dialogReadonly"> |
| | | <el-row class="detail-row-view"> |
| | | <el-col :span="12"> |
| | | <div class="label">标题</div> |
| | |
| | | <div class="val">{{ formData.reviewOpinion }}</div> |
| | | </el-col> |
| | | </el-row> |
| | | <div v-if=" detailObjectionStatus === '1'"> |
| | | <div v-if=" detailObjectionStatus === '1' && !requesterProvider"> |
| | | <div class="detail-title" :style="{ marginTop:pxToRem(20)}">异议反馈</div> |
| | | <el-form ref="feedbackFormRef" class="gd-dialog-form" :model="feedbackFormData" |
| | | :rules="feedbackRules" label-width="140px"> |
| | |
| | | <div class="upload-container"> |
| | | <el-upload |
| | | :http-request="handleHttpRequest" |
| | | :limit="3" |
| | | :on-success="handleUploadSuccess" |
| | | :on-error="handleUploadError" |
| | | :on-remove="handleFileRemove" |
| | |
| | | <el-button type="primary">选择文件</el-button> |
| | | </template> |
| | | <template #tip> |
| | | <div class="el-upload__tip">支持上传 (.zip/.rar/.7z/.tar/.gz)格式文件</div> |
| | | <div class="el-upload__tip">支持上传 (.zip/.rar/.7z/.tar/.gz)格式</div> |
| | | </template> |
| | | </el-upload> |
| | | </div> |
| | |
| | | color="#F2F3F5" |
| | | |
| | | v-if="!dialogReadonly" |
| | | :loading="submitting" |
| | | :disabled="submitting" |
| | | :loading="submitting || uploading" |
| | | :disabled="submitting || uploading" |
| | | @click="handleSubmit" |
| | | > |
| | | 保存 |
| | | </el-button> |
| | | <el-button class="" color="#4C34FF" :loading="submitting" :disabled="submitting" @click="handleApply">申请</el-button> |
| | | <el-button class="" color="#4C34FF" :loading="submitting || uploading" :disabled="submitting || uploading" @click="handleApply">申请</el-button> |
| | | </template> |
| | | <template v-if="dialogReadonly && detailObjectionStatus === '1'"> |
| | | <template v-if="dialogReadonly && detailObjectionStatus === '1' && !requesterProvider"> |
| | | <el-button color="#F2F3F5" :loading="submitting" :disabled="submitting" @click="visible = false">取消</el-button> |
| | | |
| | | <el-button |
| | |
| | | } from '@/views/orderView/orderDataManage/dataObjection/dataObjectionApi' |
| | | import { putFileAttachApi } from '@/views/orderView/orderDataManage/supplyAdd/supplyAddApi' |
| | | import { pxToRem } from '@/utils/rem' |
| | | import { useStore } from 'vuex' |
| | | const store = useStore() |
| | | const requesterProvider = computed(() => store.state.user.userInfo?.role_id === '2014158512610869250') |
| | | // 初始化表单数据 |
| | | const initForm = () => ({ |
| | | id:'', |
| | | title: '', |
| | | objectionType: '', |
| | | submitter: '', |
| | |
| | | const fileList = ref([]) // 上传文件列表 |
| | | const uploadedFiles = ref([]) // 已上传文件列表 |
| | | const attachmentDetailsList = ref([]) |
| | | const uploading = ref(false) // 文件上传中状态 |
| | | |
| | | // 表单校验规则 |
| | | const rules = { |
| | |
| | | catalogResourceName: fieldRules(true), |
| | | objectionDesc: fieldRules(true), |
| | | objectionBasis: fieldRules(true), |
| | | // attachId: dialogMode.value === 'add' ? fieldRules(true) : fieldRules(false) |
| | | |
| | | } |
| | | |
| | | // 异议反馈表单校验规则 |
| | |
| | | |
| | | // 自定义上传请求 |
| | | const handleHttpRequest = async options => { |
| | | uploading.value = true |
| | | try { |
| | | const formDataObj = new FormData() |
| | | formDataObj.append('file', options.file) |
| | |
| | | } catch (error) { |
| | | options.onError(error) |
| | | console.error('文件上传失败:', error) |
| | | } finally { |
| | | uploading.value = false |
| | | } |
| | | } |
| | | |
| | | // 文件移除 |
| | | // const handleFileRemove = (file, fileListVal) => { |
| | | // uploadedFiles.value = fileListVal |
| | | // } |
| | | const handleFileRemove = (file, fileListVal) => { |
| | | if (file.response && file.response.attachId) { |
| | | uploadedFiles.value = uploadedFiles.value.filter(item => item.attachId !== file.response.attachId) |
| | | } |
| | | } |
| | | // 从展示列表中移除 |
| | | fileList.value = fileListVal |
| | | |
| | | // 从已上传列表中移除 |
| | | const index = uploadedFiles.value.findIndex(item => |
| | | item.attachId === file.attachId || item.name === file.name |
| | | ) |
| | | if (index > -1) { |
| | | uploadedFiles.value.splice(index, 1) |
| | | } |
| | | } |
| | | // 上传前验证 |
| | | const beforeFileUpload = file => { |
| | | const allowedExtensions = ['.zip', '.rar', '.7z', '.tar', '.gz'] |
| | |
| | | ElMessage.error('只能上传压缩文件格式:.zip/.rar/.7z/.tar/.gz') |
| | | return false |
| | | } |
| | | const maxSize = 100 * 1024 * 1024 // 100MB |
| | | if (file.size > maxSize) { |
| | | ElMessage.error('文件大小不能超过100MB') |
| | | return false |
| | | } |
| | | // const maxSize = 100 * 1024 * 1024 // 100MB |
| | | // if (file.size > maxSize) { |
| | | // ElMessage.error('文件大小不能超过100MB') |
| | | // return false |
| | | // } |
| | | return true |
| | | } |
| | | |
| | |
| | | async function submitForm(objectionStatus) { |
| | | const isValid = await formRef.value?.validate().catch(() => false) |
| | | if (!isValid) return |
| | | |
| | | // 在编辑模式下,如果已有附件,可以不强制上传新附件 |
| | | if (dialogMode.value === 'add' && uploadedFiles.value.length === 0) { |
| | | return ElMessage.warning('请上传附件') |
| | | } |
| | | |
| | | submitting.value = true |
| | | |
| | | try { |
| | | // 构建符合接口要求的提交数据 |
| | | const submitData = { |
| | | // 编辑模式下传递id |
| | | ...(formData.value.id && { id: formData.value.id }), |
| | | title: formData.value.title, |
| | | objectionType: formData.value.objectionType, |
| | | submitter: formData.value.submitter, |
| | |
| | | objectionBasis: formData.value.objectionBasis, |
| | | areaCode: formData.value.areaCode || '', |
| | | handleUnit: formData.value.handleUnit || '', |
| | | // 构建附件列表 |
| | | // 构建附件列表 - 使用当前已上传的文件(包括回显的) |
| | | ...(uploadedFiles.value.length > 0 && { |
| | | attachmentList: uploadedFiles.value.map(file => ({ |
| | | attachId: file.attachId, |
| | | attachName: file.originalName, |
| | | })), |
| | | }), |
| | | objectionStatus: objectionStatus |
| | | } |
| | | |
| | | // 如果是编辑且没有修改附件,可以保留原有附件ID |
| | | if (dialogMode.value === 'edit' && formData.value.attachIds) { |
| | | // 这里可以根据业务需求决定是否保留原附件ID |
| | | // 如果接口支持更新时重新上传附件ID列表,可以这样做 |
| | | } |
| | | |
| | | await gdDataObjectionSubmitApi(submitData) |
| | | ElMessage.success(dialogMode.value === 'add' ? '新增成功' : '更新成功') |
| | | visible.value = false |
| | |
| | | if (!formData.value.id) return |
| | | const res = await gdDataObjectionDetailApi({ id: formData.value.id }) |
| | | formData.value = res?.data?.data ?? {} |
| | | |
| | | // 处理附件回显 |
| | | if (formData.value.attachIds) { |
| | | getAttachDetail(formData.value.attachIds) |
| | | await getAttachDetail(formData.value.attachIds) |
| | | // 回显到上传组件 |
| | | updateFileListForDisplay() |
| | | } |
| | | } |
| | | |
| | | // 更新文件列表用于显示 |
| | | function updateFileListForDisplay() { |
| | | fileList.value = [] |
| | | uploadedFiles.value = [] |
| | | |
| | | if (attachmentDetailsList.value && attachmentDetailsList.value.length > 0) { |
| | | attachmentDetailsList.value.forEach(attach => { |
| | | const fileItem = { |
| | | name: attach.originalName || attach.name, |
| | | url: attach.link, // 用于预览 |
| | | attachId: attach.id, // 文件ID |
| | | originalName: attach.originalName, |
| | | link: attach.link |
| | | } |
| | | |
| | | fileList.value.push({ |
| | | name: fileItem.name, |
| | | url: fileItem.url, |
| | | status: 'success' // 已上传状态 |
| | | }) |
| | | |
| | | uploadedFiles.value.push(fileItem) |
| | | }) |
| | | } |
| | | } |
| | | // 获取附件详情 |
| | |
| | | const detailPromises = ids.map(id => getAttachDetailApi({ id })) |
| | | const results = await Promise.all(detailPromises) |
| | | attachmentDetailsList.value = results.map(res => res.data.data).filter(Boolean) |
| | | console.log('附件详情', attachmentDetailsList.value) |
| | | } |
| | | // 处理附件下载 |
| | | async function handleDownloadAttach() { |
| | |
| | | formData.value = dialogMode.value === 'add' ? initForm() : row |
| | | // 重置反馈表单数据 |
| | | feedbackFormData.value = initFeedbackForm() |
| | | |
| | | if (dialogMode.value !== 'add') { |
| | | // 如果是编辑,设置ID并加载详情 |
| | | if (row && row.id) { |
| | | formData.value.id = row.id |
| | | } |
| | | await loadDetail() |
| | | } |
| | | } |
| | |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .detail-container1 { |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | .upload-container { |
| | | width: 100%; |
| | | .el-upload__tip { |
| | | display: inline; |
| | | } |
| | | } |
| | | .label { |
| | | width: 120px !important; |
| | |
| | | <el-table-column prop="handleUnit" show-overflow-tooltip label="处理单位" /> |
| | | <el-table-column prop="objectionDesc" show-overflow-tooltip label="异议描述" /> |
| | | <el-table-column prop="objectionBasis" show-overflow-tooltip label="异议依据" /> |
| | | <el-table-column prop="attachName" show-overflow-tooltip label="附件名称" /> |
| | | <el-table-column prop="attachNames" show-overflow-tooltip label="附件名称" /> |
| | | <el-table-column prop="reviewOpinion" show-overflow-tooltip label="审核意见" /> |
| | | <el-table-column label="操作" class-name="operation-btns" width="150"> |
| | | <template v-slot="{ row }"> |
| | |
| | | <el-table-column label="操作" class-name="operation-btns" width="150"> |
| | | <template v-slot="{ row }"> |
| | | <el-link type="primary" @click="openForm('view', row)">查看</el-link> |
| | | <el-link type="primary" @click="openForm('edit', row)">编辑</el-link> |
| | | <el-link type="primary" @click="handleDelete(row)">删除</el-link> |
| | | <el-link type="primary" @click="openForm('edit', row)" v-if="row.isTheSameDepartment">编辑</el-link> |
| | | <el-link type="primary" @click="handleDelete(row)" v-if="row.isTheSameDepartment">删除</el-link> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | gdDataEvaluationPageApi, |
| | | gdDataEvaluationRemoveApi, |
| | | } from '@/views/orderView/orderDataManage/evaluate/evaluateApi' |
| | | |
| | | import { useStore } from 'vuex' |
| | | const store = useStore() |
| | | const userDepartment = store.state.user.userInfo?.dept_id |
| | | // 初始化查询参数 |
| | | const initSearchParams = () => ({ |
| | | title: '', // 标题 |
| | |
| | | loading.value = true |
| | | try { |
| | | const res = await gdDataEvaluationPageApi(searchParams.value) |
| | | res?.data?.data?.records.forEach(item => { |
| | | item.isTheSameDepartment = String(item.createDept) === String(userDepartment) |
| | | }) |
| | | list.value = res?.data?.data?.records ?? [] |
| | | total.value = res?.data?.data?.total ?? 0 |
| | | } finally { |
| | |
| | | </div> |
| | | <!-- 申请中--> |
| | | <div v-if="detailDemandStatus === '1' && !requesterProvider"> |
| | | <div class="detail-title">数据上传</div> |
| | | <div class="detail-title" :style="{ marginTop:pxToRem(10)}">数据上传</div> |
| | | <div class="upload-container"> |
| | | <el-upload |
| | | :http-request="handleHttpRequest" |
| | |
| | | </div> |
| | | <template #footer> |
| | | <template v-if="detailDemandStatus === '1' && !requesterProvider"> |
| | | <el-button color="#F2F3F5" :loading="submitting" :disabled="submitting" @click="rejectTheApplication">拒绝申请</el-button> |
| | | <el-button class="" color="#4C34FF" :loading="submitting" :disabled="submitting" @click="approvedByTheReview">审核通过</el-button> |
| | | <el-button color="#F2F3F5" :loading="submitting || uploading" :disabled="submitting || uploading" @click="rejectTheApplication">拒绝申请</el-button> |
| | | <el-button class="" color="#4C34FF" :loading="submitting || uploading" :disabled="submitting || uploading" @click="approvedByTheReview">审核通过</el-button> |
| | | </template> |
| | | <template v-if="detailDemandStatus === '2'"> |
| | | <el-button class="" color="#4C34FF" @click="downloadAllFiles">全部下载</el-button> |
| | |
| | | const uploadedFiles = ref([]) // 已上传文件列表 |
| | | const responseData = ref(null) |
| | | const submitting = ref(false) // 提交中状态 |
| | | const uploading = ref(false) // 文件上传中状态 |
| | | // 自定义上传请求函数 |
| | | const handleHttpRequest = async (options) => { |
| | | uploading.value = true |
| | | try { |
| | | // 创建FormData对象 |
| | | const formData = new FormData() |
| | |
| | | |
| | | // 调用导入的API函数 |
| | | const response = await putFileAttachApi(formData) |
| | | console.log('response',response) |
| | | if (response.data && response.data.success) { |
| | | // 调用上传成功的回调 |
| | | options.onSuccess(response) |
| | |
| | | // 调用上传失败的回调 |
| | | options.onError(error) |
| | | console.error('文件上传失败:', error) |
| | | } finally { |
| | | uploading.value = false |
| | | } |
| | | } |
| | | // 拒绝申请弹框控制 |
| | |
| | | const tableData = ref([]) // 附件表格数据 |
| | | // 文件移除 |
| | | const handleFileRemove = (file, fileList) => { |
| | | console.log('删除文件', fileList); |
| | | uploadedFiles.value = fileList |
| | | // 从已上传文件列表中移除对应文件 |
| | | // if (file.response && file.response.attachId) { |
| | | // // uploadedFiles.value = uploadedFiles.value.filter(item => item.attachId !== file.response.attachId) |
| | | // // 找到 id=1 的对象的索引 |
| | | // const index = uploadedFiles.value.findIndex(item => item.attachId !== file.response.attachId) |
| | | |
| | | // // 如果找到了,移除该对象 |
| | | // if (index !== -1) { |
| | | // uploadedFiles.value.splice(index, 1) |
| | | // } |
| | | // console.log('删除文件', uploadedFiles.value); |
| | | |
| | | // } |
| | | // 清空响应数据 |
| | | if (responseData.value && responseData.value.attachId === file.response?.attachId) { |
| | | responseData.value = null |
| | |
| | | } |
| | | |
| | | // 文件大小限制,这里限制为100MB |
| | | const maxSize = 100 * 1024 * 1024 // 100MB |
| | | if (file.size > maxSize) { |
| | | ElMessage.error('文件大小不能超过100MB') |
| | | return false |
| | | } |
| | | // const maxSize = 100 * 1024 * 1024 // 100MB |
| | | // if (file.size > maxSize) { |
| | | // ElMessage.error('文件大小不能超过100MB') |
| | | // return false |
| | | // } |
| | | |
| | | return true |
| | | } |
| | |
| | | // 添加更严格的检查,确保response不是undefined |
| | | if (response && response?.data && response?.data?.success) { |
| | | const fileData = response.data.data |
| | | console.log('成功数据', fileData) |
| | | responseData.value = fileData |
| | | // 添加到已上传文件列表 |
| | | uploadedFiles.value.push({ |
| | |
| | | } |
| | | } |
| | | |
| | | // 下载文件 |
| | | const downloadFile = file => { |
| | | if (file.link) { |
| | | // 创建一个隐藏的a标签来触发下载 |
| | | const a = document.createElement('a') |
| | | a.href = file.link |
| | | a.download = file.originalName || file.name |
| | | document.body.appendChild(a) |
| | | a.click() |
| | | document.body.removeChild(a) |
| | | } else { |
| | | ElMessage.warning('文件链接无效') |
| | | } |
| | | } |
| | | |
| | | // 从表格下载文件 |
| | | const downloadFileFromTable = file => { |
| | | if (file.fileUrl) { |
| | | // 创建一个隐藏的a标签来触发下载 |
| | | const a = document.createElement('a') |
| | | a.href = file.fileUrl |
| | | a.download = file.name || 'attachment' |
| | | a.download = file.fileOriginalName || '下载附件' |
| | | document.body.appendChild(a) |
| | | a.click() |
| | | document.body.removeChild(a) |
| | |
| | | if (file.fileUrl) { |
| | | const a = document.createElement('a') |
| | | a.href = file.fileUrl |
| | | a.download = file.name || `attachment_${index + 1}` |
| | | a.download = file.fileOriginalName || `下载附件_${index + 1}` |
| | | document.body.appendChild(a) |
| | | a.click() |
| | | document.body.removeChild(a) |
| | |
| | | |
| | | // 拒绝申请 |
| | | const rejectTheApplication = () => { |
| | | if (uploadedFiles.value.length === 0) { |
| | | return ElMessage.warning('请上传数据') |
| | | } |
| | | // if (uploadedFiles.value.length === 0) { |
| | | // return ElMessage.warning('请上传数据') |
| | | // } |
| | | // 打开拒绝申请弹框 |
| | | rejectionDialogVisible.value = true |
| | | } |
| | |
| | | :deep(.el-upload-list) { |
| | | margin-top: 10px; |
| | | } |
| | | .el-upload-list__item.is-success:focus .el-upload-list__item-status-label, .el-upload-list__item.is-success:hover .el-upload-list__item-status-label{ |
| | | display: none !important;} |
| | | |
| | | </style> |
| | |
| | | :close-on-click-modal="false" |
| | | > |
| | | <div class="detail-container"> |
| | | <div class="detail-cell"> |
| | | <div class="detail-cell-reject"> |
| | | <span class="cell-label">拒绝原因:</span> |
| | | <el-input v-model="reasonForRejection" style="width: 380px" type="textarea" :rows="4" placeholder="请输入" /> |
| | | </div> |
| | |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .detail-cell-reject { |
| | | display: flex; |
| | | justify-content: flex-start; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <el-dialog class="gd-dialog" v-model="visible" title="查看" @closed="visible = false" width="1000px" destroy-on-close> |
| | | <div v-loading="loading"> |
| | | <el-table :data="list"> |
| | | <el-table :data="list" class="gd-dialog-table"> |
| | | <el-table-column label="线索缩略图" width="120"> |
| | | <template v-slot="{ row }"> |
| | | <el-image |
| | |
| | | </el-table> |
| | | </div> |
| | | |
| | | <template #footer> |
| | | <!-- <template #footer> |
| | | <el-button color="#F2F3F5" @click="visible = false">关闭</el-button> |
| | | </template> |
| | | </template> --> |
| | | |
| | | <DistributeDiaLog |
| | | ref="distributeDialogRef" |
| | |
| | | <el-table-column type="selection" width="46" /> |
| | | <el-table-column type="index" width="64" label="序号" /> |
| | | <el-table-column prop="nickName" show-overflow-tooltip label="文档名称" /> |
| | | <el-table-column prop="attachSize" show-overflow-tooltip label="文档大小" /> |
| | | <el-table-column prop="attachSize" show-overflow-tooltip label="文档大小"> |
| | | <template v-slot="{ row }"> |
| | | {{ formatFileSize(row.attachSize) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="deptName" show-overflow-tooltip label="文档归属" /> |
| | | <!-- <el-table-column prop="resultType" show-overflow-tooltip label="文档类型" /> --> |
| | | <el-table-column prop="resultType" show-overflow-tooltip label="文档类型"> |
| | |
| | | </template> |
| | | <script setup> |
| | | import { Search, RefreshRight, Download, Upload, Delete } from '@element-plus/icons-vue' |
| | | import { fjPageApi, fjSubmitApi, fjRemoveApi, fjDetailApi, fjUploadApi } from './inspectionRequestApi' |
| | | import { fjPageApi, fjSubmitApi, fjRemoveApi, fjDetailApi, fjUploadApi,fjDownloadByByteApi } from './inspectionRequestApi' |
| | | import { useStore } from 'vuex' |
| | | import { ref, computed, inject, onMounted } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { ElMessage, ElMessageBox, ElLoading } from 'element-plus' |
| | | import { getDictLabel } from '@ztzf/utils' |
| | | import PreviewFiles from '@/components/PreviewFiles/PreviewFiles.vue' |
| | | import { getDictionaryByCode } from '@/api/system/dictbiz' |
| | |
| | | getDictionaryByCode('patrolTaskType').then(res => { |
| | | dictObj.value = res.data.data |
| | | }) |
| | | } |
| | | |
| | | // 将字节大小转换为可读格式的函数 |
| | | const formatFileSize = (bytes) => { |
| | | if (bytes === 0 || bytes === null) return '0 B' |
| | | const k = 1024 |
| | | const sizes = ['B', 'KB', 'MB', 'GB', 'TB'] |
| | | const i = Math.floor(Math.log(bytes) / Math.log(k)) |
| | | return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i] |
| | | } |
| | | |
| | | // 获取列表 |
| | |
| | | selectedFiles.value = rows |
| | | selectedIds.value = rows.map(item => item.id) |
| | | } |
| | | |
| | | let loadingData |
| | | // 文档下载 |
| | | async function handleDownload() { |
| | | // 如果是勾选一个可以直接下载,超过一个打包下载 |
| | |
| | | ElMessage.warning('请选择要下载的文件') |
| | | return |
| | | } |
| | | if (selectedFiles.value.length === 1) { |
| | | selectedFiles.value.forEach((file, index) => { |
| | | setTimeout(() => { |
| | | // setTimeout(() => { |
| | | if (file.link) { |
| | | const a = document.createElement('a') |
| | | a.href = file.link |
| | |
| | | a.click() |
| | | document.body.removeChild(a) |
| | | } |
| | | }, index * 300) // 300ms delay between downloads |
| | | // }, index * 300) // 300ms delay between downloads |
| | | }) |
| | | } else { |
| | | // 批量下载 |
| | | try { |
| | | console.log(selectedFiles.value, '9999') |
| | | loadingData = ElLoading.service({ background: 'rgba(0, 0, 0, 0.5)', text: '打包中,请稍等...' }) |
| | | const fileIds = selectedFiles.value.map(i => i.id) |
| | | // const res = await getDownloadStatusApi({ type: 'dpsjzx' }) |
| | | // if (!['CANCELLED', 'COMPLETED'].includes(res.data.data?.status || 'COMPLETED')) { |
| | | // return ElMessage.warning('还有正在处理的') |
| | | // } |
| | | console.log(fileIds, '7777') |
| | | await fjDownloadByByteApi({ attachIds: fileIds }).then(res => { |
| | | if (res.data.code === 200) { |
| | | ElMessage.success('下载成功') |
| | | } else { |
| | | ElMessage.error(res.msg || '下载失败') |
| | | } |
| | | }) |
| | | } catch (e) { |
| | | } finally { |
| | | loadingData.close() |
| | | } |
| | | |
| | | } |
| | | } |
| | | |
| | | // 文档上传 |
| | |
| | | function onUploadFileBefore(file) { |
| | | // 执行文件上传 |
| | | let data = new FormData() |
| | | // 获取文件扩展名 |
| | | const fileExtension = file.name.split('.').pop().toLowerCase(); |
| | | data.append('file', file) |
| | | |
| | | fjUploadApi(data).then(res => { |
| | |
| | | // 保存文件URL到表单 |
| | | uploadName.value = res.data.data.originalName |
| | | editParams.value.link = res.data.data.link |
| | | editParams.value.name = res.data.data.name |
| | | editParams.value.originalName = res.data.data.originalName |
| | | editParams.value.attachSize = file.size; |
| | | editParams.value.extension = fileExtension |
| | | editParams.value.domainUrl = res.data.data.link.replace(res.data.data.name, '') |
| | | } else { |
| | | ElMessage.error(res.msg || '上传失败') |
| | | } |
| | |
| | | data, |
| | | }) |
| | | } |
| | | |
| | | // 批量打包下载 |
| | | export const fjDownloadByByteApi = data => { |
| | | return request({ |
| | | url: `/blade-resource/attach/downloadByByte`, |
| | | method: 'post', |
| | | data, |
| | | }) |
| | | } |
| | |
| | | @closed="visible = false" |
| | | destroy-on-close |
| | | :close-on-click-modal="false" |
| | | width="80%" |
| | | > |
| | | <div class="detail-container" style="display: flex"> |
| | | <div class="detail-left" v-if="dialogMode !== 'add' && processList.length"> |
| | |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">巡查任务航线</div> |
| | | <div class="val">{{ getAirName(formData.patrolRouteUrl) }}</div> |
| | | <div class="val val-long"> |
| | | <el-tooltip :content="getAirName(formData.patrolRouteUrl)" placement="top"> |
| | | {{ getAirName(formData.patrolRouteUrl) }} |
| | | </el-tooltip> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">推荐飞手</div> |
| | |
| | | function loadList() { |
| | | gdWorkOrderFlowListApi({ workOrderId: formData.value.id, type: '1' }).then(res => { |
| | | processList.value = res.data.data |
| | | console.log(processList.value, 'processList.value') |
| | | }) |
| | | } |
| | | |
| | |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | /* 时间线样式 */ |
| | | :deep(.gd-timeline) { |
| | | padding-left: 90px; |
| | | } |
| | | |
| | | :deep(.el-timeline-item) { |
| | | padding-bottom: 20px; |
| | | .item-content { |
| | | position: relative; |
| | | .flowName { |
| | | width: 80px; |
| | | position: absolute; |
| | | left: -120px; |
| | | top: 0px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | :deep(.el-timeline-item__timestamp) { |
| | | font-size: 12px; |
| | | color: #999; |
| | | margin-top: 2px; |
| | | } |
| | | </style> |
| | |
| | | confirmButtonClass: 'gd-confirm-button', |
| | | cancelButtonClass: 'gd-confirm-cancel-button', |
| | | }) |
| | | const ids = row ? row.id : selectedIds.value |
| | | const ids = row ? [row.id] : selectedIds.value |
| | | await operatingIncomeBatchDelete(ids) |
| | | ElMessage.success('删除成功') |
| | | selectedIds.value = [] |
| | |
| | | </el-table> |
| | | <template v-if="hasPatrolTaskList"> |
| | | <div class="detail-title" :style="{ marginTop: pxToRem(20) }">巡查任务名称</div> |
| | | <el-table class="setHeight" :data="patrolTaskList" row-key="id"> |
| | | <el-table class="setHeight gd-dialog-table" :data="patrolTaskList" row-key="id"> |
| | | <el-table-column prop="patrolTaskName" show-overflow-tooltip label="巡查任务名称" /> |
| | | <el-table-column prop="patrolTaskType" show-overflow-tooltip label="巡查任务类型"> |
| | | <template v-slot="{ row }"> |
| | |
| | | const url = URL.createObjectURL(blob) |
| | | const a = document.createElement('a') |
| | | a.href = url |
| | | a.download = `机构列表${new Date().getTime()}.xlsx` |
| | | // `机构列表${new Date().getTime()}.xlsx` |
| | | a.download = `机构列表.xlsx` |
| | | document.body.appendChild(a) |
| | | a.click() |
| | | document.body.removeChild(a) |
| | |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">区划级别</div> |
| | | <div class="val"> {{ getDictLabel(formData.regionLevel, dictObj.divisionLevel) }}</div> |
| | | <div class="val"> {{ getDictLabel(formData.regionLevel, dictObj.regionLevel) }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">区划排序</div> |
| | |
| | | placeholder="请选择" |
| | | clearable |
| | | > |
| | | <el-option v-for="item in dictObj.divisionLevel" :key="item.dictKey" |
| | | <el-option v-for="item in dictObj.regionLevel" :key="item.dictKey" |
| | | :label="item.dictValue" |
| | | :value="item.dictKey" /> |
| | | </el-select> |
| | |
| | | <el-table-column prop="parentName" show-overflow-tooltip label="上级区划名称" /> |
| | | <el-table-column prop="regionLevel" show-overflow-tooltip label="区划级别"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.regionLevel, dictObj.divisionLevel) }} |
| | | {{ getDictLabel(row.regionLevel, dictObj.regionLevel) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="sort" show-overflow-tooltip label="排序" /> |
| | |
| | | |
| | | // 获取字典列表 |
| | | function getDictList() { |
| | | return getDictionaryByCode('zoningStatus,divisionLevel').then(res => { |
| | | return getDictionaryByCode('zoningStatus,regionLevel').then(res => { |
| | | dictObj.value = res.data.data |
| | | }) |
| | | } |
| | |
| | | <div class="workOrderContainer"> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">工单编号</div> |
| | | <div>{{ workDetailData.eventCode }}</div> |
| | | <div>{{ workDetailData.eventNum }}</div> |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">工单处置人</div> |
| | |
| | | </div> |
| | | <!-- 操作按钮 --> |
| | | <div class="actionButton"> |
| | | <div class="btngroups"> |
| | | <div class="btngroups" v-if="workDetailData.eventStatus !== 3"> |
| | | <up-button type="primary" color="#AEAEAE" text="退回" @click="rejectTicket"></up-button> |
| | | <up-button type="primary" color="#1D6FE9" text="确认" @click="confirmTheTicket"></up-button> |
| | | </div> |
| | | <div class="btngroups" v-if="workDetailData.eventStatus === 3"> |
| | | <up-button type="primary" color="#1D6FE9" text="已确认" ></up-button> |
| | | </div> |
| | | </div> |
| | | <!-- 分享弹出层 --> |
| | |
| | | const res = await getGddetailedData(params) |
| | | const response = res.data.data |
| | | workDetailData.value = response |
| | | console.log('详情', workDetailData.value) |
| | | |
| | | } |
| | | // 图片预览 |
| | | const previewImage = index => { |
| | |
| | | }) |
| | | setTimeout(() => { |
| | | uni.navigateBack() |
| | | }, 1500) |
| | | }) |
| | | }) |
| | | |
| | | } |
| | |
| | | }) |
| | | setTimeout(() => { |
| | | uni.navigateBack() |
| | | }, 1500) |
| | | }) |
| | | }) |
| | | } |
| | | // 分享模态框状态 |
| | |
| | | v-model="startTime" |
| | | mode="datetime" |
| | | :min-date="minDate" |
| | | :formatter="formatter" |
| | | @confirm="onConfirmStartTime" |
| | | @cancel="isShowStartTime = false" |
| | | ></u-datetime-picker> |
| | |
| | | v-model="endTime" |
| | | mode="datetime" |
| | | :min-date="minDate" |
| | | :formatter="formatter" |
| | | @confirm="onConfirmEndTime" |
| | | @cancel="isShowEndTime = false" |
| | | ></u-datetime-picker> |
| | |
| | | const endTime = ref(Date.now()); // 设置默认值为当前时间戳 |
| | | |
| | | const onConfirmStartTime = (e) => { |
| | | formParams.value.flightStartTime = dayjs(e.value).format('YYYY-MM-DD HH:mm:ss') |
| | | formParams.value.flightStartTime = dayjs(e.value).format('YYYY-MM-DD HH:mm') |
| | | isShowStartTime.value = false |
| | | } |
| | | const onConfirmEndTime = (e) => { |
| | | formParams.value.flightEndTime = dayjs(e.value).format('YYYY-MM-DD HH:mm:ss') |
| | | formParams.value.flightEndTime = dayjs(e.value).format('YYYY-MM-DD HH:mm') |
| | | isShowEndTime.value = false |
| | | } |
| | | |
| | |
| | | isSubmitDisabled.value = false |
| | | }) |
| | | } |
| | | |
| | | const formatter = (type, value) => { |
| | | if (type === 'year') return `${value}年`; |
| | | if (type === 'month') return `${value}月`; |
| | | if (type === 'day') return `${value}日`; |
| | | if (type === 'hour') return `${value}时`; |
| | | if (type === 'minute') return `${value}分`; |
| | | return value; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | // getProTypeApi() |
| | | // getTaskType() |