| | |
| | | // 设备巡检 |
| | | // 巡检管理 |
| | | import request from '@/utils/request' |
| | | |
| | | // 巡检任务表表查询 |
| | |
| | | } |
| | | |
| | | // /inspectionTask/addOrEditInspectionTask |
| | | // 设备巡检 |
| | | // 巡检管理 |
| | | export function uploadInspectionTask(query) { |
| | | return request({ |
| | | url: '/inspectionTask/addOrEditInspectionTask', |
| | |
| | | // 设备巡检 |
| | | // 巡检管理 |
| | | import request from '@/utils/request' |
| | | |
| | | // 二维码管理表查询 |
| | |
| | | { |
| | | "path": "pages/equipmentManagement/inspection/index", |
| | | "style": { |
| | | "navigationBarTitleText": "设备巡检", |
| | | "navigationBarTitleText": "巡检管理", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | |
| | | { |
| | | "path": "pages/inspectionUpload/index", |
| | | "style": { |
| | | "navigationBarTitleText": "设备巡检", |
| | | "navigationBarTitleText": "巡检管理", |
| | | "navigationStyle": "custom", |
| | | "enablePullDownRefresh": true, |
| | | "backgroundColor": "#f8f8f8" |
| | |
| | | @click="editVisit(item)"> |
| | | 编辑 |
| | | </u-button> |
| | | <u-button type="error" |
| | | <!-- <u-button type="error" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="deleteVisit(item)"> |
| | | 删除 |
| | | </u-button> |
| | | </u-button> --> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | </view> |
| | | <view class="detail-row"> |
| | | <view class="actions"> |
| | | <u-button type="primary" |
| | | <!-- <u-button type="primary" |
| | | size="small" |
| | | class="action-btn edit" |
| | | :disabled="item.approveStatus == 2 || item.approveStatus == 1 || item.approveStatus == 4 || item.approveStatus == 8" |
| | | @click="handleItemClick(item)"> |
| | | 编辑 |
| | | </u-button> |
| | | </u-button> --> |
| | | <u-button type="success" |
| | | size="small" |
| | | class="action-btn approve" |
| | |
| | | <text>暂无审批数据</text> |
| | | </view> |
| | | <!-- 浮动操作按钮 --> |
| | | <view class="fab-button" |
| | | <!-- <view class="fab-button" |
| | | v-if="props.approveType != 5 && props.approveType != 6 && props.approveType != 7" |
| | | @click="handleAdd"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | </view> --> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | <text>{{ notice.title }}</text> |
| | | </view> |
| | | <view class="card-actions"> |
| | | <up-button text |
| | | <!-- <up-button text |
| | | type="primary" |
| | | size="mini" |
| | | @click="handleEdit(notice)" |
| | |
| | | size="mini" |
| | | @click="handleDelete(notice.id)"> |
| | | 删除 |
| | | </up-button> |
| | | </up-button> --> |
| | | </view> |
| | | </view> |
| | | <view class="card-content"> |
| | |
| | | <template> |
| | | <view class="inspection-detail"> |
| | | <!-- 使用通用页面头部组件 --> |
| | | <PageHeader title="设备巡检详情" @back="goBack" /> |
| | | |
| | | <PageHeader title="巡检管理详情" |
| | | @back="goBack" /> |
| | | <!-- 设备信息卡片 --> |
| | | <view class="device-card"> |
| | | <view class="device-header"> |
| | | <view class="device-icon"> |
| | | <up-icon name="settings" size="24" color="#1890ff"></up-icon> |
| | | <up-icon name="settings" |
| | | size="24" |
| | | color="#1890ff"></up-icon> |
| | | </view> |
| | | <view class="device-info"> |
| | | <text class="device-name">{{ deviceInfo.deviceName }}</text> |
| | | <text class="device-code">{{ deviceInfo.deviceCode }}</text> |
| | | </view> |
| | | <view class="qr-scan" @click="scanDeviceQR"> |
| | | <up-icon name="scan" size="20" color="#1890ff"></up-icon> |
| | | <view class="qr-scan" |
| | | @click="scanDeviceQR"> |
| | | <up-icon name="scan" |
| | | size="20" |
| | | color="#1890ff"></up-icon> |
| | | <text class="scan-text">扫码</text> |
| | | </view> |
| | | </view> |
| | |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 巡检项目清单 --> |
| | | <view class="inspection-items"> |
| | | <view class="section-title"> |
| | | <up-icon name="list" size="18" color="#333"></up-icon> |
| | | <up-icon name="list" |
| | | size="18" |
| | | color="#333"></up-icon> |
| | | <text class="title-text">巡检项目清单</text> |
| | | <text class="progress-text">({{ completedItems }}/{{ totalItems }})</text> |
| | | </view> |
| | | |
| | | <view class="items-list"> |
| | | <view |
| | | v-for="(item, index) in inspectionItems" |
| | | <view v-for="(item, index) in inspectionItems" |
| | | :key="index" |
| | | class="inspection-item" |
| | | :class="{ 'completed': item.completed, 'abnormal': item.isAbnormal }" |
| | | > |
| | | <view class="item-header" @click="toggleItem(index)"> |
| | | :class="{ 'completed': item.completed, 'abnormal': item.isAbnormal }"> |
| | | <view class="item-header" |
| | | @click="toggleItem(index)"> |
| | | <view class="item-left"> |
| | | <view class="checkbox" :class="{ 'checked': item.completed }"> |
| | | <up-icon v-if="item.completed" name="checkmark" size="14" color="#ffffff"></up-icon> |
| | | <view class="checkbox" |
| | | :class="{ 'checked': item.completed }"> |
| | | <up-icon v-if="item.completed" |
| | | name="checkmark" |
| | | size="14" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | <text class="item-name">{{ item.name }}</text> |
| | | </view> |
| | | <view class="item-status"> |
| | | <u-tag v-if="item.isAbnormal" type="error" size="mini">异常</u-tag> |
| | | <u-tag v-else-if="item.completed" type="success" size="mini">正常</u-tag> |
| | | <u-tag v-else type="info" size="mini">待检</u-tag> |
| | | <u-tag v-if="item.isAbnormal" |
| | | type="error" |
| | | size="mini">异常</u-tag> |
| | | <u-tag v-else-if="item.completed" |
| | | type="success" |
| | | size="mini">正常</u-tag> |
| | | <u-tag v-else |
| | | type="info" |
| | | size="mini">待检</u-tag> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 展开的详情内容 --> |
| | | <view v-if="item.expanded" class="item-content"> |
| | | <view v-if="item.expanded" |
| | | class="item-content"> |
| | | <view class="item-description"> |
| | | <text class="desc-text">{{ item.description }}</text> |
| | | </view> |
| | | |
| | | <!-- 巡检结果选择 --> |
| | | <view class="result-section"> |
| | | <text class="section-label">巡检结果:</text> |
| | | <view class="result-options"> |
| | | <u-radio-group v-model="item.result" @change="onResultChange(index, $event)"> |
| | | <u-radio |
| | | v-for="option in resultOptions" |
| | | <u-radio-group v-model="item.result" |
| | | @change="onResultChange(index, $event)"> |
| | | <u-radio v-for="option in resultOptions" |
| | | :key="option.value" |
| | | :label="option.value" |
| | | :name="option.label" |
| | | size="small" |
| | | > |
| | | size="small"> |
| | | {{ option.label }} |
| | | </u-radio> |
| | | </u-radio-group> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 异常情况描述 --> |
| | | <view v-if="item.result === 'abnormal'" class="abnormal-section"> |
| | | <view v-if="item.result === 'abnormal'" |
| | | class="abnormal-section"> |
| | | <text class="section-label">异常描述:</text> |
| | | <up-textarea |
| | | v-model="item.abnormalDesc" |
| | | <up-textarea v-model="item.abnormalDesc" |
| | | placeholder="请详细描述异常情况" |
| | | :maxlength="200" |
| | | count |
| | | height="80" |
| | | ></up-textarea> |
| | | height="80"></up-textarea> |
| | | </view> |
| | | |
| | | <!-- 图片上传 --> |
| | | <view class="upload-section"> |
| | | <text class="section-label">现场照片:</text> |
| | | <up-upload |
| | | :fileList="item.images" |
| | | <up-upload :fileList="item.images" |
| | | @afterRead="(event) => afterRead(event, index, 'images')" |
| | | @delete="(event) => deleteFile(event, index, 'images')" |
| | | name="images" |
| | | multiple |
| | | :maxCount="5" |
| | | :previewImage="true" |
| | | > |
| | | :previewImage="true"> |
| | | <view class="upload-btn"> |
| | | <up-icon name="camera" size="20" color="#999"></up-icon> |
| | | <up-icon name="camera" |
| | | size="20" |
| | | color="#999"></up-icon> |
| | | <text class="upload-text">添加照片</text> |
| | | </view> |
| | | </up-upload> |
| | | </view> |
| | | |
| | | <!-- 视频上传 --> |
| | | <view class="upload-section"> |
| | | <text class="section-label">现场视频:</text> |
| | | <up-upload |
| | | :fileList="item.videos" |
| | | <up-upload :fileList="item.videos" |
| | | @afterRead="(event) => afterRead(event, index, 'videos')" |
| | | @delete="(event) => deleteFile(event, index, 'videos')" |
| | | name="videos" |
| | | :maxCount="2" |
| | | accept="video" |
| | | > |
| | | accept="video"> |
| | | <view class="upload-btn"> |
| | | <up-icon name="play-circle" size="20" color="#999"></up-icon> |
| | | <up-icon name="play-circle" |
| | | size="20" |
| | | color="#999"></up-icon> |
| | | <text class="upload-text">添加视频</text> |
| | | </view> |
| | | </up-upload> |
| | | </view> |
| | | |
| | | <!-- 备注 --> |
| | | <view class="remark-section"> |
| | | <text class="section-label">备注:</text> |
| | | <up-textarea |
| | | v-model="item.remark" |
| | | <up-textarea v-model="item.remark" |
| | | placeholder="请输入备注信息(可选)" |
| | | :maxlength="100" |
| | | count |
| | | height="60" |
| | | ></up-textarea> |
| | | height="60"></up-textarea> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 底部操作按钮 --> |
| | | <view class="bottom-actions"> |
| | | <u-button |
| | | type="primary" |
| | | <u-button type="primary" |
| | | size="large" |
| | | :disabled="!canSubmit" |
| | | @click="submitInspection" |
| | | :loading="submitting" |
| | | > |
| | | :loading="submitting"> |
| | | {{ allCompleted ? '提交巡检记录' : `继续巡检 (${completedItems}/${totalItems})` }} |
| | | </u-button> |
| | | </view> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, computed, onMounted } from 'vue' |
| | | import { onShow } from '@dcloudio/uni-app' |
| | | import PageHeader from '@/components/PageHeader.vue' |
| | | import { submitInspectionRecord } from '@/api/equipmentManagement/inspection' |
| | | import dayjs from 'dayjs' |
| | | import { ref, computed, onMounted } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { submitInspectionRecord } from "@/api/equipmentManagement/inspection"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | // 设备信息 |
| | | const deviceInfo = ref({}) |
| | | const deviceInfo = ref({}); |
| | | |
| | | // 巡检项目列表 |
| | | const inspectionItems = ref([]) |
| | | const inspectionItems = ref([]); |
| | | |
| | | // 提交状态 |
| | | const submitting = ref(false) |
| | | const submitting = ref(false); |
| | | |
| | | // 巡检结果选项 |
| | | const resultOptions = [ |
| | | { label: '正常', value: 'normal' }, |
| | | { label: '异常', value: 'abnormal' } |
| | | ] |
| | | { label: "正常", value: "normal" }, |
| | | { label: "异常", value: "abnormal" }, |
| | | ]; |
| | | |
| | | // 显示提示信息 |
| | | const showToast = (message) => { |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | // 计算属性 |
| | | const totalItems = computed(() => inspectionItems.value.length) |
| | | const completedItems = computed(() => inspectionItems.value.filter(item => item.completed).length) |
| | | const allCompleted = computed(() => completedItems.value === totalItems.value && totalItems.value > 0) |
| | | const canSubmit = computed(() => completedItems.value > 0) |
| | | const totalItems = computed(() => inspectionItems.value.length); |
| | | const completedItems = computed( |
| | | () => inspectionItems.value.filter(item => item.completed).length |
| | | ); |
| | | const allCompleted = computed( |
| | | () => completedItems.value === totalItems.value && totalItems.value > 0 |
| | | ); |
| | | const canSubmit = computed(() => completedItems.value > 0); |
| | | |
| | | // 返回上一页 |
| | | const goBack = () => { |
| | | if (completedItems.value > 0) { |
| | | uni.showModal({ |
| | | title: '提示', |
| | | content: '当前有未保存的巡检记录,确定要离开吗?', |
| | | success: (res) => { |
| | | title: "提示", |
| | | content: "当前有未保存的巡检记录,确定要离开吗?", |
| | | success: res => { |
| | | if (res.confirm) { |
| | | uni.navigateBack() |
| | | uni.navigateBack(); |
| | | } |
| | | } |
| | | }) |
| | | }, |
| | | }); |
| | | } else { |
| | | uni.navigateBack() |
| | | uni.navigateBack(); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 扫描设备二维码 |
| | | const scanDeviceQR = () => { |
| | | uni.scanCode({ |
| | | success: (res) => { |
| | | console.log('扫码结果:', res) |
| | | success: res => { |
| | | console.log("扫码结果:", res); |
| | | if (res.result.includes(deviceInfo.value.deviceCode)) { |
| | | showToast('设备确认成功') |
| | | showToast("设备确认成功"); |
| | | // 记录扫码时间 |
| | | deviceInfo.value.scanTime = new Date().toISOString() |
| | | deviceInfo.value.scanTime = new Date().toISOString(); |
| | | } else { |
| | | showToast('设备二维码不匹配') |
| | | showToast("设备二维码不匹配"); |
| | | } |
| | | }, |
| | | fail: (err) => { |
| | | console.log('扫码失败:', err) |
| | | showToast('扫码失败') |
| | | } |
| | | }) |
| | | } |
| | | fail: err => { |
| | | console.log("扫码失败:", err); |
| | | showToast("扫码失败"); |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // 切换巡检项目 |
| | | const toggleItem = (index) => { |
| | | inspectionItems.value[index].expanded = !inspectionItems.value[index].expanded |
| | | } |
| | | const toggleItem = index => { |
| | | inspectionItems.value[index].expanded = |
| | | !inspectionItems.value[index].expanded; |
| | | }; |
| | | |
| | | // 巡检结果改变 |
| | | const onResultChange = (index, value) => { |
| | | const item = inspectionItems.value[index] |
| | | item.result = value |
| | | item.completed = true |
| | | item.isAbnormal = value === 'abnormal' |
| | | const item = inspectionItems.value[index]; |
| | | item.result = value; |
| | | item.completed = true; |
| | | item.isAbnormal = value === "abnormal"; |
| | | |
| | | // 如果选择正常,清空异常描述 |
| | | if (value === 'normal') { |
| | | item.abnormalDesc = '' |
| | | if (value === "normal") { |
| | | item.abnormalDesc = ""; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 文件上传后处理 |
| | | const afterRead = async (event, index, type) => { |
| | | const { file } = event |
| | | const item = inspectionItems.value[index] |
| | | const { file } = event; |
| | | const item = inspectionItems.value[index]; |
| | | |
| | | // 模拟上传过程 |
| | | uni.showLoading({ title: '上传中...' }) |
| | | uni.showLoading({ title: "上传中..." }); |
| | | |
| | | try { |
| | | // 这里应该调用实际的上传API |
| | | await new Promise(resolve => setTimeout(resolve, 1000)) |
| | | await new Promise(resolve => setTimeout(resolve, 1000)); |
| | | |
| | | // 添加到对应的文件列表 |
| | | if (type === 'images') { |
| | | item.images = item.images || [] |
| | | if (type === "images") { |
| | | item.images = item.images || []; |
| | | item.images.push({ |
| | | url: file.url, |
| | | name: file.name, |
| | | size: file.size |
| | | }) |
| | | } else if (type === 'videos') { |
| | | item.videos = item.videos || [] |
| | | size: file.size, |
| | | }); |
| | | } else if (type === "videos") { |
| | | item.videos = item.videos || []; |
| | | item.videos.push({ |
| | | url: file.url, |
| | | name: file.name, |
| | | size: file.size |
| | | }) |
| | | size: file.size, |
| | | }); |
| | | } |
| | | |
| | | uni.hideLoading() |
| | | showToast('上传成功') |
| | | uni.hideLoading(); |
| | | showToast("上传成功"); |
| | | } catch (error) { |
| | | uni.hideLoading() |
| | | showToast('上传失败') |
| | | uni.hideLoading(); |
| | | showToast("上传失败"); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 删除文件 |
| | | const deleteFile = (event, index, type) => { |
| | | const item = inspectionItems.value[index] |
| | | if (type === 'images') { |
| | | item.images.splice(event.index, 1) |
| | | } else if (type === 'videos') { |
| | | item.videos.splice(event.index, 1) |
| | | const item = inspectionItems.value[index]; |
| | | if (type === "images") { |
| | | item.images.splice(event.index, 1); |
| | | } else if (type === "videos") { |
| | | item.videos.splice(event.index, 1); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 提交巡检记录 |
| | | const submitInspection = async () => { |
| | | if (!canSubmit.value) { |
| | | showToast('请至少完成一项巡检') |
| | | return |
| | | showToast("请至少完成一项巡检"); |
| | | return; |
| | | } |
| | | |
| | | // 检查异常项目是否填写了描述 |
| | | const abnormalItems = inspectionItems.value.filter(item => item.isAbnormal) |
| | | const abnormalItems = inspectionItems.value.filter(item => item.isAbnormal); |
| | | for (const item of abnormalItems) { |
| | | if (!item.abnormalDesc || item.abnormalDesc.trim() === '') { |
| | | showToast(`请填写"${item.name}"的异常描述`) |
| | | return |
| | | if (!item.abnormalDesc || item.abnormalDesc.trim() === "") { |
| | | showToast(`请填写"${item.name}"的异常描述`); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | submitting.value = true |
| | | submitting.value = true; |
| | | |
| | | try { |
| | | const recordData = { |
| | | deviceId: deviceInfo.value.id, |
| | | deviceCode: deviceInfo.value.deviceCode, |
| | | inspectionDate: dayjs().format('YYYY-MM-DD'), |
| | | inspectionDate: dayjs().format("YYYY-MM-DD"), |
| | | inspector: deviceInfo.value.inspector, |
| | | scanTime: deviceInfo.value.scanTime, |
| | | items: inspectionItems.value.map(item => ({ |
| | |
| | | abnormalDesc: item.abnormalDesc, |
| | | images: item.images || [], |
| | | videos: item.videos || [], |
| | | remark: item.remark |
| | | remark: item.remark, |
| | | })), |
| | | completedAt: new Date().toISOString() |
| | | } |
| | | completedAt: new Date().toISOString(), |
| | | }; |
| | | |
| | | // 模拟API调用 |
| | | await new Promise(resolve => setTimeout(resolve, 2000)) |
| | | await new Promise(resolve => setTimeout(resolve, 2000)); |
| | | |
| | | // 实际API调用 |
| | | // await submitInspectionRecord(recordData) |
| | | |
| | | showToast('巡检记录提交成功') |
| | | showToast("巡检记录提交成功"); |
| | | |
| | | // 返回列表页面 |
| | | setTimeout(() => { |
| | | uni.navigateBack() |
| | | }, 1500) |
| | | |
| | | uni.navigateBack(); |
| | | }, 1500); |
| | | } catch (error) { |
| | | showToast('提交失败,请重试') |
| | | showToast("提交失败,请重试"); |
| | | } finally { |
| | | submitting.value = false |
| | | submitting.value = false; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 初始化数据 |
| | | const initData = () => { |
| | | // 从存储中获取当前巡检信息 |
| | | const currentInspection = uni.getStorageSync('currentInspection') |
| | | const currentInspection = uni.getStorageSync("currentInspection"); |
| | | if (currentInspection) { |
| | | deviceInfo.value = currentInspection |
| | | deviceInfo.value = currentInspection; |
| | | } |
| | | |
| | | // 模拟巡检项目数据 |
| | | inspectionItems.value = [ |
| | | { |
| | | name: '设备外观检查', |
| | | description: '检查设备外观是否有损坏、锈蚀、变形等异常情况', |
| | | name: "设备外观检查", |
| | | description: "检查设备外观是否有损坏、锈蚀、变形等异常情况", |
| | | completed: false, |
| | | expanded: false, |
| | | result: '', |
| | | result: "", |
| | | isAbnormal: false, |
| | | abnormalDesc: '', |
| | | abnormalDesc: "", |
| | | images: [], |
| | | videos: [], |
| | | remark: '' |
| | | remark: "", |
| | | }, |
| | | { |
| | | name: '运行状态检查', |
| | | description: '检查设备运行是否正常,有无异常声音、振动等', |
| | | name: "运行状态检查", |
| | | description: "检查设备运行是否正常,有无异常声音、振动等", |
| | | completed: false, |
| | | expanded: false, |
| | | result: '', |
| | | result: "", |
| | | isAbnormal: false, |
| | | abnormalDesc: '', |
| | | abnormalDesc: "", |
| | | images: [], |
| | | videos: [], |
| | | remark: '' |
| | | remark: "", |
| | | }, |
| | | { |
| | | name: '安全装置检查', |
| | | description: '检查各类安全装置是否完好,安全标识是否清晰', |
| | | name: "安全装置检查", |
| | | description: "检查各类安全装置是否完好,安全标识是否清晰", |
| | | completed: false, |
| | | expanded: false, |
| | | result: '', |
| | | result: "", |
| | | isAbnormal: false, |
| | | abnormalDesc: '', |
| | | abnormalDesc: "", |
| | | images: [], |
| | | videos: [], |
| | | remark: '' |
| | | remark: "", |
| | | }, |
| | | { |
| | | name: '环境条件检查', |
| | | description: '检查设备周围环境是否符合要求,通风、照明等是否正常', |
| | | name: "环境条件检查", |
| | | description: "检查设备周围环境是否符合要求,通风、照明等是否正常", |
| | | completed: false, |
| | | expanded: false, |
| | | result: '', |
| | | result: "", |
| | | isAbnormal: false, |
| | | abnormalDesc: '', |
| | | abnormalDesc: "", |
| | | images: [], |
| | | videos: [], |
| | | remark: '' |
| | | remark: "", |
| | | }, |
| | | { |
| | | name: '仪表读数记录', |
| | | description: '记录相关仪表的读数,检查是否在正常范围内', |
| | | name: "仪表读数记录", |
| | | description: "记录相关仪表的读数,检查是否在正常范围内", |
| | | completed: false, |
| | | expanded: false, |
| | | result: '', |
| | | result: "", |
| | | isAbnormal: false, |
| | | abnormalDesc: '', |
| | | abnormalDesc: "", |
| | | images: [], |
| | | videos: [], |
| | | remark: '' |
| | | } |
| | | ] |
| | | } |
| | | remark: "", |
| | | }, |
| | | ]; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | initData() |
| | | }) |
| | | initData(); |
| | | }); |
| | | |
| | | onShow(() => { |
| | | // 页面显示时刷新数据 |
| | | }) |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | |
| | | position: relative; |
| | | |
| | | &::before { |
| | | content: ''; |
| | | content: ""; |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | height: 200px; |
| | | background: linear-gradient(135deg, rgba(102, 126, 234, 0.8) 0%, rgba(118, 75, 162, 0.8) 100%); |
| | | background: linear-gradient( |
| | | 135deg, |
| | | rgba(102, 126, 234, 0.8) 0%, |
| | | rgba(118, 75, 162, 0.8) 100% |
| | | ); |
| | | z-index: 0; |
| | | } |
| | | } |
| | |
| | | <template> |
| | | <view class="inspection-page"> |
| | | <!-- 使用通用页面头部组件 --> |
| | | <PageHeader title="设备巡检" @back="goBack" /> |
| | | |
| | | <PageHeader title="巡检管理" |
| | | @back="goBack" /> |
| | | <!-- 统计信息卡片 --> |
| | | <view class="stats-cards"> |
| | | <view class="stat-card"> |
| | |
| | | <text class="stat-label">待巡检</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 巡检清单 --> |
| | | <view class="inspection-list" v-if="inspectionList.length > 0"> |
| | | <view v-for="(item, index) in inspectionList" :key="index"> |
| | | <view class="inspection-item" @click="startInspection(item)"> |
| | | <view class="inspection-list" |
| | | v-if="inspectionList.length > 0"> |
| | | <view v-for="(item, index) in inspectionList" |
| | | :key="index"> |
| | | <view class="inspection-item" |
| | | @click="startInspection(item)"> |
| | | <view class="item-header"> |
| | | <view class="item-left"> |
| | | <view class="device-icon" :class="getStatusClass(item.status)"> |
| | | <up-icon :name="getStatusIcon(item.status)" size="16" color="#ffffff"></up-icon> |
| | | <view class="device-icon" |
| | | :class="getStatusClass(item.status)"> |
| | | <up-icon :name="getStatusIcon(item.status)" |
| | | size="16" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | <view class="device-info"> |
| | | <text class="device-name">{{ item.deviceName }}</text> |
| | |
| | | </view> |
| | | </view> |
| | | <view class="status-tag"> |
| | | <u-tag :type="getTagType(item.status)" size="mini"> |
| | | <u-tag :type="getTagType(item.status)" |
| | | size="mini"> |
| | | {{ getStatusText(item.status) }} |
| | | </u-tag> |
| | | </view> |
| | | </view> |
| | | |
| | | <up-divider></up-divider> |
| | | |
| | | <view class="item-details"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">设备编号</text> |
| | |
| | | <text class="detail-label">负责人</text> |
| | | <text class="detail-value">{{ item.inspector || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row" v-if="item.status === 2"> |
| | | <view class="detail-row" |
| | | v-if="item.status === 2"> |
| | | <text class="detail-label">完成时间</text> |
| | | <text class="detail-value">{{ formatDateTime(item.completedTime) || '-' }}</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 操作按钮 --> |
| | | <view class="action-buttons"> |
| | | <u-button |
| | | type="primary" |
| | | <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.status === 2" |
| | | @click.stop="startInspection(item)" |
| | | > |
| | | @click.stop="startInspection(item)"> |
| | | {{ item.status === 0 ? '开始巡检' : item.status === 1 ? '继续巡检' : '查看详情' }} |
| | | </u-button> |
| | | <u-button |
| | | type="success" |
| | | <u-button type="success" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.status !== 1" |
| | | @click.stop="scanQRCode(item)" |
| | | > |
| | | @click.stop="scanQRCode(item)"> |
| | | 扫码打卡 |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view v-else class="no-data"> |
| | | <up-empty mode="data" text="暂无巡检任务"></up-empty> |
| | | <view v-else |
| | | class="no-data"> |
| | | <up-empty mode="data" |
| | | text="暂无巡检任务"></up-empty> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, computed, onMounted } from 'vue' |
| | | import { onShow } from '@dcloudio/uni-app' |
| | | import PageHeader from '@/components/PageHeader.vue' |
| | | import { ref, computed, onMounted } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | // import { getInspectionList } from '@/api/inspectionUpload/index' |
| | | import dayjs from 'dayjs' |
| | | import dayjs from "dayjs"; |
| | | |
| | | // 选中的日期 |
| | | const selectedDate = ref(Date.now()) |
| | | const selectedDate = ref(Date.now()); |
| | | |
| | | // 巡检清单数据 |
| | | const inspectionList = ref([]) |
| | | const inspectionList = ref([]); |
| | | |
| | | // 显示提示信息 |
| | | const showToast = (message) => { |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | // 计算统计数据 |
| | | const totalCount = computed(() => inspectionList.value.length) |
| | | const completedCount = computed(() => inspectionList.value.filter(item => item.status === 2).length) |
| | | const pendingCount = computed(() => inspectionList.value.filter(item => item.status === 0).length) |
| | | const totalCount = computed(() => inspectionList.value.length); |
| | | const completedCount = computed( |
| | | () => inspectionList.value.filter(item => item.status === 2).length |
| | | ); |
| | | const pendingCount = computed( |
| | | () => inspectionList.value.filter(item => item.status === 0).length |
| | | ); |
| | | |
| | | // 返回上一页 |
| | | const goBack = () => { |
| | | uni.navigateBack() |
| | | } |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // 日期格式化器 |
| | | const dateFormatter = (type, value) => { |
| | | if (type === 'year') { |
| | | return `${value}年` |
| | | if (type === "year") { |
| | | return `${value}年`; |
| | | } |
| | | if (type === 'month') { |
| | | return `${value}月` |
| | | if (type === "month") { |
| | | return `${value}月`; |
| | | } |
| | | if (type === 'day') { |
| | | return `${value}日` |
| | | if (type === "day") { |
| | | return `${value}日`; |
| | | } |
| | | return value |
| | | } |
| | | return value; |
| | | }; |
| | | |
| | | // 格式化日期 |
| | | const formatDate = (timestamp) => { |
| | | return dayjs(timestamp).format('YYYY年MM月DD日') |
| | | } |
| | | const formatDate = timestamp => { |
| | | return dayjs(timestamp).format("YYYY年MM月DD日"); |
| | | }; |
| | | |
| | | // 格式化日期时间 |
| | | const formatDateTime = (dateStr) => { |
| | | if (!dateStr) return '' |
| | | return dayjs(dateStr).format('MM-DD HH:mm') |
| | | } |
| | | const formatDateTime = dateStr => { |
| | | if (!dateStr) return ""; |
| | | return dayjs(dateStr).format("MM-DD HH:mm"); |
| | | }; |
| | | |
| | | // 日期改变事件 |
| | | const onDateChange = (value) => { |
| | | selectedDate.value = value.value |
| | | getList() |
| | | } |
| | | const onDateChange = value => { |
| | | selectedDate.value = value.value; |
| | | getList(); |
| | | }; |
| | | |
| | | // 获取状态样式类 |
| | | const getStatusClass = (status) => { |
| | | const getStatusClass = status => { |
| | | switch (status) { |
| | | case 0: return 'status-pending' |
| | | case 1: return 'status-progress' |
| | | case 2: return 'status-completed' |
| | | default: return 'status-pending' |
| | | case 0: |
| | | return "status-pending"; |
| | | case 1: |
| | | return "status-progress"; |
| | | case 2: |
| | | return "status-completed"; |
| | | default: |
| | | return "status-pending"; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 获取状态图标 |
| | | const getStatusIcon = (status) => { |
| | | const getStatusIcon = status => { |
| | | switch (status) { |
| | | case 0: return 'clock' |
| | | case 1: return 'play-circle' |
| | | case 2: return 'checkmark-circle' |
| | | default: return 'clock' |
| | | case 0: |
| | | return "clock"; |
| | | case 1: |
| | | return "play-circle"; |
| | | case 2: |
| | | return "checkmark-circle"; |
| | | default: |
| | | return "clock"; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 获取标签类型 |
| | | const getTagType = (status) => { |
| | | const getTagType = status => { |
| | | switch (status) { |
| | | case 0: return 'warning' |
| | | case 1: return 'primary' |
| | | case 2: return 'success' |
| | | default: return 'info' |
| | | case 0: |
| | | return "warning"; |
| | | case 1: |
| | | return "primary"; |
| | | case 2: |
| | | return "success"; |
| | | default: |
| | | return "info"; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 获取状态文本 |
| | | const getStatusText = (status) => { |
| | | const getStatusText = status => { |
| | | switch (status) { |
| | | case 0: return '待巡检' |
| | | case 1: return '巡检中' |
| | | case 2: return '已完成' |
| | | default: return '未知' |
| | | case 0: |
| | | return "待巡检"; |
| | | case 1: |
| | | return "巡检中"; |
| | | case 2: |
| | | return "已完成"; |
| | | default: |
| | | return "未知"; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 开始巡检 |
| | | const startInspection = (item) => { |
| | | const startInspection = item => { |
| | | // 存储当前巡检项目信息 |
| | | uni.setStorageSync('currentInspection', item) |
| | | uni.setStorageSync("currentInspection", item); |
| | | uni.navigateTo({ |
| | | url: '/pages/equipmentManagement/inspection/detail' |
| | | }) |
| | | } |
| | | url: "/pages/equipmentManagement/inspection/detail", |
| | | }); |
| | | }; |
| | | |
| | | // 扫码打卡 |
| | | const scanQRCode = (item) => { |
| | | const scanQRCode = item => { |
| | | uni.scanCode({ |
| | | success: (res) => { |
| | | console.log('扫码结果:', res) |
| | | success: res => { |
| | | console.log("扫码结果:", res); |
| | | // 验证二维码内容 |
| | | if (res.result.includes(item.deviceCode)) { |
| | | showToast('打卡成功') |
| | | showToast("打卡成功"); |
| | | // 更新打卡状态 |
| | | updateCheckInStatus(item.id) |
| | | updateCheckInStatus(item.id); |
| | | } else { |
| | | showToast('二维码不匹配,请扫描正确的设备二维码') |
| | | showToast("二维码不匹配,请扫描正确的设备二维码"); |
| | | } |
| | | }, |
| | | fail: (err) => { |
| | | console.log('扫码失败:', err) |
| | | showToast('扫码失败') |
| | | } |
| | | }) |
| | | } |
| | | fail: err => { |
| | | console.log("扫码失败:", err); |
| | | showToast("扫码失败"); |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // 更新打卡状态 |
| | | const updateCheckInStatus = (id) => { |
| | | const updateCheckInStatus = id => { |
| | | // 这里应该调用API更新打卡状态 |
| | | // 暂时模拟更新本地数据 |
| | | const item = inspectionList.value.find(item => item.id === id) |
| | | const item = inspectionList.value.find(item => item.id === id); |
| | | if (item) { |
| | | item.checkInTime = new Date().toISOString() |
| | | item.checkInTime = new Date().toISOString(); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 查询巡检清单 |
| | | const getList = () => { |
| | | uni.showLoading({ |
| | | title: '加载中...', |
| | | mask: true |
| | | }) |
| | | title: "加载中...", |
| | | mask: true, |
| | | }); |
| | | |
| | | const params = { |
| | | date: dayjs(selectedDate.value).format('YYYY-MM-DD') |
| | | } |
| | | date: dayjs(selectedDate.value).format("YYYY-MM-DD"), |
| | | }; |
| | | |
| | | // 模拟数据,实际应该调用API |
| | | setTimeout(() => { |
| | | inspectionList.value = [ |
| | | { |
| | | id: 1, |
| | | deviceName: '空压机A01', |
| | | deviceCode: 'KYJ-A01', |
| | | location: '生产车间A区', |
| | | inspectionTime: '08:00-09:00', |
| | | inspector: '张三', |
| | | deviceName: "空压机A01", |
| | | deviceCode: "KYJ-A01", |
| | | location: "生产车间A区", |
| | | inspectionTime: "08:00-09:00", |
| | | inspector: "张三", |
| | | status: 0, // 0:待巡检 1:巡检中 2:已完成 |
| | | completedTime: null |
| | | completedTime: null, |
| | | }, |
| | | { |
| | | id: 2, |
| | | deviceName: '冷却塔B02', |
| | | deviceCode: 'LQT-B02', |
| | | location: '生产车间B区', |
| | | inspectionTime: '09:00-10:00', |
| | | inspector: '李四', |
| | | deviceName: "冷却塔B02", |
| | | deviceCode: "LQT-B02", |
| | | location: "生产车间B区", |
| | | inspectionTime: "09:00-10:00", |
| | | inspector: "李四", |
| | | status: 1, |
| | | completedTime: null |
| | | completedTime: null, |
| | | }, |
| | | { |
| | | id: 3, |
| | | deviceName: '变压器C03', |
| | | deviceCode: 'BYQ-C03', |
| | | location: '配电房', |
| | | inspectionTime: '10:00-11:00', |
| | | inspector: '王五', |
| | | deviceName: "变压器C03", |
| | | deviceCode: "BYQ-C03", |
| | | location: "配电房", |
| | | inspectionTime: "10:00-11:00", |
| | | inspector: "王五", |
| | | status: 2, |
| | | completedTime: '2024-01-15T10:30:00' |
| | | } |
| | | ] |
| | | uni.hideLoading() |
| | | }, 1000) |
| | | completedTime: "2024-01-15T10:30:00", |
| | | }, |
| | | ]; |
| | | uni.hideLoading(); |
| | | }, 1000); |
| | | |
| | | // 实际API调用 |
| | | // getInspectionList(params) |
| | |
| | | // uni.hideLoading() |
| | | // showToast('获取数据失败') |
| | | // }) |
| | | } |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList() |
| | | }) |
| | | getList(); |
| | | }); |
| | | |
| | | onShow(() => { |
| | | getList() |
| | | }) |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/styles/sales-common.scss'; |
| | | @import "@/styles/sales-common.scss"; |
| | | |
| | | .inspection-page { |
| | | background: #ffffff; |
| | | min-height: 100vh; |
| | | padding-bottom: 20px; |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | .stats-cards { |
| | | display: flex; |
| | |
| | | <template> |
| | | <view class="sales-account"> |
| | | <!-- 使用通用页面头部组件 --> |
| | | <PageHeader title="设备报修" @back="goBack" /> |
| | | |
| | | <PageHeader title="设备报修" |
| | | @back="goBack" /> |
| | | <!-- 搜索区域 --> |
| | | <view class="search-section"> |
| | | <view class="search-bar"> |
| | | <view class="search-input"> |
| | | <up-input |
| | | class="search-text" |
| | | <up-input class="search-text" |
| | | placeholder="请输入设备名称搜索" |
| | | v-model="searchKeyword" |
| | | @change="getList" |
| | | clearable |
| | | /> |
| | | clearable /> |
| | | </view> |
| | | <view class="filter-button" @click="getList"> |
| | | <up-icon name="search" size="24" color="#999"></up-icon> |
| | | <view class="filter-button" |
| | | @click="getList"> |
| | | <up-icon name="search" |
| | | size="24" |
| | | color="#999"></up-icon> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 设备报修列表 --> |
| | | <view class="ledger-list" v-if="repairList.length > 0"> |
| | | <view v-for="(item, index) in repairList" :key="index"> |
| | | <view class="ledger-list" |
| | | v-if="repairList.length > 0"> |
| | | <view v-for="(item, index) in repairList" |
| | | :key="index"> |
| | | <view class="ledger-item"> |
| | | <view class="item-header"> |
| | | <view class="item-left"> |
| | | <view class="document-icon"> |
| | | <up-icon name="file-text" size="16" color="#ffffff"></up-icon> |
| | | <up-icon name="file-text" |
| | | size="16" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | <text class="item-id">设备名称:{{ item.deviceName }}</text> |
| | | </view> |
| | | <view class="status-tag"> |
| | | <u-tag v-if="item.status === 1" type="success">完结</u-tag> |
| | | <u-tag v-if="item.status === 0" type="error">待维修</u-tag> |
| | | <u-tag v-if="item.status === 1" |
| | | type="success">完结</u-tag> |
| | | <u-tag v-if="item.status === 0" |
| | | type="error">待维修</u-tag> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | |
| | | <view class="item-details"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">规格型号</text> |
| | |
| | | <text class="detail-value">{{ formatDate(item.maintenanceTime) || '-' }}</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 按钮区域 --> |
| | | <view class="action-buttons"> |
| | | <u-button |
| | | type="primary" |
| | | <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.status === 1" |
| | | @click="edit(item.id)" |
| | | > |
| | | @click="edit(item.id)"> |
| | | 编辑 |
| | | </u-button> |
| | | <u-button |
| | | type="warning" |
| | | <u-button type="warning" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.status === 1" |
| | | @click="addMaintain(item.id)" |
| | | > |
| | | @click="addMaintain(item.id)"> |
| | | 新增维修 |
| | | </u-button> |
| | | <u-button |
| | | type="error" |
| | | <u-button type="error" |
| | | size="small" |
| | | plain |
| | | class="action-btn" |
| | | @click="delRepairByIds(item.id)" |
| | | > |
| | | @click="delRepairByIds(item.id)"> |
| | | 删除 |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view v-else class="no-data"> |
| | | <view v-else |
| | | class="no-data"> |
| | | <text>暂无设备报修数据</text> |
| | | </view> |
| | | <!-- 浮动操作按钮 --> |
| | | <view class="fab-button" @click="addRepair"> |
| | | <up-icon name="plus" size="24" color="#ffffff"></up-icon> |
| | | <view class="fab-button" |
| | | @click="addRepair"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted } from 'vue' |
| | | import { onShow } from '@dcloudio/uni-app' |
| | | import PageHeader from '@/components/PageHeader.vue' |
| | | import { getRepairPage, delRepair } from '@/api/equipmentManagement/repair' |
| | | import useUserStore from "@/store/modules/user" |
| | | import { ref, onMounted } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { getRepairPage, delRepair } from "@/api/equipmentManagement/repair"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | |
| | | const showToast = (message) => { |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | const userStore = useUserStore() |
| | | const userStore = useUserStore(); |
| | | |
| | | // 搜索关键词 |
| | | const searchKeyword = ref('') |
| | | const searchKeyword = ref(""); |
| | | |
| | | // 设备报修数据 |
| | | const repairList = ref([]) |
| | | const repairList = ref([]); |
| | | |
| | | // 返回上一页 |
| | | const goBack = () => { |
| | | uni.navigateBack() |
| | | } |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // 格式化日期 |
| | | const formatDate = (dateStr) => { |
| | | if (!dateStr) return '' |
| | | const date = new Date(dateStr) |
| | | const year = date.getFullYear() |
| | | const month = String(date.getMonth() + 1).padStart(2, '0') |
| | | const day = String(date.getDate()).padStart(2, '0') |
| | | return `${year}-${month}-${day}` |
| | | } |
| | | const formatDate = dateStr => { |
| | | if (!dateStr) return ""; |
| | | const date = new Date(dateStr); |
| | | const year = date.getFullYear(); |
| | | const month = String(date.getMonth() + 1).padStart(2, "0"); |
| | | const day = String(date.getDate()).padStart(2, "0"); |
| | | return `${year}-${month}-${day}`; |
| | | }; |
| | | |
| | | // 查询列表 |
| | | const getList = () => { |
| | | showLoadingToast('加载中...') |
| | | showLoadingToast("加载中..."); |
| | | const params = { |
| | | current: -1, |
| | | size: -1, |
| | | deviceName: searchKeyword.value || undefined |
| | | } |
| | | deviceName: searchKeyword.value || undefined, |
| | | }; |
| | | getRepairPage(params) |
| | | .then((res) => { |
| | | repairList.value = res.records || res.data?.records || [] |
| | | closeToast() |
| | | .then(res => { |
| | | repairList.value = res.records || res.data?.records || []; |
| | | closeToast(); |
| | | }) |
| | | .catch(() => { |
| | | closeToast() |
| | | showToast('获取数据失败') |
| | | }) |
| | | } |
| | | closeToast(); |
| | | showToast("获取数据失败"); |
| | | }); |
| | | }; |
| | | |
| | | // 显示加载提示 |
| | | const showLoadingToast = (message) => { |
| | | const showLoadingToast = message => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true |
| | | mask: true, |
| | | }); |
| | | }; |
| | | |
| | |
| | | }; |
| | | |
| | | // 新增维修 - 跳转到维修页面 |
| | | const addMaintain = (id) => { |
| | | const addMaintain = id => { |
| | | if (!id) { |
| | | showToast('参数错误') |
| | | return |
| | | showToast("参数错误"); |
| | | return; |
| | | } |
| | | // 使用uni.setStorageSync存储id |
| | | uni.setStorageSync('repairId', id) |
| | | uni.setStorageSync("repairId", id); |
| | | uni.navigateTo({ |
| | | url: '/pages/equipmentManagement/repair/maintain' |
| | | }) |
| | | } |
| | | url: "/pages/equipmentManagement/repair/maintain", |
| | | }); |
| | | }; |
| | | |
| | | // 新增报修 - 跳转到报修页面 |
| | | const addRepair = () => { |
| | | uni.navigateTo({ |
| | | url: '/pages/equipmentManagement/repair/add' |
| | | }) |
| | | } |
| | | url: "/pages/equipmentManagement/repair/add", |
| | | }); |
| | | }; |
| | | |
| | | // 编辑 - 跳转到add页面,通过id区分新增还是编辑 |
| | | const edit = (id) => { |
| | | if (!id) return |
| | | const edit = id => { |
| | | if (!id) return; |
| | | // 使用uni.setStorageSync存储id |
| | | uni.setStorageSync('repairId', id) |
| | | uni.setStorageSync("repairId", id); |
| | | uni.navigateTo({ |
| | | url: '/pages/equipmentManagement/repair/add' |
| | | }) |
| | | } |
| | | url: "/pages/equipmentManagement/repair/add", |
| | | }); |
| | | }; |
| | | |
| | | // 删除报修数据 |
| | | const delRepairByIds = async (ids) => { |
| | | const delRepairByIds = async ids => { |
| | | uni.showModal({ |
| | | title: '警告', |
| | | content: '确认删除报修数据, 此操作不可逆?', |
| | | confirmText: '确定', |
| | | cancelText: '取消', |
| | | success: async (res) => { |
| | | if (!res.confirm) return |
| | | title: "警告", |
| | | content: "确认删除报修数据, 此操作不可逆?", |
| | | confirmText: "确定", |
| | | cancelText: "取消", |
| | | success: async res => { |
| | | if (!res.confirm) return; |
| | | try { |
| | | const response = await delRepair(ids) |
| | | const response = await delRepair(ids); |
| | | if (response.code === 200) { |
| | | showToast('删除成功') |
| | | getList() |
| | | showToast("删除成功"); |
| | | getList(); |
| | | } else { |
| | | showToast('删除失败') |
| | | showToast("删除失败"); |
| | | } |
| | | } catch (e) { |
| | | showToast('删除失败') |
| | | showToast("删除失败"); |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList() |
| | | }) |
| | | getList(); |
| | | }); |
| | | |
| | | onShow(() => { |
| | | getList() |
| | | }) |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/styles/sales-common.scss'; |
| | | @import "@/styles/sales-common.scss"; |
| | | |
| | | // 设备维修特有样式 |
| | | .sales-account { |
| | |
| | | const todayRecord = ref({}); |
| | | |
| | | // 班次信息 |
| | | const workTimeDict = ref({ |
| | | startAt: "09:00", |
| | | endAt: "18:00", |
| | | }); |
| | | const workTimeDict = ref(); |
| | | |
| | | // 当前时间展示 |
| | | const nowTime = ref(""); |
| | |
| | | title="搜索日期" /> |
| | | <view class="record-list"> |
| | | <!-- 加载状态 --> |
| | | <view v-if="loading" |
| | | class="loading-state"> |
| | | <u-icon name="loading" |
| | | size="40" |
| | | color="#348fe2"></u-icon> |
| | | <text class="loading-text">加载中...</text> |
| | | </view> |
| | | <view v-else |
| | | v-for="(item) in tableData" |
| | | <view v-for="(item) in tableData" |
| | | :key="item.id" |
| | | class="record-item-card" |
| | | :class="{ 'abnormal': item.status !== 0 }"> |
| | |
| | | </view> |
| | | <!-- 按钮区域 --> |
| | | <view class="action-buttons"> |
| | | <u-button type="primary" |
| | | <!-- <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="editItem(item)"> |
| | |
| | | class="action-btn" |
| | | @click="deleteItem(item)"> |
| | | 删除 |
| | | </u-button> |
| | | </u-button> --> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | <text>暂无薪资台账数据</text> |
| | | </view> |
| | | <!-- 浮动新增按钮 --> |
| | | <view class="fab-button" |
| | | <!-- <view class="fab-button" |
| | | @click="addItem"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | </view> --> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/xunjianshangchuan@2x.png", |
| | | label: "设备巡检", |
| | | label: "巡检管理", |
| | | }, |
| | | ]); |
| | | |
| | |
| | | url: "/pages/equipmentManagement/upkeep/index", |
| | | }); |
| | | break; |
| | | case "设备巡检": |
| | | case "巡检管理": |
| | | uni.navigateTo({ |
| | | url: "/pages/inspectionUpload/index", |
| | | }); |
| | |
| | | { icon: "/static/images/icon/shbeibaoxiu@2x.png", label: "运行管理" }, |
| | | { icon: "/static/images/icon/shbeibaoxiu@2x.png", label: "设备报修" }, |
| | | { icon: "/static/images/icon/shbeibaoyang@2x.png", label: "设备保养" }, |
| | | { icon: "/static/images/icon/xunjianshangchuan@2x.png", label: "设备巡检" }, |
| | | { icon: "/static/images/icon/xunjianshangchuan@2x.png", label: "巡检管理" }, |
| | | ]; |
| | | const filteredEquipment = originalEquipment.filter(item => { |
| | | return allowedMenuTitles.has(item.label); |
| | |
| | | url: "/pages/equipmentManagement/upkeep/index", |
| | | }); |
| | | break; |
| | | case "设备巡检": |
| | | case "巡检管理": |
| | | uni.navigateTo({ |
| | | url: "/pages/inspectionUpload/index", |
| | | }); |
| | |
| | | <template> |
| | | <view class="inspection-upload-page"> |
| | | <!-- 页面头部 --> |
| | | <PageHeader title="设备巡检" |
| | | <PageHeader title="巡检管理" |
| | | @back="goBack" /> |
| | | <!-- 数据列表 --> |
| | | <view class="table-section"> |
| | |
| | | @click="viewDetail(item,3)"> |
| | | 查看 |
| | | </u-button> |
| | | <u-button type="error" |
| | | <!-- <u-button type="error" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="confirmDelete(item)"> |
| | |
| | | class="action-btn" |
| | | @click="viewDetail(item,2)"> |
| | | 编辑 |
| | | </u-button> |
| | | </u-button> --> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | <text>暂无知识记录</text> |
| | | </view> |
| | | <!-- 浮动新增按钮 --> |
| | | <view class="fab-button" |
| | | <!-- <view class="fab-button" |
| | | @click="addVisit"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | </view> --> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | </view> |
| | | <!-- 按钮区域 --> |
| | | <view class="action-buttons"> |
| | | <u-button type="primary" |
| | | <!-- <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="viewDetail(item)"> |
| | |
| | | class="action-btn" |
| | | @click="confirmDelete(item)"> |
| | | 删除 |
| | | </u-button> |
| | | </u-button> --> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | <text>暂无会议室记录</text> |
| | | </view> |
| | | <!-- 浮动新增按钮 --> |
| | | <view class="fab-button" |
| | | <!-- <view class="fab-button" |
| | | @click="addVisit"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | </view> --> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | @click="viewDetail(item,3)"> |
| | | 查看 |
| | | </u-button> |
| | | <u-button type="error" |
| | | <!-- <u-button type="error" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="handleAbrogate(item)"> |
| | |
| | | class="action-btn" |
| | | @click="viewDetail(item,2)"> |
| | | 编辑 |
| | | </u-button> |
| | | </u-button> --> |
| | | <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | |
| | | <text>暂无规章制度</text> |
| | | </view> |
| | | <!-- 浮动新增按钮 --> |
| | | <view class="fab-button" |
| | | <!-- <view class="fab-button" |
| | | @click="addVisit"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | </view> --> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | @click="viewDetail(item,3)"> |
| | | 查看 |
| | | </u-button> |
| | | <u-button type="primary" |
| | | <!-- <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | v-if="item.status === 'pending'" |
| | |
| | | v-if="item.status === 'pending'" |
| | | @click="confirmApprove(item,false)"> |
| | | 拒绝 |
| | | </u-button> |
| | | </u-button> --> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | <text>暂无用印记录</text> |
| | | </view> |
| | | <!-- 浮动新增按钮 --> |
| | | <view class="fab-button" |
| | | <!-- <view class="fab-button" |
| | | @click="addVisit"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | </view> --> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | </view> |
| | | <!-- 操作按钮区域 --> |
| | | <view class="action-buttons"> |
| | | <u-button type="primary" |
| | | <!-- <u-button type="primary" |
| | | size="small" |
| | | @click="handleAddInvoice(item)" |
| | | class="action-btn" |
| | | :disabled="item.unReceiptPaymentAmount == 0"> |
| | | 新增开票 |
| | | </u-button> |
| | | </u-button> --> |
| | | <u-button size="small" |
| | | @click="handleViewDetail(item)" |
| | | class="action-btn"> |
| | |
| | | </view> |
| | | <!-- 操作按钮 --> |
| | | <view class="action-buttons"> |
| | | <u-button type="primary" |
| | | <!-- <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.unPaymentAmountTotal == 0" |
| | | @click="openForm('add', item)"> |
| | | 新增付款 |
| | | </u-button> |
| | | </u-button> --> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | <template> |
| | | <view class="sales-account"> |
| | | <!-- 使用通用页面头部组件 --> |
| | | <PageHeader title="来票台账" @back="goBack" /> |
| | | |
| | | <PageHeader title="来票台账" |
| | | @back="goBack" /> |
| | | <!-- 搜索区域 --> |
| | | <view class="search-section"> |
| | | <view class="search-bar"> |
| | | <view class="search-input"> |
| | | <up-input |
| | | class="search-text" |
| | | <up-input class="search-text" |
| | | placeholder="请输入供应商名称搜索" |
| | | v-model="searchForm.supplierName" |
| | | @change="handleQuery" |
| | | clearable |
| | | /> |
| | | clearable /> |
| | | </view> |
| | | <view class="filter-button" @click="handleQuery"> |
| | | <up-icon name="search" size="24" color="#999"></up-icon> |
| | | <view class="filter-button" |
| | | @click="handleQuery"> |
| | | <up-icon name="search" |
| | | size="24" |
| | | color="#999"></up-icon> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 列表区域 --> |
| | | <view class="ledger-list" v-if="total > 0"> |
| | | <view v-for="(item, index) in ledgerList" :key="index"> |
| | | <view class="ledger-list" |
| | | v-if="total > 0"> |
| | | <view v-for="(item, index) in ledgerList" |
| | | :key="index"> |
| | | <view class="ledger-item"> |
| | | <view class="item-header"> |
| | | <view class="item-left"> |
| | | <view class="document-icon"> |
| | | <up-icon name="file-text" size="16" color="#ffffff"></up-icon> |
| | | <up-icon name="file-text" |
| | | size="16" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | <text class="item-id">{{ item.purchaseContractNumber }}</text> |
| | | </view> |
| | |
| | | </view> |
| | | </view> |
| | | <view class="action-buttons"> |
| | | <u-button |
| | | <!-- <u-button |
| | | type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | |
| | | @click="handleDelete(item)" |
| | | > |
| | | 删除 |
| | | </u-button> |
| | | </u-button> --> |
| | | <!-- <u-button--> |
| | | <!-- type="default"--> |
| | | <!-- size="small"--> |
| | |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else class="no-data"> |
| | | <view v-else |
| | | class="no-data"> |
| | | <text>暂无来票台账数据</text> |
| | | </view> |
| | | |
| | | <!-- 单行上传弹窗(无表单) --> |
| | | <u-popup v-model="showUpload" mode="bottom" border-radius="10"> |
| | | <u-popup v-model="showUpload" |
| | | mode="bottom" |
| | | border-radius="10"> |
| | | <view class="upload-container"> |
| | | <view class="popup-header"> |
| | | <text class="popup-title">上传附件(仅支持 pdf,最大10MB,最多10个)</text> |
| | | </view> |
| | | <u-upload |
| | | ref="uploadRef" |
| | | <u-upload ref="uploadRef" |
| | | accept="file" |
| | | multiple |
| | | :max-count="10" |
| | |
| | | :header="{ Authorization: 'Bearer ' + getToken() }" |
| | | name="file" |
| | | @on-success="onUploadSuccess" |
| | | @on-error="onUploadError" |
| | | /> |
| | | <view class="uploaded-list" v-if="fileList.length"> |
| | | <view class="uploaded-item" v-for="(f, idx) in fileList" :key="idx"> |
| | | @on-error="onUploadError" /> |
| | | <view class="uploaded-list" |
| | | v-if="fileList.length"> |
| | | <view class="uploaded-item" |
| | | v-for="(f, idx) in fileList" |
| | | :key="idx"> |
| | | <text class="file-name">{{ f.name || getFileNameFromUrl(f.url) }}</text> |
| | | <u-button size="mini" type="error" plain @click="removeUploaded(idx)">移除</u-button> |
| | | <u-button size="mini" |
| | | type="error" |
| | | plain |
| | | @click="removeUploaded(idx)">移除</u-button> |
| | | </view> |
| | | </view> |
| | | <view class="filter-actions"> |
| | | <u-button @click="showUpload = false" type="default" size="default" style="width: 150px;">取消</u-button> |
| | | <u-button @click="confirmUpload" type="primary" size="default" style="width: 150px;">确认</u-button> |
| | | <u-button @click="showUpload = false" |
| | | type="default" |
| | | size="default" |
| | | style="width: 150px;">取消</u-button> |
| | | <u-button @click="confirmUpload" |
| | | type="primary" |
| | | size="default" |
| | | style="width: 150px;">确认</u-button> |
| | | </view> |
| | | </view> |
| | | </u-popup> |
| | | |
| | | <!-- 附件列表选择 --> |
| | | <u-action-sheet v-model="showFileSheet" :list="fileActions" :cancel-btn="true" @click="onSelectFile" @close="showFileSheet = false" /> |
| | | <u-action-sheet v-model="showFileSheet" |
| | | :list="fileActions" |
| | | :cancel-btn="true" |
| | | @click="onSelectFile" |
| | | @close="showFileSheet = false" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted } from 'vue' |
| | | import dayjs from 'dayjs' |
| | | const showToast = (message) => { |
| | | import { ref, reactive, onMounted } from "vue"; |
| | | import dayjs from "dayjs"; |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | import useUserStore from '@/store/modules/user' |
| | | import { getToken } from '@/utils/auth' |
| | | import config from '@/config.js' |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { getToken } from "@/utils/auth"; |
| | | import config from "@/config.js"; |
| | | import { |
| | | registrationProductPage, |
| | | commitFile, |
| | | delInvoiceLedgerByRegProductId |
| | | } from '@/api/salesManagement/invoiceLedger.js' |
| | | delInvoiceLedgerByRegProductId, |
| | | } from "@/api/salesManagement/invoiceLedger.js"; |
| | | import {onShow} from "@dcloudio/uni-app"; |
| | | import {productRecordPage} from "@/api/procurementManagement/procurementInvoiceLedger"; |
| | | import {delRegistration} from "@/api/procurementManagement/invoiceEntry"; |
| | | import PageHeader from '@/components/PageHeader.vue'; |
| | | import FooterButtons from '@/components/FooterButtons.vue'; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import FooterButtons from "@/components/FooterButtons.vue"; |
| | | |
| | | const userStore = useUserStore() |
| | | const userStore = useUserStore(); |
| | | |
| | | // 列表与查询 |
| | | const ledgerList = ref([]) |
| | | const total = ref(0) |
| | | const page = reactive({ current: -1, size: -1 }) |
| | | const ledgerList = ref([]); |
| | | const total = ref(0); |
| | | const page = reactive({ current: -1, size: -1 }); |
| | | const searchForm = reactive({ |
| | | supplierName: '', |
| | | }) |
| | | supplierName: "", |
| | | }); |
| | | |
| | | const currentId = ref('') |
| | | const fileList = ref([]) // 行上传或通用上传列表 |
| | | const uploadRef = ref() |
| | | const uploadUrl = config.baseUrl + '/invoiceLedger/uploadFile' |
| | | const currentId = ref(""); |
| | | const fileList = ref([]); // 行上传或通用上传列表 |
| | | const uploadRef = ref(); |
| | | const uploadUrl = config.baseUrl + "/invoiceLedger/uploadFile"; |
| | | |
| | | // 行上传弹窗 |
| | | const showUpload = ref(false) |
| | | const showUpload = ref(false); |
| | | |
| | | // 附件查看 |
| | | const showFileSheet = ref(false) |
| | | const fileActions = ref([]) |
| | | let currentFilesToOpen = [] |
| | | const showFileSheet = ref(false); |
| | | const fileActions = ref([]); |
| | | let currentFilesToOpen = []; |
| | | |
| | | const formatAmount = (val) => { |
| | | if (val === undefined || val === null || val === '') return '0.00' |
| | | const num = Number(val) |
| | | if (Number.isNaN(num)) return '0.00' |
| | | return num.toFixed(2) |
| | | } |
| | | const formatDateTime = (val) => { |
| | | if (!val) return '' |
| | | return dayjs(val).format('YYYY-MM-DD HH:mm:ss') |
| | | } |
| | | const formatAmount = val => { |
| | | if (val === undefined || val === null || val === "") return "0.00"; |
| | | const num = Number(val); |
| | | if (Number.isNaN(num)) return "0.00"; |
| | | return num.toFixed(2); |
| | | }; |
| | | const formatDateTime = val => { |
| | | if (!val) return ""; |
| | | return dayjs(val).format("YYYY-MM-DD HH:mm:ss"); |
| | | }; |
| | | |
| | | const goBack = () => { |
| | | uni.navigateBack() |
| | | } |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | const handleQuery = () => { |
| | | getList() |
| | | } |
| | | getList(); |
| | | }; |
| | | |
| | | const getList = async () => { |
| | | try { |
| | | uni.showLoading({ |
| | | title: '加载中...' |
| | | title: "加载中...", |
| | | }); |
| | | const res = await productRecordPage({ ...searchForm, ...page }) |
| | | const res = await productRecordPage({ ...searchForm, ...page }); |
| | | // 兼容不同返回结构 |
| | | const records = res?.data?.records || res?.records || res?.data || [] |
| | | const totalVal = res?.data?.total || res?.total || records.length || 0 |
| | | ledgerList.value = records |
| | | total.value = totalVal |
| | | const records = res?.data?.records || res?.records || res?.data || []; |
| | | const totalVal = res?.data?.total || res?.total || records.length || 0; |
| | | ledgerList.value = records; |
| | | total.value = totalVal; |
| | | uni.hideLoading(); |
| | | } catch (e) { |
| | | uni.hideLoading(); |
| | | showToast('获取列表失败') |
| | | showToast("获取列表失败"); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 编辑逻辑改为跳转新页面 |
| | | const openEdit = (row) => { |
| | | const openEdit = row => { |
| | | try { |
| | | uni.setStorageSync('invoiceLedgerEditRow', JSON.stringify(row)) |
| | | uni.navigateTo({ url: '/pages/procurementManagement/procurementInvoiceLedger/detail' }) |
| | | uni.setStorageSync("invoiceLedgerEditRow", JSON.stringify(row)); |
| | | uni.navigateTo({ |
| | | url: "/pages/procurementManagement/procurementInvoiceLedger/detail", |
| | | }); |
| | | } catch (e) { |
| | | showToast('跳转失败') |
| | | showToast("跳转失败"); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 删除 |
| | | const handleDelete = (row) => { |
| | | const handleDelete = row => { |
| | | let ids = []; |
| | | ids.push(row.id); |
| | | console.log(ids) |
| | | console.log(ids); |
| | | uni.showModal({ |
| | | title: '删除确认', |
| | | content: '该发票台账将被删除,是否确认删除?', |
| | | success: async (res) => { |
| | | title: "删除确认", |
| | | content: "该发票台账将被删除,是否确认删除?", |
| | | success: async res => { |
| | | if (res.confirm) { |
| | | try { |
| | | uni.showLoading({ |
| | | title: '处理中...' |
| | | title: "处理中...", |
| | | }); |
| | | await delRegistration(ids) |
| | | await delRegistration(ids); |
| | | uni.hideLoading(); |
| | | showToast('删除成功') |
| | | await getList() |
| | | showToast("删除成功"); |
| | | await getList(); |
| | | } catch (e) { |
| | | uni.hideLoading(); |
| | | showToast('删除失败,请重试') |
| | | showToast("删除失败,请重试"); |
| | | } |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // 行上传 |
| | | const openUpload = (row) => { |
| | | currentId.value = row.id |
| | | fileList.value = [] |
| | | showUpload.value = true |
| | | } |
| | | const openUpload = row => { |
| | | currentId.value = row.id; |
| | | fileList.value = []; |
| | | showUpload.value = true; |
| | | }; |
| | | const confirmUpload = async () => { |
| | | try { |
| | | const payload = { fileList: fileList.value, id: currentId.value } |
| | | const payload = { fileList: fileList.value, id: currentId.value }; |
| | | uni.showLoading({ |
| | | title: '提交中...' |
| | | title: "提交中...", |
| | | }); |
| | | await commitFile(payload) |
| | | await commitFile(payload); |
| | | uni.hideLoading(); |
| | | showToast('提交成功') |
| | | showUpload.value = false |
| | | fileList.value = [] |
| | | currentId.value = '' |
| | | getList() |
| | | showToast("提交成功"); |
| | | showUpload.value = false; |
| | | fileList.value = []; |
| | | currentId.value = ""; |
| | | getList(); |
| | | } catch (e) { |
| | | uni.hideLoading(); |
| | | showToast('提交失败,请重试') |
| | | showToast("提交失败,请重试"); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 上传相关 |
| | | const beforeReadPdf = (file) => { |
| | | const beforeReadPdf = file => { |
| | | // 兼容多文件 |
| | | const files = Array.isArray(file) ? file : [file] |
| | | const files = Array.isArray(file) ? file : [file]; |
| | | for (const f of files) { |
| | | const sizeOk = f.size <= 10 * 1024 * 1024 |
| | | const ext = (f.name || '').split('.').pop()?.toLowerCase() |
| | | if (ext !== 'pdf') { |
| | | showToast('仅支持pdf文件') |
| | | return false |
| | | const sizeOk = f.size <= 10 * 1024 * 1024; |
| | | const ext = (f.name || "").split(".").pop()?.toLowerCase(); |
| | | if (ext !== "pdf") { |
| | | showToast("仅支持pdf文件"); |
| | | return false; |
| | | } |
| | | if (!sizeOk) { |
| | | showToast('上传文件大小不能超过10MB') |
| | | return false |
| | | showToast("上传文件大小不能超过10MB"); |
| | | return false; |
| | | } |
| | | } |
| | | return true |
| | | } |
| | | return true; |
| | | }; |
| | | |
| | | // uview-plus 的上传成功回调 |
| | | const onUploadSuccess = (res, file) => { |
| | | try { |
| | | const data = JSON.parse(res.data || '{}') |
| | | const data = JSON.parse(res.data || "{}"); |
| | | if (data.code === 200) { |
| | | fileList.value.push(data.data) |
| | | showToast('上传成功') |
| | | fileList.value.push(data.data); |
| | | showToast("上传成功"); |
| | | } else { |
| | | showToast('上传失败: ' + (data.msg || '未知错误')) |
| | | showToast("上传失败: " + (data.msg || "未知错误")); |
| | | } |
| | | } catch (err) { |
| | | showToast('上传失败') |
| | | showToast("上传失败"); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // uview-plus 的上传失败回调 |
| | | const onUploadError = (err) => { |
| | | showToast('上传失败') |
| | | } |
| | | const onUploadError = err => { |
| | | showToast("上传失败"); |
| | | }; |
| | | |
| | | const removeUploaded = (index) => { |
| | | fileList.value.splice(index, 1) |
| | | } |
| | | const removeUploaded = index => { |
| | | fileList.value.splice(index, 1); |
| | | }; |
| | | |
| | | const getFileNameFromUrl = (url) => { |
| | | const getFileNameFromUrl = url => { |
| | | try { |
| | | if (!url) return '' |
| | | return decodeURIComponent(url.split('/').pop()) |
| | | if (!url) return ""; |
| | | return decodeURIComponent(url.split("/").pop()); |
| | | } catch (e) { |
| | | return url |
| | | return url; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 附件查看 |
| | | const openFileActions = (commonFiles) => { |
| | | currentFilesToOpen = commonFiles || [] |
| | | const openFileActions = commonFiles => { |
| | | currentFilesToOpen = commonFiles || []; |
| | | fileActions.value = (commonFiles || []).map((f, idx) => ({ |
| | | title: getFileNameFromUrl(f.url || ''), |
| | | index: idx |
| | | })) |
| | | showFileSheet.value = true |
| | | } |
| | | const onSelectFile = async (action) => { |
| | | title: getFileNameFromUrl(f.url || ""), |
| | | index: idx, |
| | | })); |
| | | showFileSheet.value = true; |
| | | }; |
| | | const onSelectFile = async action => { |
| | | try { |
| | | const item = currentFilesToOpen[action.index] |
| | | if (!item || !item.url) return |
| | | const item = currentFilesToOpen[action.index]; |
| | | if (!item || !item.url) return; |
| | | uni.showLoading({ |
| | | title: '下载中...' |
| | | title: "下载中...", |
| | | }); |
| | | uni.downloadFile({ |
| | | url: item.url, |
| | | success: (res) => { |
| | | success: res => { |
| | | uni.hideLoading(); |
| | | if (res.statusCode === 200) { |
| | | uni.openDocument({ filePath: res.tempFilePath }) |
| | | uni.openDocument({ filePath: res.tempFilePath }); |
| | | } else { |
| | | showToast('下载失败') |
| | | showToast("下载失败"); |
| | | } |
| | | }, |
| | | fail: () => { |
| | | uni.hideLoading(); |
| | | showToast('下载失败') |
| | | } |
| | | }) |
| | | showToast("下载失败"); |
| | | }, |
| | | }); |
| | | } catch (e) { |
| | | uni.hideLoading(); |
| | | showToast('打开失败') |
| | | showToast("打开失败"); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | onShow(() => { |
| | | getList() |
| | | }) |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/styles/procurement-common.scss'; |
| | | @import "@/styles/procurement-common.scss"; |
| | | |
| | | // 来票台账特有样式(所有样式都已包含在公共样式中) |
| | | </style> |
| | |
| | | </view> |
| | | </view> |
| | | <!-- 仅非“审批通过”的台账展示删除按钮 --> |
| | | <view class="detail-row" |
| | | <!-- <view class="detail-row" |
| | | v-if="item.approvalStatus !== 3" |
| | | style="justify-content: flex-end; margin-top: 8px;"> |
| | | <up-button type="error" |
| | |
| | | @click.stop="handleDelete(item)"> |
| | | 删除 |
| | | </up-button> |
| | | </view> |
| | | </view> --> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | <text>暂无采购台账数据</text> |
| | | </view> |
| | | <!-- 浮动操作按钮 --> |
| | | <view class="fab-button" |
| | | <!-- <view class="fab-button" |
| | | @click="handleInfo('add')"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | </view> --> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | > |
| | | 编辑付款 |
| | | </u-button> --> |
| | | <u-button type="error" |
| | | <!-- <u-button type="error" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.registrant !== userStore.nickName" |
| | | @click="deleteItem(item)"> |
| | | 删除 |
| | | </u-button> |
| | | </u-button> --> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | </view> |
| | | <!-- 操作按钮 --> |
| | | <view class="action-buttons"> |
| | | <u-button type="primary" |
| | | <!-- <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.inspectState" |
| | | @click.stop="startInspection(item)"> |
| | | 编辑 |
| | | </u-button> |
| | | </u-button> --> |
| | | <u-button type="info" |
| | | size="small" |
| | | class="action-btn" |
| | | @click.stop="viewDetail(item)"> |
| | | 详情 |
| | | </u-button> |
| | | <u-button type="success" |
| | | <!-- <u-button type="success" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.inspectState" |
| | | @click.stop="submitInspection(item)"> |
| | | 提交 |
| | | </u-button> |
| | | </u-button> --> |
| | | </view> |
| | | <view class="action-buttons"> |
| | | <u-button type="info" |
| | | <!-- <u-button type="info" |
| | | size="small" |
| | | class="action-btn" |
| | | @click.stop="viewFileList(item)"> |
| | |
| | | :disabled="item.inspectState || item.checkName !== ''" |
| | | @click.stop="assignInspector(item)"> |
| | | 分配检验员 |
| | | </u-button> |
| | | </u-button> --> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | </view> |
| | | <!-- 分页组件 --> |
| | | <!-- 浮动新增按钮 --> |
| | | <view class="fab-button" |
| | | <!-- <view class="fab-button" |
| | | @click="addInspection"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | </view> --> |
| | | <!-- 日期选择器 --> |
| | | <up-popup v-model:show="showDate" |
| | | mode="date" |
| | |
| | | </view> |
| | | <!-- 操作按钮 --> |
| | | <view class="action-buttons"> |
| | | <u-button type="primary" |
| | | <!-- <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.inspectState" |
| | | @click.stop="startInspection(item)"> |
| | | 编辑 |
| | | </u-button> |
| | | </u-button> --> |
| | | <u-button type="info" |
| | | size="small" |
| | | class="action-btn" |
| | | @click.stop="viewDetail(item)"> |
| | | 详情 |
| | | </u-button> |
| | | <u-button type="success" |
| | | <!-- <u-button type="success" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.inspectState" |
| | | @click.stop="submitInspection(item)"> |
| | | 提交 |
| | | </u-button> |
| | | </u-button> --> |
| | | </view> |
| | | <view class="action-buttons"> |
| | | <u-button type="info" |
| | | <!-- <u-button type="info" |
| | | size="small" |
| | | class="action-btn" |
| | | @click.stop="viewFileList(item)"> |
| | |
| | | :disabled="item.inspectState || item.checkName !== ''" |
| | | @click.stop="assignInspector(item)"> |
| | | 分配检验员 |
| | | </u-button> |
| | | </u-button> --> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | </view> |
| | | <!-- 分页组件 --> |
| | | <!-- 浮动新增按钮 --> |
| | | <view class="fab-button" |
| | | <!-- <view class="fab-button" |
| | | @click="addInspection"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | </view> --> |
| | | <!-- 日期选择器 --> |
| | | <up-popup v-model:show="showDate" |
| | | mode="date" |
| | |
| | | </view> |
| | | <!-- 操作按钮 --> |
| | | <view class="action-buttons"> |
| | | <u-button type="primary" |
| | | <!-- <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.inspectState" |
| | | @click.stop="startInspection(item)"> |
| | | 编辑 |
| | | </u-button> |
| | | </u-button> --> |
| | | <u-button type="info" |
| | | size="small" |
| | | class="action-btn" |
| | | @click.stop="viewDetail(item)"> |
| | | 详情 |
| | | </u-button> |
| | | <u-button type="success" |
| | | <!-- <u-button type="success" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.inspectState" |
| | | @click.stop="submitInspection(item)"> |
| | | 提交 |
| | | </u-button> |
| | | </u-button> --> |
| | | </view> |
| | | <view class="action-buttons"> |
| | | <u-button type="info" |
| | | <!-- <u-button type="info" |
| | | size="small" |
| | | class="action-btn" |
| | | @click.stop="viewFileList(item)"> |
| | |
| | | :disabled="item.inspectState || item.checkName !== ''" |
| | | @click.stop="assignInspector(item)"> |
| | | 分配检验员 |
| | | </u-button> |
| | | </u-button> --> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | </view> |
| | | <!-- 分页组件 --> |
| | | <!-- 浮动新增按钮 --> |
| | | <view class="fab-button" |
| | | <!-- <view class="fab-button" |
| | | @click="addInspection"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | </view> --> |
| | | <!-- 日期选择器 --> |
| | | <up-popup v-model:show="showDate" |
| | | mode="date" |
| | |
| | | @click="viewDetail(item)"> |
| | | 查看详情 |
| | | </u-button> |
| | | <u-button type="primary" |
| | | <!-- <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="editAccident(item)"> |
| | |
| | | class="action-btn" |
| | | @click="deleteAccident(item)"> |
| | | 删除 |
| | | </u-button> |
| | | </u-button> --> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | <text>暂无事故记录</text> |
| | | </view> |
| | | <!-- 浮动新增按钮 --> |
| | | <view class="fab-button" |
| | | <!-- <view class="fab-button" |
| | | @click="addAccident"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | </view> --> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | </view> |
| | | <!-- 按钮区域 --> |
| | | <view class="action-buttons"> |
| | | <!-- <u-button type="info" |
| | | <u-button type="info" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="viewDetail(item)"> |
| | | 查看详情 |
| | | </u-button> --> |
| | | <u-button type="warning" |
| | | </u-button> |
| | | <!-- <u-button type="warning" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.isRectify" |
| | |
| | | :disabled="!item.rectifyActualTime" |
| | | @click="acceptanceVisit(item)"> |
| | | 验收 |
| | | </u-button> |
| | | </u-button> --> |
| | | </view> |
| | | <view class="action-buttons"> |
| | | <u-button type="primary" |
| | | <!-- <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="editVisit(item)"> |
| | |
| | | class="action-btn" |
| | | @click="deleteVisit(item)"> |
| | | 删除 |
| | | </u-button> |
| | | </u-button> --> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | <text>暂无拜访记录</text> |
| | | </view> |
| | | <!-- 浮动新增按钮 --> |
| | | <view class="fab-button" |
| | | <!-- <view class="fab-button" |
| | | @click="addVisit"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | </view> --> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | </view> |
| | | <!-- 按钮区域 --> |
| | | <view class="action-buttons"> |
| | | <u-button type="primary" |
| | | <!-- <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="editPlan(item)"> |
| | | 编辑 |
| | | </u-button> |
| | | </u-button> --> |
| | | <u-button type="info" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="viewDetail(item)"> |
| | | 查看详情 |
| | | </u-button> |
| | | <u-button type="error" |
| | | <!-- <u-button type="error" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="deletePlan(item)"> |
| | | 删除 |
| | | </u-button> |
| | | </u-button> --> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | <text>暂无应急预案</text> |
| | | </view> |
| | | <!-- 浮动新增按钮 --> |
| | | <view class="fab-button" |
| | | <!-- <view class="fab-button" |
| | | @click="addPlan"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | </view> --> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | @click="viewDetail(item)"> |
| | | 查看详情 |
| | | </u-button> |
| | | <u-button type="primary" |
| | | <!-- <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="editVisit(item)"> |
| | |
| | | class="action-btn" |
| | | @click="deleteVisit(item)"> |
| | | 删除 |
| | | </u-button> |
| | | </u-button> --> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | <text>暂无拜访记录</text> |
| | | </view> |
| | | <!-- 浮动新增按钮 --> |
| | | <view class="fab-button" |
| | | <!-- <view class="fab-button" |
| | | @click="addVisit"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | </view> --> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | @click="viewDetail(item)"> |
| | | 查看详情 |
| | | </u-button> --> |
| | | <u-button type="primary" |
| | | <!-- <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.returnUserId" |
| | |
| | | class="action-btn" |
| | | @click="deleteVisit(item)"> |
| | | 删除 |
| | | </u-button> |
| | | </u-button> --> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | <text>暂无拜访记录</text> |
| | | </view> |
| | | <!-- 浮动新增按钮 --> |
| | | <view class="fab-button" |
| | | <!-- <view class="fab-button" |
| | | @click="addVisit"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | </view> --> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | @click="viewDetail(item)"> |
| | | 查看详情 |
| | | </u-button> |
| | | <u-button type="primary" |
| | | <!-- <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="editVisit(item)"> |
| | |
| | | class="action-btn" |
| | | @click="deleteVisit(item)"> |
| | | 删除 |
| | | </u-button> |
| | | </u-button> --> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | <text>暂无拜访记录</text> |
| | | </view> |
| | | <!-- 浮动新增按钮 --> |
| | | <view class="fab-button" |
| | | <!-- <view class="fab-button" |
| | | @click="addVisit"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | </view> --> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | </view> |
| | | <!-- 按钮区域 --> |
| | | <view class="action-buttons"> |
| | | <u-button type="primary" |
| | | <!-- <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.state !== 0" |
| | |
| | | class="action-btn" |
| | | @click="deleteVisit(item)"> |
| | | 删除 |
| | | </u-button> |
| | | </u-button> --> |
| | | </view> |
| | | <view class="action-buttons"> |
| | | <u-button type="warning" |
| | |
| | | @cancel="handleDateCancel" |
| | | title="选择培训日期" /> |
| | | <!-- 浮动新增按钮 --> |
| | | <view class="fab-button" |
| | | <!-- <view class="fab-button" |
| | | @click="addVisit"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | </view> --> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | </view> |
| | | </view> |
| | | <view class="action-buttons"> |
| | | <up-button type="primary" |
| | | <!-- <up-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="openEdit(item)"> |
| | |
| | | class="action-btn" |
| | | @click="handleDelete(item)"> |
| | | 删除 |
| | | </up-button> |
| | | </up-button> --> |
| | | <!-- <up-button--> |
| | | <!-- size="small"--> |
| | | <!-- plain--> |
| | |
| | | </view> |
| | | <!-- 操作按钮区域 --> |
| | | <view class="action-buttons"> |
| | | <up-button type="primary" |
| | | <!-- <up-button type="primary" |
| | | size="small" |
| | | @click="handleAddInvoice(item)" |
| | | class="action-btn" |
| | | :disabled="item.noInvoiceAmountTotal == 0"> |
| | | 新增开票 |
| | | </up-button> |
| | | </up-button> --> |
| | | <up-button size="small" |
| | | @click="handleViewDetail(item)" |
| | | class="action-btn"> |
| | |
| | | </view> |
| | | </view> |
| | | <!-- 操作按钮 --> |
| | | <view class="action-buttons"> |
| | | <!-- <view class="action-buttons"> |
| | | <up-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | |
| | | @click="openForm(item)"> |
| | | 新增回款 |
| | | </up-button> |
| | | </view> |
| | | </view> --> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | > |
| | | 编辑回款 |
| | | </u-button> --> |
| | | <u-button type="error" |
| | | <!-- <u-button type="error" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.registrant !== userStore.nickName" |
| | | @click="delitem(item)"> |
| | | 删除 |
| | | </u-button> |
| | | </u-button> --> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | <u-button class="detail-button" |
| | | size="small" |
| | | type="primary" |
| | | plain |
| | | @click.stop="openOut(item)"> |
| | | 发货状态 |
| | | </u-button> |
| | | <!-- <u-button class="detail-button" |
| | | size="small" |
| | | type="primary" |
| | | @click.stop="handleInfo('edit', item)"> |
| | | 编辑 |
| | | </u-button> |
| | |
| | | plain |
| | | @click.stop="openOut(item)"> |
| | | 发货状态 |
| | | </u-button> |
| | | <u-button class="detail-button" |
| | | </u-button> --> |
| | | <!-- <u-button class="detail-button" |
| | | size="small" |
| | | type="error" |
| | | plain |
| | | @click.stop="handleDelete(item)"> |
| | | 删除 |
| | | </u-button> |
| | | </u-button> --> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | <text>暂无销售台账数据</text> |
| | | </view> |
| | | <!-- 浮动操作按钮 --> |
| | | <view class="fab-button" |
| | | <!-- <view class="fab-button" |
| | | @click="handleInfo('add')"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | </view> --> |
| | | </view> |
| | | </template> |
| | | |