| | |
| | | <view class="material-info"> |
| | | <view class="info-block"> |
| | | <view class="info-label">生产线别:</view> |
| | | <view class="info-value" v-if="!isUpdate">{{formData.lineNo}}</view> |
| | | <superwei-combox v-if="isUpdate" :candidates="DAA020List" placeholder="请选择或输入" |
| | | v-model="formData.lineNo" @select="onDaa020Change" class="modern-picker"></superwei-combox> |
| | | <view class="info-value">{{formData.daa015 || '暂无'}}</view> |
| | | </view> |
| | | <view class="info-block"> |
| | | <view class="info-label">送检批次号:</view> |
| | | <view class="info-value" v-if="!isUpdate">{{formData.billNo}}</view> |
| | | <superwei-combox v-if="isUpdate" :candidates="DAA001List" placeholder="请选择或输入" |
| | | v-model="formData.billNo" @select="onDaa001Change" class="modern-picker"></superwei-combox> |
| | | <view class="info-value">{{formData.billNo}}</view> |
| | | </view> |
| | | <view class="info-block"> |
| | | <view class="info-label">物料编码:</view> |
| | | <view class="info-value">{{formData.itemNo}}</view> |
| | | </view> |
| | | <view class="info-block"> |
| | | <view class="info-block" v-if="formData.taskNo"> |
| | | <view class="info-label">任务单号:</view> |
| | | <view class="info-value">{{formData.taskNo}}</view> |
| | | </view> |
| | |
| | | <view class="info-value">{{formData.itemName}}</view> |
| | | </view> |
| | | <view class="info-block"> |
| | | <view class="info-label">送检数量:</view> |
| | | <view class="info-label">工单数量:</view> |
| | | <view class="info-value highlight">{{formData.quantity}}</view> |
| | | </view> |
| | | <view class="info-block" v-if="formData.remarks"> |
| | |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 操作按钮区 - 检验项目获取 --> |
| | | <view class="action-buttons" v-if="isShowTable && current"> |
| | | <button class="secondary-btn" @click="getTable">获取检验项目</button> |
| | | <button class="primary-btn" v-if="isUpdate" @click="saveTable">生成检验项目</button> |
| | | </view> |
| | | <!-- 操作按钮区 - 已移除创建功能 --> |
| | | |
| | | <!-- 检验项目表格 --> |
| | | <view class="inspection-table" v-if="!isShowTable"> |
| | | <view class="inspection-table"> |
| | | <!-- 表格头部统计信息 --> |
| | | <view class="table-header-stats"> |
| | | <view class="stats-left"> |
| | |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <table> |
| | | <table v-if="tableData.length > 0"> |
| | | <thead> |
| | | <tr> |
| | | <th width="15%" style="text-align: center;">检验项目</th> |
| | |
| | | <td> |
| | | <view v-if="item.result=='合格'" class="watermark approved">合格</view> |
| | | <view v-if="item.result=='不合格'" class="watermark rejected">不合格</view> |
| | | <view v-if="item.result=='未完成'" class="watermark pending">待确认</view> |
| | | <view v-if="item.result=='未完成'" class="watermark pending">待检验</view> |
| | | <view class="description-text">{{ item.itemMod }}</view> |
| | | </td> |
| | | <td> |
| | |
| | | </tr> |
| | | </tbody> |
| | | </table> |
| | | <!-- 空状态显示 --> |
| | | <view v-else class="empty-state"> |
| | | <view class="empty-icon">📋</view> |
| | | <view class="empty-text">暂无检验项目</view> |
| | | <view class="empty-desc">该检验单还没有检验项目</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 主操作按钮区 --> |
| | | <!-- 主操作按钮区 - 只保留查看和提交功能 --> |
| | | <view class="action-buttons"> |
| | | <button v-if="isUpdate && !isShowTable && current" class="primary-btn" @click="getItem">生成检验单</button> |
| | | <button v-if="!isUpdate && !isShowTable" class="secondary-btn" @click="toImage">图片管理</button> |
| | | <button v-if="!isUpdate && !isShowTable" class="secondary-btn" @click="fetchItems">获取检验项目</button> |
| | | <button v-if="!isUpdate && !isShowTable" class="secondary-btn" @click="saveRemarks">添加描述</button> |
| | | <button v-if="!isUpdate && !isShowTable" class="secondary-btn" @click="showTablePopup = true">查看数据</button> |
| | | <button v-if="!isUpdate && !isShowTable && current" class="primary-btn" @click="submitInspection">检验提交</button> |
| | | <button v-if="!isUpdate && !isShowTable && current && !formData.fcheckResu" class="danger-btn" @click="removeXJ">删除单据</button> |
| | | <!-- 未提交状态:显示所有操作按钮 --> |
| | | <button v-if="!isUpdate && (formData.fsubmit === null || formData.fsubmit !== 1)" class="secondary-btn" @click="generateInspectionItems">获取检验项目</button> |
| | | <button v-if="!isUpdate && (formData.fsubmit === null || formData.fsubmit !== 1)" class="secondary-btn" @click="toImage">上传/查看图片</button> |
| | | <button v-if="!isUpdate && (formData.fsubmit === null || formData.fsubmit !== 1)" class="secondary-btn" @click="saveRemarks">填写不良描述</button> |
| | | <button v-if="!isUpdate && current && (formData.fsubmit === null || formData.fsubmit !== 1)" class="primary-btn" @click="submitInspection">检验提交</button> |
| | | |
| | | <!-- 已提交状态:只显示查看图片按钮 --> |
| | | <button v-if="formData.fsubmit === 1" class="secondary-btn" @click="toImage">查看图片</button> |
| | | </view> |
| | | |
| | | <!-- 弹出层 --> |
| | | <view v-if="showPopup" class="overlay"> |
| | | <view class="popup"> |
| | | <h3>修改不合格描述</h3> |
| | | <h3>填写不良描述</h3> |
| | | <form> |
| | | <view class="form-group"> |
| | | <label class="form-label">不合格描述:</label> |
| | |
| | | </view> |
| | | <view class="popup-buttons"> |
| | | <button class="primary-btn" @click="edit">修改</button> |
| | | <button class="secondary-btn" @click="showPopup = !showPopup">取消</button> |
| | | <button class="secondary-btn" @click="closePopup">取消</button> |
| | | </view> |
| | | </form> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 表格弹出层 --> |
| | | <view v-if="showTablePopup" class="overlay"> |
| | | <view class="popup table-popup"> |
| | | <h3>详细数据表格</h3> |
| | | <view class="table-container"> |
| | | <table> |
| | | <thead> |
| | | <tr> |
| | | <th>序号</th> |
| | | <th>项目名称</th> |
| | | <th>检验标准</th> |
| | | <th>检验结果</th> |
| | | </tr> |
| | | </thead> |
| | | <tbody> |
| | | <tr v-for="(item, index) in popupTableData" :key="index"> |
| | | <td>{{ index + 1 }}</td> |
| | | <td>{{ item.projName }}</td> |
| | | <td>{{ item.standard || '标准值' }}</td> |
| | | <td :class="item.result === '合格' ? 'text-success' : item.result === '不合格' ? 'text-danger' : ''"> |
| | | {{ item.result }} |
| | | </td> |
| | | </tr> |
| | | </tbody> |
| | | </table> |
| | | </view> |
| | | <view class="popup-buttons"> |
| | | <button class="secondary-btn" @click="showTablePopup = false">关闭</button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | </view> |
| | | </template> |
| | |
| | | itemModel:"", |
| | | }, |
| | | |
| | | DAA020List: [], |
| | | |
| | | DAA001List: [], |
| | | |
| | | BillNoList: [], |
| | | |
| | | lineList: [], |
| | | |
| | | lineNo: "", |
| | | // 下拉框数据已移除 - 不再支持编辑功能 |
| | | |
| | | tableData: [], |
| | | |
| | | isSubmit: true, |
| | | |
| | | isUpdate: true, |
| | | |
| | | isShowTable: false, |
| | | isUpdate: false, // 不再支持编辑功能 |
| | | |
| | | remarks: "", |
| | | |
| | | showPopup: false, |
| | | |
| | | showTablePopup: false, |
| | | |
| | | popupTableData: [], |
| | | |
| | | current: true, // 标记当前用户是否有操作权限 |
| | | msgId: 0 |
| | |
| | | //getQaItemXj02 |
| | | this.init(); |
| | | } else { |
| | | //初始化检验单号 |
| | | this.$post({ |
| | | url: "/RKJ/getMaxReleaseNo" |
| | | }).then(res => { |
| | | this.formData.releaseNo = res.data.tbBillList; |
| | | this.formData.createBy = this.$loginInfo.account; |
| | | this.formData.createDate = this.$getDate("yyyy-mm-dd"); |
| | | // 不再支持创建新单据,跳转到列表页 |
| | | uni.showModal({ |
| | | title: '提示', |
| | | content: '请从列表中选择检验单进行查看', |
| | | showCancel: false, |
| | | confirmText: '确定', |
| | | success: () => { |
| | | uni.navigateBack(); |
| | | } |
| | | }); |
| | | |
| | | //车间下拉框的初始化 |
| | | this.$post({ |
| | | url: "/XJ/getLineAll" |
| | | }).then(res => { |
| | | this.lineList = res.data.tbBillList; |
| | | this.DAA020List = res.data.tbBillList.map(item => item.lineName); |
| | | }) |
| | | } |
| | | |
| | | // 初始化弹窗表格数据示例 |
| | | this.initPopupTableData(); |
| | | }, |
| | | methods: { |
| | | // 手动获取现有检验项目(调用 /RKJ/getItems) |
| | | fetchItems() { |
| | | if (!this.formData.id) { |
| | | this.$showMessage("请先生成或打开检验单"); |
| | | return; |
| | | } |
| | | this.$post({ |
| | | url: "/RKJ/getItems", |
| | | data: { pid: this.formData.id } |
| | | }).then(res1 => { |
| | | let tableData = res1.data.tbBillList; |
| | | // 排序与 init 保持一致 |
| | | tableData.sort((a, b) => { |
| | | if (a.result === '未完成' && b.result === '合格') { |
| | | return -1; |
| | | } else if (a.result === '合格' && b.result === '未完成') { |
| | | return 1; |
| | | } else { |
| | | return 0; |
| | | } |
| | | }); |
| | | this.tableData = tableData; |
| | | this.isShowTable = this.tableData.length === 0; |
| | | // 为每一项添加 current 属性 |
| | | this.tableData.forEach((item) => { |
| | | this.$set(item, 'current', this.current); |
| | | }); |
| | | }); |
| | | }, |
| | | // 获取合格项目数量 |
| | | getPassedCount() { |
| | | return this.tableData.filter(item => item.result === '合格').length; |
| | |
| | | const statusMap = { |
| | | '合格': '合格', |
| | | '不合格': '不合格', |
| | | '未完成': '待确认' |
| | | '未完成': '待检验' |
| | | } |
| | | return statusMap[status] || '待确认'; |
| | | return statusMap[status] || '待检验'; |
| | | }, |
| | | |
| | | // 初始化弹窗表格数据 |
| | | initPopupTableData() { |
| | | // 这里可以从API获取数据,这里使用示例数据 |
| | | this.popupTableData = [ |
| | | { projName: '外观检查', standard: '无明显划痕', result: '合格' }, |
| | | { projName: '尺寸检查', standard: '10±0.5mm', result: '合格' }, |
| | | { projName: '功能测试', standard: '正常工作', result: '不合格' }, |
| | | { projName: '电气性能', standard: '5V±0.1V', result: '合格' }, |
| | | { projName: '耐压测试', standard: '≥1000V', result: '未完成' } |
| | | ]; |
| | | }, |
| | | |
| | | // 检验提交 |
| | | submitInspection() { |
| | | // 校验是否有检验项目 |
| | | if (!Array.isArray(this.tableData) || this.tableData.length === 0) { |
| | | this.$showMessage("没有检验项目,无法提交"); |
| | | return; |
| | | } |
| | | |
| | | // 校验检验项目是否全部完成 |
| | | const unfinishedItems = []; |
| | | const hasUnfinished = this.tableData.some(it => { |
| | | const checkedCount = Number(it?.isCheck ?? 0); |
| | | const requiredCount = Number(it?.levelNum ?? 0); |
| | | // 允许提交的前提:已检次数需达到要求次数 |
| | | if (checkedCount < requiredCount) { |
| | | unfinishedItems.push(it.projName); |
| | | return true; |
| | | } |
| | | return false; |
| | | }); |
| | | |
| | | if (hasUnfinished) { |
| | | const message = unfinishedItems.length > 0 |
| | | ? `以下检验项目未完成,不能提交:\n${unfinishedItems.join('、')}` |
| | | : "存在未完成的检验项目,不能提交"; |
| | | this.$showMessage(message); |
| | | return; |
| | | } |
| | | |
| | | // 校验是否所有检验项目都有结果 |
| | | const itemsWithoutResult = this.tableData.filter(it => |
| | | !it.result || it.result === '未完成' || it.result === '未检测' |
| | | ); |
| | | if (itemsWithoutResult.length > 0) { |
| | | const itemNames = itemsWithoutResult.map(it => it.projName); |
| | | this.$showMessage(`以下检验项目没有检验结果,不能提交:\n${itemNames.join('、')}`); |
| | | return; |
| | | } |
| | | |
| | | // 显示确认弹窗 |
| | | uni.showModal({ |
| | | title: '确认提交', |
| | | content: '确定要提交检验结果吗?提交后将无法修改。', |
| | | confirmText: '确定提交', |
| | | cancelText: '取消', |
| | | success: (res) => { |
| | | if (res.confirm) { |
| | | // 用户确认提交 |
| | | this.doSubmitInspection(); |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // 执行提交检验 |
| | | doSubmitInspection() { |
| | | this.$post({ |
| | | url: "/RKJ/IqcQaSubmit", |
| | | url: "/RKJ/RKJQaSubmit", |
| | | data: { |
| | | gid: this.formData.id, // 检验单主表ID |
| | | submitBy: this.$loginInfo.account // 提交人 |
| | | userNo: this.$loginInfo.account // 提交人 |
| | | } |
| | | }).then(res => { |
| | | if (res.status == 0) { |
| | | uni.showToast({ |
| | | title: res.message.toString(), |
| | | icon: 'success', |
| | | duration: 2000 |
| | | }) |
| | | // 如果有页面跳转,需要用定时器延迟 |
| | | setTimeout(() => { |
| | | uni.navigateTo({ |
| | | url: 'List' |
| | | }); |
| | | }, 2000); // 保持与 duration 相同的时长 |
| | | if (res.status === 0) { |
| | | // 显示成功提示框 |
| | | uni.showModal({ |
| | | title: '提交成功', |
| | | content: res.message || '检验提交成功!', |
| | | confirmText: '确定', |
| | | showCancel: false, |
| | | success: () => { |
| | | // 更新本地状态,隐藏提交按钮 |
| | | this.formData.fsubmit = 1; |
| | | this.formData.fsubmitBy = this.$loginInfo.account; |
| | | this.formData.fsubmitDate = new Date().toLocaleString(); |
| | | |
| | | // 刷新页面数据 |
| | | this.init(); |
| | | } |
| | | }); |
| | | } else { |
| | | uni.showModal({ |
| | | title: "提示", |
| | | content: res.message.toString(), |
| | | content: res.message || "提交失败", |
| | | confirmText: "确定", |
| | | showCancel: false, |
| | | success: (res) => { |
| | | |
| | | } |
| | | }) |
| | | showCancel: false |
| | | }); |
| | | } |
| | | }) |
| | | }).catch(error => { |
| | | uni.showModal({ |
| | | title: "错误", |
| | | content: "提交失败,请重试", |
| | | confirmText: "确定", |
| | | showCancel: false |
| | | }); |
| | | }); |
| | | }, |
| | | |
| | | removeXJ() { |
| | | if (this.formData.id) { |
| | | this.$post({ |
| | | url: "/RKJ/removeXJ", |
| | | data: { |
| | | id: this.formData.id |
| | | } |
| | | }).then(res => { |
| | | if (res.data.tbBillList > 0) { |
| | | this.$showMessage("删除成功"); |
| | | //关闭当前页面,返回上一页面或多级页面 |
| | | uni.navigateBack(); |
| | | } else { |
| | | this.$showMessage("删除失败"); |
| | | } |
| | | }); |
| | | } else { |
| | | this.$showMessage("请先选择检验单号"); |
| | | } |
| | | }, |
| | | getItem() { |
| | | |
| | | if (!this.formData.billNo) { |
| | | this.$showMessage("请选择送检批次号"); |
| | | return; |
| | | } |
| | | |
| | | if (this.isSubmit) { |
| | | this.$showMessage("此物料无启用的检验项目,请维护!"); |
| | | return; |
| | | } |
| | | |
| | | this.$post({ |
| | | url: "/RKJ/save", |
| | | data: { |
| | | from: this.formData, |
| | | userNo: this.$loginInfo.account, |
| | | //moidNum: this.formData.moidNum |
| | | items: this.tableData |
| | | } |
| | | }).then(res => { |
| | | this.formData.id = res.data.tbBillList; |
| | | this.$showMessage("生成检验项目成功"); |
| | | this.init(); |
| | | this.isUpdate = false; |
| | | }); |
| | | }, |
| | | //生产线别选择并初始话工单号 |
| | | onDaa020Change(event) { |
| | | //获取生产线别的下标地址 |
| | | this.formData.lineName = event; |
| | | |
| | | this.lineNo = this.lineList[this.DAA020List.indexOf(event)].lineNo; |
| | | |
| | | this.formData.line = this.lineNo; |
| | | |
| | | this.$post({ |
| | | url: "/RKJ/getDaa001", |
| | | data: { |
| | | lineNo: this.lineNo |
| | | } |
| | | }).then(res => { |
| | | this.BillNoList = res.data.tbBillList; |
| | | this.DAA001List = res.data.tbBillList.map(s => s.billNo); |
| | | |
| | | this.formData.billNo = ""; |
| | | this.formData.mocode = ""; |
| | | this.formData.boardModel = ""; |
| | | this.formData.taskNo = ""; |
| | | this.formData.itemNo = ""; |
| | | this.formData.boardName = ""; |
| | | this.formData.quantity = ""; |
| | | this.tableData = []; |
| | | }) |
| | | }, |
| | | //选取工单填充物料号和其他信息 |
| | | onDaa001Change(e) { |
| | | |
| | | this.formData.billNo = e; |
| | | |
| | | let data = this.BillNoList[this.DAA001List.indexOf(e)]; |
| | | |
| | | //当返回的结果集为空时置空原有的值 |
| | | if (!data) { |
| | | this.formData.billNo = ""; |
| | | this.formData.mocode = ""; |
| | | this.formData.boardModel = ""; |
| | | this.formData.taskNo = ""; |
| | | this.formData.itemNo = ""; |
| | | this.formData.boardName = ""; |
| | | this.formData.quantity = ""; |
| | | this.tableData = []; |
| | | return; |
| | | } |
| | | //不为空时赋值 |
| | | this.formData.billNo = data.billNo; |
| | | this.formData.mocode = data.mocode; |
| | | this.formData.boardModel = data.boardModel; |
| | | this.formData.taskNo = data.taskNo; |
| | | this.formData.itemNo = data.itemNo; |
| | | this.formData.boardName = data.boardName; |
| | | this.formData.quantity = data.quantity; |
| | | |
| | | |
| | | this.$post({ |
| | | url: "/RKJ/setJYItem", |
| | | data: { |
| | | itemId: this.formData.itemId, |
| | | quantity: this.formData.quantity |
| | | } |
| | | }).then(res => { |
| | | this.tableData = res.data.tbBillList; |
| | | if (this.tableData.length === 0) { |
| | | this.$showMessage("该物料没有检验项目"); |
| | | this.isSubmit = true; |
| | | this.tableData = []; |
| | | } else { |
| | | this.isSubmit = false; |
| | | } |
| | | }); |
| | | }, |
| | | // removeXJ方法已移除 - 不再支持删除单据 |
| | | // getItem方法已移除 - 不再支持创建检验单 |
| | | // onDaa020Change方法已移除 - 不再支持编辑功能 |
| | | // onDaa001Change方法已移除 - 不再支持编辑功能 |
| | | init() { |
| | | let userName = this.$loginInfo.account; |
| | | |
| | | this.$post({ |
| | | url: "/RKJ/getPage", |
| | | url: "/RKJ/GetPage", |
| | | data: { |
| | | id: this.formData.id, |
| | | pageIndex: 1, |
| | |
| | | pid: this.formData.id |
| | | } |
| | | }).then(res1 => { |
| | | |
| | | let tableData = res1.data.tbBillList |
| | | |
| | | //当已检验个数都不为空时按照检测结构排序 |
| | |
| | | }); |
| | | this.tableData = tableData; |
| | | |
| | | if (this.tableData.length === 0) { |
| | | this.isShowTable = true; // 无检验项目,显示获取按钮 |
| | | } else { |
| | | this.isShowTable = false; // 有检验项目,显示表格 |
| | | } |
| | | // 直接显示表格,不再使用isShowTable控制 |
| | | |
| | | // 为每一项添加current属性,表示是否可编辑 |
| | | this.tableData.forEach((item, index) => { |
| | |
| | | }); |
| | | }, |
| | | saveRemarks() { |
| | | this.showPopup = !this.showPopup; |
| | | this.remarks = this.formData.remarks; |
| | | this.showPopup = true; |
| | | this.remarks = this.formData.remarks || ''; |
| | | }, |
| | | |
| | | // 关闭弹窗 |
| | | closePopup() { |
| | | this.showPopup = false; |
| | | this.remarks = ''; |
| | | }, |
| | | edit() { |
| | | if (this.remarks) { |
| | | //saveRemarksGid |
| | | this.$post({ |
| | | url: "/RKJ/saveRemarksGid", |
| | | data: { |
| | | gid: this.formData.id, |
| | | remarks: this.remarks |
| | | } |
| | | }).then(res => { |
| | | if (res.data.tbBillList > 0) { |
| | | this.formData.remarks = this.remarks; |
| | | this.showPopup = !this.showPopup; |
| | | this.$showMessage("保存成功"); |
| | | } |
| | | }) |
| | | } else { |
| | | // 允许清空描述 |
| | | this.$post({ |
| | | url: "/RKJ/saveRemarksGid", |
| | | data: { |
| | | gid: this.formData.id, |
| | | remarks: '', |
| | | releaseNo: this.formData.releaseNo |
| | | } |
| | | }).then(res => { |
| | | if (res.data.tbBillList > 0) { |
| | | this.formData.remarks = ''; |
| | | this.showPopup = !this.showPopup; |
| | | this.$showMessage("保存成功"); |
| | | } |
| | | }) |
| | | } |
| | | }, |
| | | getTable() { |
| | | // 先关闭弹窗 |
| | | this.showPopup = false; |
| | | |
| | | // 保存描述 |
| | | this.$post({ |
| | | url: "/RKJ/setJYItem", |
| | | data: { |
| | | //itemId: this.formData.itemId, |
| | | itemNo: this.formData.itemNo, |
| | | quantity: this.formData.quantity |
| | | } |
| | | }).then(res => { |
| | | |
| | | this.tableData = res.data.tbBillList; |
| | | |
| | | if (this.tableData.length === 0) { |
| | | this.$showMessage("该物料条码没有检验项目"); |
| | | this.isSubmit = true; |
| | | this.tableData = []; |
| | | this.isShowTable = true; // 保持为true,显示按钮,因为没有检验项目 |
| | | this.isUpdate = false; |
| | | } else { |
| | | this.isSubmit = false; |
| | | this.isShowTable = false; // 设为false,以显示表格,因为有检验项目 |
| | | this.isUpdate = true; |
| | | } |
| | | }); |
| | | }, |
| | | saveTable() { |
| | | if (this.tableData.length === 0) { |
| | | return; |
| | | } |
| | | this.$post({ |
| | | url: "/RKJ/saveItem", |
| | | url: "/RKJ/saveRemarksGid", |
| | | data: { |
| | | gid: this.formData.id, |
| | | items: this.tableData, |
| | | remarks: this.remarks || '', |
| | | releaseNo: this.formData.releaseNo |
| | | } |
| | | }).then(res => { |
| | | if (res.status === 0 && res.data.affectedRows > 0) { |
| | | this.$showMessage("保存成功"); |
| | | // 刷新表单数据 |
| | | this.refreshFormData(); |
| | | } else { |
| | | this.$showMessage("保存失败"); |
| | | } |
| | | }).catch(error => { |
| | | this.$showMessage("保存失败,请重试"); |
| | | }); |
| | | }, |
| | | |
| | | // 刷新表单数据 |
| | | refreshFormData() { |
| | | // 只刷新主表单数据,不重新加载检验项目 |
| | | this.$post({ |
| | | url: "/RKJ/GetPage", |
| | | data: { |
| | | id: this.formData.id, |
| | | pageIndex: 1, |
| | | limit: 1, |
| | | } |
| | | }).then(res => { |
| | | let data = res.data.tbBillList[0]; |
| | | if (data) { |
| | | this.formData = data; |
| | | } |
| | | }).catch(error => { |
| | | console.error('刷新表单数据失败:', error); |
| | | }); |
| | | }, |
| | | // 获取检验项目 |
| | | generateInspectionItems() { |
| | | this.$post({ |
| | | url: "/RKJ/GenUpdateRKJ", |
| | | data: { |
| | | id: this.formData.id, |
| | | no: this.formData.billNo, |
| | | userNo: this.$loginInfo.account |
| | | } |
| | | }).then(res => { |
| | | this.formData.id = res.data.tbBillList; |
| | | this.isShowTable = false; // 确保表格显示 |
| | | this.isUpdate = false; |
| | | this.init(); |
| | | }) |
| | | if (res.status === 0) { |
| | | this.$showMessage("生成/获取检验项目成功"); |
| | | // 成功后刷新检验项目 |
| | | this.$post({ |
| | | url: "/RKJ/getItems", |
| | | data: { pid: this.formData.id } |
| | | }).then(r => { |
| | | this.tableData = r.data.tbBillList || []; |
| | | }); |
| | | } else { |
| | | this.$showMessage(res.message || "生成失败"); |
| | | } |
| | | }).catch(error => { |
| | | this.$showMessage("网络错误,请重试"); |
| | | }); |
| | | }, |
| | | // getTable和saveTable方法已移除 - 不再支持创建检验项目 |
| | | }, |
| | | onShow() { |
| | | //每次进入页面都会执行的方法 |
| | |
| | | background-color: #2980b9; |
| | | } |
| | | |
| | | .white-btn { |
| | | background-color: white; |
| | | color: #2c3e50; |
| | | border: 2px solid #3498db; |
| | | } |
| | | |
| | | .white-btn:hover { |
| | | background-color: #f8f9fa; |
| | | border-color: #2980b9; |
| | | } |
| | | |
| | | .secondary-btn { |
| | | background-color: #ecf0f1; |
| | | color: #7f8c8d; |
| | |
| | | /* 水印样式 */ |
| | | .watermark { |
| | | position: absolute; |
| | | font-size: 32px; |
| | | font-size: 28px; |
| | | font-weight: bold; |
| | | opacity: 0.4; |
| | | opacity: 0.3; |
| | | z-index: 3; |
| | | pointer-events: none; |
| | | bottom: 8px; |
| | | right: 8px; |
| | | transform: rotate(-15deg); |
| | | transform-origin: bottom right; |
| | | top: 50%; |
| | | right: 12px; |
| | | transform: translateY(-50%) rotate(-15deg); |
| | | transform-origin: center; |
| | | text-shadow: 1px 1px 2px rgba(255, 255, 255, 0.8); |
| | | min-width: 60px; |
| | | text-align: center; |
| | |
| | | |
| | | /* 移动端水印样式调整 */ |
| | | .watermark { |
| | | font-size: 24px; |
| | | bottom: 4px; |
| | | right: 4px; |
| | | font-size: 20px; |
| | | right: 8px; |
| | | } |
| | | |
| | | /* 移动端表格头部统计 */ |
| | |
| | | /* 平板设备样式 */ |
| | | @media (min-width: 501px) and (max-width: 768px) { |
| | | .watermark { |
| | | font-size: 28px; |
| | | bottom: 6px; |
| | | right: 6px; |
| | | font-size: 24px; |
| | | right: 10px; |
| | | } |
| | | |
| | | .inspection-table th, |
| | |
| | | } |
| | | } |
| | | |
| | | /* 空状态样式 */ |
| | | .empty-state { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | padding: 60px 20px; |
| | | text-align: center; |
| | | background-color: #fafafa; |
| | | border-radius: 8px; |
| | | margin: 20px 0; |
| | | } |
| | | |
| | | .empty-icon { |
| | | font-size: 48px; |
| | | margin-bottom: 16px; |
| | | opacity: 0.6; |
| | | } |
| | | |
| | | .empty-text { |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | color: #666; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .empty-desc { |
| | | font-size: 14px; |
| | | color: #999; |
| | | line-height: 1.5; |
| | | } |
| | | |
| | | /* 大屏设备优化 */ |
| | | @media (min-width: 1200px) { |
| | | .inspection-table { |
| | |
| | | } |
| | | |
| | | .watermark { |
| | | font-size: 36px; |
| | | bottom: 10px; |
| | | right: 10px; |
| | | font-size: 32px; |
| | | right: 16px; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | </view> |
| | | |
| | | <view class="filter-controls" style="margin-bottom: 5px;"> |
| | | <view class="dropdown-filter"> |
| | | <picker @change="onOptionsChange" :value="optionsIndex" :range="options"> |
| | | <view class="picker">{{options[optionsIndex]}}</view> |
| | | </picker> |
| | | </view> |
| | | <view class="search-container"> |
| | | <input class="search-input" v-model="searchValue" placeholder="请输入检验单号或物料编码" |
| | | <input class="search-input" v-model="searchValue" :placeholder="'请输入'+options[optionsIndex]" |
| | | @confirm="handleSearch" /> |
| | | <button class="search-button" @click="handleSearch">搜索</button> |
| | | </view> |
| | |
| | | @click="navigateToDetail(item)"> |
| | | <view class="card-header"> |
| | | <view class="card-title">检验单号: {{item.releaseNo}}</view> |
| | | <view class="status" :class="{'status-pending': current === 0, 'status-pass': item.fcheckResu === '合格', 'status-fail': item.fcheckResu === '不合格'}"> |
| | | {{current === 0 ? '未提交' : (item.fcheckResu ? item.fcheckResu : '已提交')}} |
| | | <view class="status" :class="{'status-pending': item.fsubmit === 0 || item.fsubmit == null, 'status-pass': item.fsubmit === 1 && item.fcheckResu === '合格', 'status-fail': item.fsubmit === 1 && item.fcheckResu === '不合格'}"> |
| | | {{(item.fsubmit === 0 || item.fsubmit == null) ? '未提交' : (item.fcheckResu ? item.fcheckResu : '已提交')}} |
| | | </view> |
| | | </view> |
| | | |
| | |
| | | </view> |
| | | |
| | | <view class="card-actions"> |
| | | <button class="primary">{{current === 0 ? '继续检验' : '查看详情'}}</button> |
| | | <button class="primary">{{(item.fsubmit === 0 || item.fsubmit == null) ? '继续检验' : '查看详情'}}</button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 添加按钮 --> |
| | | <view class="plus-button" @click="handleFabClick" v-if="current === 0"> |
| | | <view class="plus-icon">+</view> |
| | | </view> |
| | | <!-- 添加按钮已移除 - 不再支持自建单据 --> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | totalCount: 0, |
| | | noData: false, // 没有更多数据了 |
| | | isLoading: false, // 是否正在加载 |
| | | optionsIndex: 0, |
| | | options: ['物料编号', '物料名称', '检验单号'] |
| | | }; |
| | | }, |
| | | onLoad() { |
| | |
| | | this.init(); |
| | | }, |
| | | methods: { |
| | | //搜索选项变化 |
| | | onOptionsChange(e) { |
| | | this.optionsIndex = e.detail.value; |
| | | // 根据选择的选项设置搜索字段 |
| | | const fieldMap = { |
| | | 0: 'itemNo', // 物料编号 |
| | | 1: 'itemName', // 物料名称 |
| | | 2: 'releaseNo' // 检验单号 |
| | | }; |
| | | this.selectedField = fieldMap[this.optionsIndex]; |
| | | }, |
| | | init() { |
| | | let result = "未完成"; |
| | | if (this.current === 1) { |
| | | result = "已完成"; |
| | | let fsubmit = null; |
| | | if (this.current === 0) { |
| | | fsubmit = 0; // 未提交 |
| | | } else if (this.current === 1) { |
| | | fsubmit = 1; // 已提交 |
| | | } |
| | | |
| | | if (this.isLoading) return; // 如果正在加载则不继续执行 |
| | |
| | | |
| | | //页面加载时调用的事件 |
| | | this.$post({ |
| | | url: "/RKJ/getPage", |
| | | url: "/RKJ/GetPage", |
| | | data: { |
| | | pageIndex: this.pageIndex, |
| | | limit: this.limit, |
| | | createUser: this.$loginInfo.account, |
| | | result: result, |
| | | searchValue: this.searchValue |
| | | fsubmit: fsubmit, |
| | | searchValue: this.searchValue, |
| | | SelectedIndex: this.optionsIndex |
| | | } |
| | | }).then(res => { |
| | | if (this.pageIndex === 1) { |
| | |
| | | this.isLoading = false; // 出现错误时结束加载 |
| | | }); |
| | | }, |
| | | handleFabClick() { |
| | | uni.navigateTo({ |
| | | url: 'Add?id' |
| | | }); |
| | | }, |
| | | // handleFabClick方法已移除 - 不再支持自建单据 |
| | | onClickItem(index) { |
| | | if (this.current !== index.currentIndex) { |
| | | this.current = index.currentIndex; |
| | |
| | | }, |
| | | navigateToDetail(item) { |
| | | uni.navigateTo({ |
| | | url: 'Add?id=' + item.id + '&releaseNo=' + item.releaseNo |
| | | url: 'Add?id=' + item.id + '&releaseNo=' + item.releaseNo + '¤t=A' |
| | | }); |
| | | } |
| | | }, |
| | |
| | | font-size: 14px; |
| | | margin: 0; |
| | | } |
| | | |
| | | |
| | | .filter-controls { |
| | | display: flex; |
| | |
| | | opacity: 1; |
| | | } |
| | | |
| | | /* 加号按钮样式 */ |
| | | .plus-button { |
| | | position: fixed; |
| | | bottom: 20px; |
| | | right: 20px; |
| | | width: 60px; |
| | | height: 60px; |
| | | border-radius: 50%; |
| | | background-color: #3498db; |
| | | color: #ffffff; |
| | | text-align: center; |
| | | line-height: 59px; |
| | | font-size: 24px; |
| | | cursor: pointer; |
| | | z-index: 1000; |
| | | box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); |
| | | } |
| | | /* 加号按钮样式已移除 - 不再支持自建单据 */ |
| | | |
| | | /* 响应式设计 */ |
| | | @media (min-width: 768px) { |
| | |
| | | <view class="tabs"> |
| | | <view v-for="(tab, index) in tabs" :key="index" class="tab" :class="{active: currentTab === index}" |
| | | @tap="switchTab(index, tab.id)"> |
| | | <view class="tab-text">{{ tab.projName || tab.fcheckItem || '项目' + (index + 1) }}</view> |
| | | <view class="tab-text">{{ getTabDisplayName(tab, index) }}</view> |
| | | </view> |
| | | </view> |
| | | </scroll-view> |
| | | |
| | | <!-- 加载状态 --> |
| | | <view v-if="loading" class="loading-indicator"> |
| | | <text>加载中...</text> |
| | | </view> |
| | | |
| | | <!-- 错误提示 --> |
| | | <view v-if="errorMessage" class="error-message"> |
| | | <text>{{ errorMessage }}</text> |
| | | <button class="retry-btn" @tap="retryLoad">重试</button> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="tab-content"> |
| | |
| | | <view class="info-label">检验数</view> |
| | | <view class="info-value">{{formData.levelNum}}</view> |
| | | </view> |
| | | <view class="info-item"> |
| | | <view class="info-label">检验标准编码</view> |
| | | <view class="info-value">{{formData.qsCode}}</view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 检验标准 --> |
| | | |
| | | <!-- 结果信息 --> |
| | | <view class="section"> |
| | | <view class="section-header">检验标准</view> |
| | | <view class="section-header">结果信息</view> |
| | | <view class="section-body"> |
| | | <view class="info-grid"> |
| | | |
| | | <view class="info-item"> |
| | | <view class="info-label">检验标准名称</view> |
| | | <view class="info-value">{{formData.qsName}}</view> |
| | | <view class="info-label">不合格数</view> |
| | | <view class="info-value">{{formData.unqualified}}</view> |
| | | </view> |
| | | <view class="info-item"> |
| | | <view class="info-label">检验水平</view> |
| | | <view class="info-value">{{formData.fcheckLevel}}</view> |
| | | </view> |
| | | <view class="info-item"> |
| | | <view class="info-label">接收水平</view> |
| | | <view class="info-value">{{formData.facLevel}}</view> |
| | | <view class="info-label">预览结果</view> |
| | | <view class="info-value" :class="{danger: formData.result === '不合格'}">{{formData.result}}</view> |
| | | </view> |
| | | <view class="info-item" v-if="formData.minValue"> |
| | | <view class="info-label">下限</view> |
| | |
| | | <view class="info-value">{{formData.maxValue}}</view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 结果信息 --> |
| | | <view class="section"> |
| | | <view class="section-header">结果信息</view> |
| | | <view class="section-body"> |
| | | <view class="info-grid"> |
| | | <view class="info-item"> |
| | | <view class="info-label">AC数</view> |
| | | <view class="info-value">{{formData.freQty ? (formData.freQty - 1) : ''}}</view> |
| | | </view> |
| | | <view class="info-item"> |
| | | <view class="info-label">RE数</view> |
| | | <view class="info-value">{{formData.freQty}}</view> |
| | | </view> |
| | | <view class="info-item"> |
| | | <view class="info-label">不合格数</view> |
| | | <view class="info-value">{{formData.unqualified}}</view> |
| | | </view> |
| | | <view class="info-item"> |
| | | <view class="info-label">预览结果</view> |
| | | <view class="info-value" :class="{danger: formData.result === '不合格'}">{{formData.result}}</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view v-if="formData.remarks" class="result-remarks"> |
| | | <view class="info-label">不合格描述</view> |
| | |
| | | <view class="hint-text" v-if="!formData.maxValue || !formData.minValue"> |
| | | <view class="danger">没有最大值和最小值时填写0(未通过检验)或1(通过检验)</view> |
| | | </view> |
| | | |
| | | <!-- 填写检验结果 --> |
| | | <view v-if="current && tableData.length < formData.levelNum" class="input-group input1"> |
| | | <view class="input-wrapper llj-flex-row"> |
| | | <input class="result-input" |
| | | :type="isNumber ? 'number' : 'text'" |
| | | v-model="formData.fcheckResu" |
| | | :placeholder="isNumber ? '请输入检验数值...' : '请输入检验结果...'"/> |
| | | <button class="llj-btn llj-btn-save" @click="submit">保存结果</button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 检验结果录入 --> |
| | | <view class="section"> |
| | | <view class="section-header">检验结果录入</view> |
| | | <view class="section-body"> |
| | | <view class="input-group input1"> |
| | | <view class="input-wrapper"> |
| | | <button class="btn upload-btn" @tap="chooseImage"> |
| | | <uni-icons type="upload" size="16" color="#fff"></uni-icons> |
| | | 上传/查看图片 |
| | | </button> |
| | | <button v-if="this.current" class="btn upload-btn" @tap="saveRemarks"> |
| | | <uni-icons type="compose" size="16" color="#fff"></uni-icons> |
| | | 不合格描述 |
| | | </button> |
| | | <input v-if="(tableData.length < formData.levelNum)" |
| | | v-model="formData.fcheckResu" type="text" class="result-input" |
| | | placeholder="请输入检验结果..." /> |
| | | <button v-if="(tableData.length < formData.levelNum)" |
| | | style="margin: 0px;background-color: #3498db;color:#ffffff ;" |
| | | class="btn primary-btn" @tap="submit">保存结果</button> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 移动端适配的输入区 --> |
| | | <view class="input-group input2"> |
| | | <view class="input-wrapper"> |
| | | <button class="btn upload-btn" @tap="chooseImage"> |
| | | <uni-icons type="upload" size="16" color="#fff"></uni-icons> |
| | | 上传/查看图片 |
| | | </button> |
| | | <button v-if="this.current" class="btn upload-btn" @tap="saveRemarks"> |
| | | <uni-icons type="compose" size="16" color="#fff"></uni-icons> |
| | | 不合格描述 |
| | | </button> |
| | | </view> |
| | | <view class="input-wrapper" style="margin-top: 15px;"> |
| | | <input v-if="(tableData.length < formData.levelNum)" |
| | | v-model="formData.fcheckResu" type="text" class="result-input" |
| | | placeholder="请输入检验结果..." /> |
| | | <button v-if="(tableData.length < formData.levelNum)" |
| | | style="margin: 0px;background-color: #3498db;color:#ffffff ;" |
| | | class="btn primary-btn" @tap="submit">保存结果</button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 结果表格 --> |
| | | <view v-if="tableData.length>0" class="simple-table-container"> |
| | |
| | | </view> |
| | | <view class="simple-data-cell simple-result"> |
| | | <!-- 数字结果样式 --> |
| | | <view v-if="isNumber && !isNaN(parseFloat(item.fstand))" class="simple-number-result"> |
| | | <view class="result-value">{{ item.fstand }}</view> |
| | | <view v-if="isNumber && !isNaN(parseFloat(item.fcheckResu))" class="simple-number-result"> |
| | | <view class="result-value">{{ item.fcheckResu }}</view> |
| | | <view v-if="formData.unitName" class="result-unit">{{ formData.unitName }}</view> |
| | | <view class="result-status" :class="{'pass': isInRange(item.fstand), 'fail': !isInRange(item.fstand)}"> |
| | | {{ isInRange(item.fstand) ? '合格' : '不合格' }} |
| | | <view class="result-status" :class="{'pass': isInRange(item.fcheckResu), 'fail': !isInRange(item.fcheckResu)}"> |
| | | {{ isInRange(item.fcheckResu) ? '合格' : '不合格' }} |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- NG/OK状态样式 --> |
| | | <view v-else class="simple-status-result"> |
| | | <view class="simple-status" :class="{'pass': item.fcheckResu === '1', 'fail': item.fcheckResu !== '1'}"> |
| | | {{ item.fcheckResu === '1' ? '合格' : '不合格' }} |
| | | <view class="simple-status" :class="{'pass': isPassResult(item.fcheckResu), 'fail': !isPassResult(item.fcheckResu)}"> |
| | | {{ isPassResult(item.fcheckResu) ? '合格' : '不合格' }} |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | <form> |
| | | <view class="form-group"> |
| | | <label class="form-label">不合格描述:</label> |
| | | <input class="form-input" type="text" v-model="remarks"/> |
| | | <input class="form-input" type="text" v-model="remarks" placeholder="请输入不合格描述,留空表示清除描述"/> |
| | | </view> |
| | | <view class="popup-buttons"> |
| | | <button class="btn primary-btn" @click="editRemarks">修改</button> |
| | |
| | | remarksPopup: false, |
| | | currentTab: 0, |
| | | tabs: [], |
| | | current: true // 添加current属性,默认为true |
| | | current: true, // 添加current属性,默认为true |
| | | loading: false, // 添加加载状态 |
| | | errorMessage: '' // 添加错误信息 |
| | | } |
| | | }, |
| | | methods: { |
| | | switchTab(index, id) { |
| | | // 验证索引和ID的有效性 |
| | | if (index < 0 || index >= this.tabs.length) { |
| | | console.warn('Invalid tab index:', index); |
| | | return; |
| | | } |
| | | |
| | | if (!id) { |
| | | console.warn('Invalid tab id:', id); |
| | | return; |
| | | } |
| | | |
| | | // 如果点击的是当前标签,不需要切换 |
| | | if (this.currentTab === index && this.id === id) { |
| | | return; |
| | | } |
| | | |
| | | this.currentTab = index; |
| | | this.id = id; |
| | | |
| | | // 清空当前表单数据,避免显示上一个项目的数据 |
| | | this.formData = {}; |
| | | this.tableData = []; |
| | | this.isShowImg = false; |
| | | this.base64Image = ""; |
| | | this.isNumber = false; |
| | | |
| | | // 刷新当前项目的数据 |
| | | this.refreshResult(); |
| | | }, |
| | | |
| | |
| | | }, |
| | | |
| | | editResult(fcheckResu) { |
| | | if (fcheckResu == '1') { |
| | | if (this.isPassResult(fcheckResu)) { |
| | | return "改为不合格"; |
| | | } else { |
| | | return "改为合格"; |
| | |
| | | this.$post({ |
| | | url: "/RKJ/SetQSItemDetail", |
| | | data: { |
| | | pid: this.id, |
| | | gid: this.gid, |
| | | fstand: fstand, |
| | | fcheckResu: this.formData.fcheckResu, |
| | | isPass: isPass, // 添加合格状态 |
| | | updateBy: this.formData.updater, |
| | | Pid: this.id, |
| | | Gid: this.gid, |
| | | Fstand: fstand, |
| | | FcheckResu: this.formData.fcheckResu, |
| | | IsPass: isPass, // 添加合格状态 |
| | | UpdateBy: this.formData.updater, |
| | | count: count |
| | | } |
| | | }).then(res => { |
| | |
| | | this.base64Image = 'data:image/jpeg;base64,' + this.formData.imageData; |
| | | } |
| | | |
| | | //maxValue minValue standardValue |
| | | if (this.formData.maxValue && this.formData.minValue && this.formData.standardValue) { |
| | | //maxValue minValue 只要有上下限就按数字类型处理 |
| | | if (this.formData.maxValue && this.formData.minValue) { |
| | | this.isNumber = true; |
| | | } |
| | | |
| | |
| | | url: "/RKJ/UpdateQSItemDetail", |
| | | data: { |
| | | id: this.editData.id, |
| | | pid: this.id, |
| | | gid: this.gid, |
| | | fstand: fstand, |
| | | fcheckResu: this.editData.fcheckResu, |
| | | isPass: isPass, // 添加合格状态 |
| | | updateBy: this.editData.updater, |
| | | Pid: this.id, |
| | | Gid: this.gid, |
| | | Fstand: fstand, |
| | | FcheckResu: this.editData.fcheckResu, |
| | | IsPass: isPass, // 添加合格状态 |
| | | UpdateBy: this.editData.updater, |
| | | } |
| | | }).then(res => { |
| | | this.showPopup = !this.showPopup; |
| | |
| | | let fstand = "√"; |
| | | let fcheckResu = 1; |
| | | |
| | | if (item.fcheckResu == '1') { |
| | | if (this.isPassResult(item.fcheckResu)) { |
| | | fstand = "×"; |
| | | fcheckResu = 0; |
| | | } |
| | |
| | | url: "/RKJ/UpdateQSItemDetail", |
| | | data: { |
| | | id: item.id, |
| | | pid: item.pid, |
| | | gid: item.gid, |
| | | fstand: fstand, |
| | | fcheckResu: fcheckResu, |
| | | updateBy: this.$loginInfo.account, |
| | | Pid: item.pid, |
| | | Gid: item.gid, |
| | | Fstand: fstand, |
| | | FcheckResu: fcheckResu, |
| | | UpdateBy: this.$loginInfo.account, |
| | | } |
| | | }).then(res => { |
| | | this.$showMessage("修改成功"); |
| | |
| | | this.remarks = this.formData.remarks; |
| | | }, |
| | | editRemarks() { |
| | | if (this.remarks) { |
| | | //saveRemarksGid |
| | | this.$post({ |
| | | url: "/RKJ/saveRemarksPid", |
| | | data: { |
| | | pid: this.formData.id, |
| | | remarks: this.remarks |
| | | } |
| | | }).then(res => { |
| | | if(res.data.tbBillList > 0){ |
| | | this.formData.remarks = this.remarks; |
| | | this.remarksPopup = !this.remarksPopup; |
| | | this.$showMessage("保存成功"); |
| | | } |
| | | }) |
| | | } |
| | | // 允许留空,留空代表清除描述 |
| | | this.$post({ |
| | | url: "/RKJ/saveRemarksPid", |
| | | data: { |
| | | Pid: this.formData.id, |
| | | remarks: this.remarks || "" // 留空时传递空字符串 |
| | | } |
| | | }).then(res => { |
| | | if(res.data.tbBillList > 0){ |
| | | this.formData.remarks = this.remarks || ""; // 更新本地数据 |
| | | this.remarksPopup = !this.remarksPopup; |
| | | this.$showMessage(this.remarks ? "保存成功" : "描述已清除"); |
| | | } |
| | | }).catch(error => { |
| | | this.$showMessage("保存失败,请重试"); |
| | | }); |
| | | }, |
| | | // 加载检验项目列表 |
| | | loadTabItems() { |
| | | if (!this.gid) { |
| | | console.warn('gid is empty, cannot load tab items'); |
| | | this.errorMessage = '缺少必要参数,无法加载检验项目'; |
| | | return; |
| | | } |
| | | |
| | | this.loading = true; |
| | | this.errorMessage = ''; |
| | | |
| | | // 使用与Add.vue完全相同的参数格式和调用方式 |
| | | this.$post({ |
| | | url: "/RKJ/getItems", |
| | | data: { |
| | | pid: this.gid, |
| | | pid: this.gid // 与Add.vue中的pid: this.formData.id保持一致 |
| | | } |
| | | }).then(res => { |
| | | if(res.data && res.data.tbBillList) { |
| | | if(res.data && res.data.tbBillList && res.data.tbBillList.length > 0) { |
| | | this.tabs = res.data.tbBillList; |
| | | |
| | | // 按检测结果排序,未完成的排在前面 |
| | | this.tabs.sort((a, b) => { |
| | | if (a.result === '未完成' && b.result !== '未完成') { |
| | |
| | | return 0; |
| | | } |
| | | }); |
| | | |
| | | // 确保当前选中的标签存在 |
| | | if (this.currentTab >= this.tabs.length) { |
| | | this.currentTab = 0; |
| | | } |
| | | |
| | | // 如果当前ID不在标签列表中,更新为第一个标签的ID |
| | | const currentTabExists = this.tabs.some(tab => tab.id === this.id); |
| | | if (!currentTabExists && this.tabs.length > 0) { |
| | | this.id = this.tabs[this.currentTab].id; |
| | | this.refreshResult(); |
| | | } |
| | | } else { |
| | | // 没有项目时至少添加当前项目到标签 |
| | | this.tabs = [{id: this.id, projName: this.formData.projName || '当前项目'}]; |
| | | this.currentTab = 0; |
| | | } |
| | | this.loading = false; |
| | | }).catch(error => { |
| | | console.error('加载检验项目列表失败:', error); |
| | | this.loading = false; |
| | | this.errorMessage = '加载检验项目失败,请检查网络连接'; |
| | | // 发生错误时至少添加当前项目到标签 |
| | | this.tabs = [{id: this.id, projName: this.formData.projName || '当前项目'}]; |
| | | this.currentTab = 0; |
| | | }) |
| | | }, |
| | | // 判断数字是否在范围内 |
| | |
| | | const numValue = parseFloat(value); |
| | | return numValue >= parseFloat(this.formData.minValue) && |
| | | numValue <= parseFloat(this.formData.maxValue); |
| | | }, |
| | | |
| | | // 判断检验结果是否合格 |
| | | isPassResult(fcheckResu) { |
| | | // 支持多种合格状态的表示方式 |
| | | if (fcheckResu === '1' || fcheckResu === 'OK' || fcheckResu === 'ok' || fcheckResu === '合格') { |
| | | return true; |
| | | } |
| | | return false; |
| | | }, |
| | | // 获取数字结果的样式类 |
| | | getNumberResultClass(value) { |
| | |
| | | uni.navigateTo({ |
| | | url: 'ImageItem?id=' + this.formData.id |
| | | }); |
| | | }, |
| | | |
| | | // 获取标签显示名称 |
| | | getTabDisplayName(tab, index) { |
| | | // 优先使用项目名称 |
| | | if (tab.projName && tab.projName.trim()) { |
| | | return tab.projName.trim(); |
| | | } |
| | | // 其次使用检验项目名称 |
| | | if (tab.fcheckItem && tab.fcheckItem.trim()) { |
| | | return tab.fcheckItem.trim(); |
| | | } |
| | | // 最后使用默认名称 |
| | | return '项目' + (index + 1); |
| | | }, |
| | | |
| | | // 重试加载 |
| | | retryLoad() { |
| | | this.errorMessage = ''; |
| | | this.loadTabItems(); |
| | | } |
| | | }, |
| | | onLoad(options) { |
| | |
| | | background-color: $bg-color; |
| | | border-bottom: 1px solid $border-color; |
| | | position: relative; |
| | | } |
| | | |
| | | .loading-indicator { |
| | | padding: 10px; |
| | | text-align: center; |
| | | color: #666; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .error-message { |
| | | padding: 10px; |
| | | background-color: #fef0f0; |
| | | border: 1px solid #fbc4c4; |
| | | border-radius: 4px; |
| | | margin: 10px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | |
| | | text { |
| | | color: #f56c6c; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .retry-btn { |
| | | padding: 4px 12px; |
| | | background-color: #f56c6c; |
| | | color: white; |
| | | border: none; |
| | | border-radius: 4px; |
| | | font-size: 12px; |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | |
| | | .tabs-scroll { |
| | |
| | | word-break: break-word; |
| | | display: -webkit-box; |
| | | -webkit-line-clamp: 2; |
| | | line-clamp: 2; |
| | | -webkit-box-orient: vertical; |
| | | overflow: hidden; |
| | | font-size: 14px; |
| | |
| | | |
| | | .input-group { |
| | | margin: 16px 0; |
| | | |
| | | .input-wrapper { |
| | | display: flex; |
| | | gap: 12px; |
| | | |
| | | .result-input { |
| | | flex: 1; |
| | | height: 45px; |
| | | padding: 0 12px; |
| | | border: 1px solid $border-color; |
| | | border-radius: 4px; |
| | | font-size: 14px; |
| | | box-sizing: border-box; |
| | | min-width: 120px; |
| | | -webkit-appearance: none; /* 移除移动端默认样式 */ |
| | | -moz-appearance: none; |
| | | appearance: none; |
| | | } |
| | | |
| | | .upload-btn { |
| | | background-color: #909399; |
| | | color: #fff; |
| | | padding: 0 10px; |
| | | margin: 0; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .input-wrapper { |
| | | |
| | | /* llj按钮样式 - 与SJ和XJ保持一致 */ |
| | | .llj-flex-row { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12px; |
| | | flex-wrap: wrap; |
| | | width: 100%; |
| | | } |
| | | |
| | | .result-input { |
| | | flex: 1; |
| | | |
| | | .llj-btn { |
| | | display: flex; |
| | | align-items: center; |
| | | border: none; |
| | | border-radius: 24px; |
| | | font-size: 16px; |
| | | font-weight: 500; |
| | | height: 45px; |
| | | padding: 0 12px; |
| | | border: 1px solid var(--border-color); |
| | | border-radius: 6px; |
| | | font-size: 14px; |
| | | transition: border-color 0.3s ease, box-shadow 0.3s ease; |
| | | min-width: 0; /* 防止flex子项溢出 */ |
| | | line-height: 1; |
| | | padding: 0 28px; |
| | | margin: 0; |
| | | cursor: pointer; |
| | | transition: all 0.3s ease; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); |
| | | -webkit-appearance: none; |
| | | -moz-appearance: none; |
| | | appearance: none; |
| | | user-select: none; |
| | | touch-action: manipulation; |
| | | } |
| | | |
| | | .result-input:focus { |
| | | outline: none; |
| | | border-color: #409EFF; |
| | | box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2); |
| | | |
| | | .llj-btn-save { |
| | | background: linear-gradient(90deg, #27ae60 0%, #43e97b 100%); |
| | | color: #fff; |
| | | margin-right: 12px; |
| | | } |
| | | |
| | | .llj-btn-save:active { |
| | | background: linear-gradient(90deg, #43e97b 0%, #27ae60 100%); |
| | | } |
| | | |
| | | .llj-btn, .llj-btn-save { |
| | | height: 45px; |
| | | line-height: 1; |
| | | padding: 0 24px; |
| | | min-width: 90px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | .btn { |
| | |
| | | display: none; |
| | | } |
| | | |
| | | .input-group { |
| | | margin: 16px 0; |
| | | |
| | | .input-wrapper { |
| | | display: flex; |
| | | gap: 12px; |
| | | |
| | | .result-input { |
| | | flex: 1; |
| | | height: 45px; |
| | | padding: 0 12px; |
| | | border: 1px solid $border-color; |
| | | border-radius: 4px; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .upload-btn { |
| | | background-color: #909399; |
| | | color: #fff; |
| | | padding: 0 10px; |
| | | margin: 0; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .result-preview { |
| | | .info-label { |
| | |
| | | } |
| | | } |
| | | |
| | | /* 移动端按钮和输入框样式调整 */ |
| | | @media (max-width: 768px) { |
| | | .llj-btn { |
| | | font-size: 14px; |
| | | padding: 0 20px; |
| | | height: 40px; |
| | | border-radius: 20px; |
| | | } |
| | | |
| | | .llj-btn, .llj-btn-save { |
| | | height: 40px; |
| | | padding: 0 20px; |
| | | min-width: 80px; |
| | | } |
| | | |
| | | .result-input { |
| | | height: 40px; |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | |
| | | @media (max-width: 500px) { |
| | | .llj-btn { |
| | | -webkit-tap-highlight-color: transparent; |
| | | -webkit-touch-callout: none; |
| | | -webkit-user-select: none; |
| | | -khtml-user-select: none; |
| | | -moz-user-select: none; |
| | | -ms-user-select: none; |
| | | user-select: none; |
| | | } |
| | | |
| | | .btn { |
| | | height: 40px; |
| | | padding: 0 20px; |
| | | min-width: 80px; |
| | | } |
| | | |
| | | .result-input { |
| | | height: 40px; |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | |
| | | /* 移动端按钮点击效果优化 */ |
| | | .llj-btn:active { |
| | | transform: scale(0.98); |
| | | transition: transform 0.1s ease; |
| | | } |
| | | |
| | | </style> |
| | |
| | | <view class="material-info"> |
| | | <view class="info-block"> |
| | | <view class="info-label">生产线别:</view> |
| | | <view class="info-value" v-if="!isUpdate">{{formData.line}}</view> |
| | | <superwei-combox v-else :candidates="DAA020List" placeholder="请选择或输入" |
| | | v-model="formData.line" @select="onDaa020Change" class="info-picker-input"></superwei-combox> |
| | | <view class="info-value">{{formData.line}}</view> |
| | | </view> |
| | | <view class="info-block"> |
| | | <view class="info-label">物料编码:</view> |
| | | <view class="info-value" v-if="!isUpdate">{{formData.itemNo}}</view> |
| | | <superwei-combox v-else :candidates="boardItems" placeholder="请选择或输入" v-model="formData.itemNo" |
| | | :isJSON="true" keyName="itemName" @select="onItemChange" class="info-picker-input"></superwei-combox> |
| | | <view class="info-value">{{formData.itemNo}}</view> |
| | | </view> |
| | | <view class="info-block"> |
| | | <view class="info-label">计划编号:</view> |
| | | <view class="info-value" v-if="!isUpdate">{{formData.daa001}}</view> |
| | | <picker v-else class="info-picker" name="selector" :range="DAA001List" |
| | | @change="onDaa001Change"> |
| | | <view>{{ DAA001List[DAA001Index] }}</view> |
| | | </picker> |
| | | <view class="info-value">{{formData.daa001}}</view> |
| | | </view> |
| | | <view class="info-block"> |
| | | <view class="info-label">产品名称:</view> |
| | |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 操作按钮区 --> |
| | | <view class="action-buttons" v-if="isUpdate"> |
| | | <button class="action-btn secondary" @click="getTable">获取检验项目</button> |
| | | </view> |
| | | |
| | | <!-- 检验项目表格 --> |
| | | <view class="inspection-table" v-if="tableData.length > 0"> |
| | | <table> |
| | | <view class="inspection-table"> |
| | | <!-- 表格头部统计信息 --> |
| | | <view class="table-header-stats"> |
| | | <view class="stats-left"> |
| | | <view class="stats-title">检验项目清单</view> |
| | | <view class="stats-subtitle">共 {{tableData.length}} 个检验项目</view> |
| | | <view class="submit-status" :class="{'can-submit': canSubmit, 'cannot-submit': !canSubmit}"> |
| | | {{canSubmit ? '✓ 可以提交' : '✗ 检验未完成,无法提交'}} |
| | | </view> |
| | | </view> |
| | | <view class="stats-right"> |
| | | <view class="stat-item passed"> |
| | | <span class="stat-count">{{getPassedCount()}}</span> |
| | | <span class="stat-label">已合格</span> |
| | | </view> |
| | | <view class="stat-item failed"> |
| | | <span class="stat-count">{{getFailedCount()}}</span> |
| | | <span class="stat-label">不合格</span> |
| | | </view> |
| | | <view class="stat-item pending"> |
| | | <span class="stat-count">{{getPendingCount()}}</span> |
| | | <span class="stat-label">待检验</span> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <table v-if="tableData.length > 0"> |
| | | <thead> |
| | | <tr> |
| | | <th width="15%" style="text-align: center;">检验项目</th> |
| | |
| | | 'status-rejected': item.result=='不合格', |
| | | 'status-pending': item.result=='未完成' |
| | | }"></span> |
| | | {{ item.projName }} |
| | | <span>{{ item.projName }}</span> |
| | | </view> |
| | | </td> |
| | | <td> |
| | | <view v-if="item.result=='合格'" class="watermark approved">合格</view> |
| | | <view v-if="item.result=='不合格'" class="watermark rejected">不合格</view> |
| | | <view v-if="item.result=='未完成'" class="watermark pending">待确认</view> |
| | | <view v-if="item.result=='合格'" class="watermark approved"> |
| | | 合格 |
| | | </view> |
| | | <view v-if="item.result=='不合格'" class="watermark rejected"> |
| | | 不合格 |
| | | </view> |
| | | <view v-if="item.result=='未完成'" class="watermark pending"> |
| | | 待检验 |
| | | </view> |
| | | <view class="description-text">{{ item.itemMod }}</view> |
| | | </td> |
| | | <td> |
| | | <button v-if="item.isCheck < item.levelNum" class="record-btn record-btn-fill" @click="toDetail(item, index)"> |
| | | 填写 ({{ item.isCheck }}/{{ item.levelNum }}) |
| | | </button> |
| | | <button v-else class="record-btn record-btn-view" @click="toDetail(item, index)"> |
| | | 查看 ({{ item.isCheck }}/{{ item.levelNum }}) |
| | | <td> |
| | | <button class="record-btn" :class="{ |
| | | 'record-btn-fill': item.isCheck >= item.levelNum, |
| | | 'record-btn-view': item.isCheck < item.levelNum |
| | | }" @click="toDetail(item, index)"> |
| | | {{item.isCheck >= item.levelNum ? '查看' : '填写'}} |
| | | </button> |
| | | </td> |
| | | </tr> |
| | | </tbody> |
| | | </table> |
| | | <!-- 空状态显示 --> |
| | | <view v-else class="empty-state"> |
| | | <view class="empty-icon">📋</view> |
| | | <view class="empty-text">暂无检验项目</view> |
| | | <view class="empty-desc">该检验单还没有检验项目</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 操作按钮区 --> |
| | | <view class="action-buttons"> |
| | | <button class="action-btn primary" v-if="isUpdate && !isShowTable" @click="save">创建检验单并生成部分默认值</button> |
| | | <button class="action-btn secondary" v-if="!isUpdate && !isShowTable" @click="toImage">上传/查看图片</button> |
| | | <button class="action-btn secondary" v-if="!isUpdate && !isShowTable" @click="refreshItems">刷新检验项目</button> |
| | | <button class="action-btn success" v-if="!isUpdate && !isShowTable" @click="submit">提交检验</button> |
| | | <!-- <button class="action-btn danger" v-if="!isUpdate && !formData.statusUser && !isShowTable" @click="removeXJ">删除单据</button> --> |
| | | <button class="action-btn secondary" v-if="!isUpdate && !isShowTable" @click="saveRemarks">添加不合格描述</button> |
| | | <!-- <button class="action-btn success" v-if="!isUpdate && !isShowTable" @click="submit">审核单据</button> --> |
| | | <button class="action-btn secondary" v-if="isShowTable" @click="getTable">获取检验项目</button> |
| | | <button class="action-btn primary" v-if="isShowTable && isUpdate" @click="saveTable">生成检验项目</button> |
| | | <button class="secondary-btn" v-if="!isSubmitted" @click="genByProc">获取检验项目</button> |
| | | <button class="secondary-btn" @click="toImage">上传/查看图片</button> |
| | | <button class="secondary-btn" v-if="!isSubmitted" @click="saveRemarks">添加不合格描述</button> |
| | | <button class="primary-btn" v-if="!isSubmitted && canSubmit" @click="submit">提交检验</button> |
| | | <button class="primary-btn disabled" v-if="!isSubmitted && !canSubmit" disabled>提交检验</button> |
| | | </view> |
| | | |
| | | <!-- 弹窗 --> |
| | |
| | | itemId: "", |
| | | }, |
| | | |
| | | DAA020List: [], |
| | | |
| | | DAA001List: [], |
| | | schemeResult: [], |
| | | DAA001Index: -1, |
| | | |
| | | ItemList: [], |
| | | |
| | | boardItems: [], |
| | | |
| | | womdaaList: [], |
| | | |
| | | tableData: [], |
| | | |
| | | isSubmit: true, |
| | | |
| | | isUpdate: true, |
| | | |
| | | isShowTable: false, |
| | | |
| | | remarks: "", |
| | | remarksPopup: false, |
| | | |
| | | }; |
| | | }, |
| | | computed: { |
| | | isSubmitted() { |
| | | const val = this.formData && (this.formData.Fsubmit ?? this.formData.fsubmit ?? this.formData.FSUBMIT ?? this.formData.fSubmit); |
| | | if (val === null || val === undefined || val === '') return false; |
| | | return String(val).trim() === '1' || Number(val) === 1; |
| | | }, |
| | | canSubmit() { |
| | | // 检查是否有检验项目 |
| | | if (!Array.isArray(this.tableData) || this.tableData.length === 0) { |
| | | return false; |
| | | } |
| | | |
| | | // 检查是否所有检验项目都已完成 |
| | | const allCompleted = this.tableData.every(it => { |
| | | const checkedCount = Number(it?.isCheck ?? 0); |
| | | const requiredCount = Number(it?.levelNum ?? 0); |
| | | return checkedCount >= requiredCount; |
| | | }); |
| | | |
| | | // 检查是否所有检验项目都有结果 |
| | | const allHaveResult = this.tableData.every(it => |
| | | it.result && it.result !== '未完成' && it.result !== '未检测' |
| | | ); |
| | | |
| | | return allCompleted && allHaveResult; |
| | | } |
| | | }, |
| | | onLoad(options) { |
| | | //options中包含了url附带的参数 |
| | |
| | | this.formData.billNo = params["billNo"]; |
| | | this.init(); |
| | | } else { |
| | | //初始化检验单号 |
| | | this.$post({ |
| | | url: "/SJ/GetMaxBillNo" |
| | | }).then(res => { |
| | | this.formData.billNo = res.data.tbBillList; |
| | | this.formData.createTime = this.$getDate("yyyy-mm-dd"); |
| | | }); |
| | | |
| | | //产品编码下拉框的初始化 |
| | | this.$post({ |
| | | url: "/XJ/getLineAll" |
| | | }).then(res => { |
| | | this.lineList = res.data.tbBillList; |
| | | this.DAA020List = res.data.tbBillList.map(item => item.lineName); |
| | | this.formData.itemNo = ""; |
| | | this.formData.itemName = ""; |
| | | this.formData.workshopCode = ""; |
| | | this.formData.workshopName = ""; |
| | | this.formData.line = ""; |
| | | this.formData.lineName = ""; |
| | | this.formData.pbaid = null; |
| | | }) |
| | | // 自建单据功能已移除,只允许查看现有单据 |
| | | this.$showMessage("请从列表中选择检验单进行查看"); |
| | | uni.navigateBack(); |
| | | } |
| | | }, |
| | | methods: { |
| | | refreshItems() { |
| | | if (!this.formData.id) { |
| | | this.$showMessage("请先保存检验单"); |
| | | return; |
| | | } |
| | | // 获取合格项目数量 |
| | | getPassedCount() { |
| | | return this.tableData.filter(item => item.result === '合格').length; |
| | | }, |
| | | // 获取不合格项目数量 |
| | | getFailedCount() { |
| | | return this.tableData.filter(item => item.result === '不合格').length; |
| | | }, |
| | | // 获取待检验项目数量 |
| | | getPendingCount() { |
| | | return this.tableData.filter(item => item.result === '未完成').length; |
| | | }, |
| | | genByProc() { |
| | | this.$post({ |
| | | url: "/SJ/GenUpdateSJ", |
| | | data: { |
| | |
| | | } |
| | | }).then(res => { |
| | | if (res.status === 0) { |
| | | this.$showMessage(res.message || "已刷新检验项目"); |
| | | this.init(); |
| | | this.$showMessage("生成/获取检验项目成功"); |
| | | // 成功后刷新检验项目 |
| | | this.$post({ |
| | | url: "/SJ/getQSItems", |
| | | data: { pid: this.formData.id } |
| | | }).then(r => { |
| | | this.tableData = r.data.tbBillList || []; |
| | | }); |
| | | } else { |
| | | this.$showMessage(res.message || "刷新失败"); |
| | | this.$showMessage(res.message || "生成失败"); |
| | | } |
| | | }).catch(err => { |
| | | console.error("刷新检验项目失败:", err); |
| | | this.$showMessage("刷新失败,请稍后重试"); |
| | | }); |
| | | }, |
| | | removeXJ() { |
| | |
| | | }, |
| | | |
| | | submit() { |
| | | // 校验:所有检验项目必须完成 |
| | | const hasIncomplete = this.tableData && this.tableData.some(item => { |
| | | // 允许的完成条件:result 不为 '未完成' 且 已检次数达到要求 |
| | | const resultIncomplete = item.result === '未完成'; |
| | | const countIncomplete = (item.isCheck ?? 0) < (item.levelNum ?? 0); |
| | | return resultIncomplete || countIncomplete; |
| | | // 校验是否有检验项目 |
| | | if (!Array.isArray(this.tableData) || this.tableData.length === 0) { |
| | | this.$showMessage("没有检验项目,无法提交"); |
| | | return; |
| | | } |
| | | |
| | | // 校验检验项目是否全部完成 |
| | | const unfinishedItems = []; |
| | | const hasUnfinished = this.tableData.some(it => { |
| | | const checkedCount = Number(it?.isCheck ?? 0); |
| | | const requiredCount = Number(it?.levelNum ?? 0); |
| | | // 允许提交的前提:已检次数需达到要求次数 |
| | | if (checkedCount < requiredCount) { |
| | | unfinishedItems.push(it.projName); |
| | | return true; |
| | | } |
| | | return false; |
| | | }); |
| | | if (hasIncomplete) { |
| | | this.$showMessage("还有未完成的检验项目,无法提交"); |
| | | |
| | | if (hasUnfinished) { |
| | | const message = unfinishedItems.length > 0 |
| | | ? `以下检验项目未完成,不能提交:\n${unfinishedItems.join('、')}` |
| | | : "存在未完成的检验项目,不能提交"; |
| | | this.$showMessage(message); |
| | | return; |
| | | } |
| | | |
| | | // 校验是否所有检验项目都有结果 |
| | | const itemsWithoutResult = this.tableData.filter(it => |
| | | !it.result || it.result === '未完成' || it.result === '未检测' |
| | | ); |
| | | if (itemsWithoutResult.length > 0) { |
| | | const itemNames = itemsWithoutResult.map(it => it.projName); |
| | | this.$showMessage(`以下检验项目没有检验结果,不能提交:\n${itemNames.join('、')}`); |
| | | return; |
| | | } |
| | | this.$post({ |
| | |
| | | id: this.formData.id |
| | | } |
| | | }).then(res => { |
| | | // 按后端统一返回结构判断 |
| | | //2024-11-28 kyy 校验合格提交增加提示 |
| | | console.log("Response:", res); |
| | | if (res.status === 0) { |
| | | this.$showMessage("成功提交检验"); |
| | | // 使用setTimeout在7秒后隐藏消息 |
| | | setTimeout(() => { |
| | | this.hideCustomMessage(); |
| | | }, 7000); // 7000毫秒等于7秒 |
| | | // 显示成功提示框 |
| | | uni.showModal({ |
| | | title: '提交成功', |
| | | content: '检验单已成功提交!', |
| | | showCancel: false, |
| | | confirmText: '确定', |
| | | confirmColor: '#27ae60', |
| | | success: (modalRes) => { |
| | | if (modalRes.confirm) { |
| | | // 提交成功后刷新当前单据,确保FSUBMIT最新,从而隐藏按钮 |
| | | this.init(); |
| | | } |
| | | } |
| | | }); |
| | | } else { |
| | | this.$showMessage(res.message || "审核失败"); |
| | | // 显示失败提示框 |
| | | uni.showModal({ |
| | | title: '提交失败', |
| | | content: res.message || "审核失败,请重试", |
| | | showCancel: false, |
| | | confirmText: '确定', |
| | | confirmColor: '#e74c3c' |
| | | }); |
| | | } |
| | | }).catch(error => { |
| | | console.error("审核提交失败:", error); |
| | | // 处理审核失败的情况 |
| | | // 处理审核失败的情况,显示错误提示框 |
| | | let errorMessage = "审核失败,请检查检验项目是否完成"; |
| | | if (error.message) { |
| | | this.$showMessage(error.message); |
| | | errorMessage = error.message; |
| | | } else if (error.data && error.data.message) { |
| | | this.$showMessage(error.data.message); |
| | | } else { |
| | | this.$showMessage("审核失败,请检查检验项目是否完成"); |
| | | errorMessage = error.data.message; |
| | | } |
| | | |
| | | uni.showModal({ |
| | | title: '提交失败', |
| | | content: errorMessage, |
| | | showCancel: false, |
| | | confirmText: '确定', |
| | | confirmColor: '#e74c3c' |
| | | }); |
| | | }) |
| | | }, |
| | | |
| | |
| | | } |
| | | }); |
| | | |
| | | if (this.tableData.length <= 0) { |
| | | this.isShowTable = true; |
| | | } |
| | | }).catch(error => { |
| | | console.error("获取检验项目失败:", error); |
| | | this.$showMessage("获取检验项目失败"); |
| | |
| | | }) |
| | | } |
| | | }, |
| | | onDaa020Change(event) { |
| | | //获取生产线别的下标地址 |
| | | //this.formData.line = event; |
| | | |
| | | this.lineNo = this.lineList[this.DAA020List.indexOf(event)].lineNo; |
| | | |
| | | this.formData.line = this.lineNo; |
| | | |
| | | this.$post({ |
| | | url: "/XJ/getBoardItem", |
| | | data: { |
| | | lineNo: this.lineNo |
| | | } |
| | | }).then(res => { |
| | | //填充工单号的数据源 |
| | | this.boardItems = res.data.tbBillList; |
| | | |
| | | this.ItemList = this.boardItems.map(item => item.itemName); |
| | | }) |
| | | |
| | | }, |
| | | onItemChange(event) { |
| | | |
| | | this.formData.itemNo = event.itemNo; |
| | | |
| | | this.$post({ |
| | | url: "/XJ/getDaa001", |
| | | data: { |
| | | daa020: this.lineNo, |
| | | item: this.formData.itemNo |
| | | } |
| | | }).then(res => { |
| | | //填充工单号的数据源 |
| | | this.schemeResult = res.data.tbBillList; |
| | | this.DAA001List = this.schemeResult.map(s => s.daa001); |
| | | //变为默认空值的状态 |
| | | this.DAA001Index = -1; |
| | | this.formData.daa001 = ""; |
| | | }) |
| | | }, |
| | | //选取工单填充物料号和其他信息 |
| | | onDaa001Change(event) { |
| | | this.DAA001Index = event.mp.detail.value; |
| | | |
| | | this.formData.daa001 = this.schemeResult[this.DAA001Index].daa001; |
| | | |
| | | //表单中的部分字段赋值 |
| | | this.$post({ |
| | | url: "/XJ/getItem", |
| | | data: { |
| | | daa001: this.formData.daa001 |
| | | } |
| | | }).then(res => { |
| | | let data = res.data.tbBillList[0]; |
| | | //当返回的结果集为空时置空原有的值 |
| | | if (!data) { |
| | | this.formData.billNo = ""; |
| | | this.formData.taskNo = ""; |
| | | this.formData.itemNo = ""; |
| | | this.tableData = []; |
| | | return; |
| | | } |
| | | //不为空时赋值 |
| | | this.formData.daa001 = data.daa001; |
| | | this.formData.daa003 = data.daa003; |
| | | this.formData.daa004 = data.daa004; |
| | | this.formData.daa008 = data.daa008; |
| | | this.formData.pbaid = data.id; |
| | | |
| | | |
| | | this.$post({ |
| | | url: "/SJ/SetQSItems", |
| | | data: { |
| | | itemId: this.formData.itemNo |
| | | } |
| | | }).then(res => { |
| | | if (res.data.tbBillList.length > 0) { |
| | | this.tableData = res.data.tbBillList; // 在箭头函数中,this 指向外层作用域的 this |
| | | this.isSubmit = false; |
| | | } else { |
| | | this.$showMessage("此物料没有启用的检验项目,请维护!"); |
| | | this.isSubmit = true; |
| | | this.tableData = []; |
| | | } |
| | | }); |
| | | |
| | | }); |
| | | }, |
| | | toDetail(item, index) { |
| | | if (this.isUpdate) { |
| | | uni.showToast({ |
| | | icon: "none", |
| | | title: "请先生成检验项目", |
| | | duration: 2000, |
| | | }); |
| | | } else { |
| | | uni.navigateTo({ |
| | | url: 'detail?id=' + item.id + '&billNo=' + this.formData.billNo + '&gid=' + this.formData |
| | | .id+'&index='+index |
| | | }); |
| | | } |
| | | }, |
| | | getTable() { |
| | | this.$post({ |
| | | url: "/SJ/SetQSItems", |
| | | data: { |
| | | itemId: this.formData.itemNo |
| | | } |
| | | }).then(res => { |
| | | if (res.data.tbBillList.length > 0) { |
| | | this.tableData = res.data.tbBillList; // 在箭头函数中,this 指向外层作用域的 this |
| | | this.isShowTable = true; |
| | | this.isUpdate = true; |
| | | } else { |
| | | this.$showMessage("此物料没有启用的检验项目,请维护!"); |
| | | this.isShowTable = true; |
| | | this.isUpdate = false; |
| | | this.tableData = []; |
| | | } |
| | | uni.navigateTo({ |
| | | url: 'detail?id=' + item.id + '&billNo=' + this.formData.billNo + '&gid=' + this.formData |
| | | .id+'&index='+index |
| | | }); |
| | | }, |
| | | saveTable() { |
| | | if (this.tableData.length === 0) { |
| | | return; |
| | | } |
| | | |
| | | this.$post({ |
| | | url: "/SJ/SaveItem", |
| | | data: { |
| | | gid: this.formData.id, |
| | | items: this.tableData, |
| | | statusUser: this.$loginInfo.account |
| | | } |
| | | }).then(res => { |
| | | this.tableData = res.data.tbBillList.items; |
| | | this.isShowTable = false; |
| | | this.isUpdate = false; |
| | | }) |
| | | }, |
| | | save() { |
| | | |
| | | // if (this.tableData.length === 0) { |
| | | // this.$showMessage(this.formData.itemNo + "物料没有检验项目"); |
| | | // return; |
| | | // } |
| | | |
| | | if (!this.formData.daa001) { |
| | | this.$showMessage("请选择计划编号"); |
| | | return; |
| | | } |
| | | |
| | | this.formData.statusUser = this.$loginInfo.account; |
| | | |
| | | this.$post({ |
| | | url: "/SJ/Save", |
| | | data: { |
| | | from: this.formData, |
| | | items: this.tableData |
| | | } |
| | | }).then(res => { |
| | | this.formData = res.data.tbBillList.result; |
| | | this.tableData = res.data.tbBillList.items; |
| | | this.isUpdate = false; |
| | | }) |
| | | }, |
| | | saveRemarks() { |
| | | this.remarksPopup = !this.remarksPopup; |
| | |
| | | /* 检验项目表格 */ |
| | | .inspection-table { |
| | | margin: 25px 0; |
| | | border-radius: 8px; |
| | | overflow: hidden; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); |
| | | background: #fff; |
| | | } |
| | | |
| | | /* 表格头部统计信息 */ |
| | | .table-header-stats { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 16px 20px; |
| | | background: linear-gradient(135deg, #f8f9fa, #e9ecef); |
| | | border-bottom: 1px solid #e0e0e0; |
| | | } |
| | | |
| | | .stats-left .stats-title { |
| | | font-size: 18px; |
| | | font-weight: bold; |
| | | color: #2c3e50; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .stats-left .stats-subtitle { |
| | | font-size: 14px; |
| | | color: #7f8c8d; |
| | | } |
| | | |
| | | .submit-status { |
| | | font-size: 13px; |
| | | font-weight: 500; |
| | | margin-top: 4px; |
| | | padding: 4px 8px; |
| | | border-radius: 4px; |
| | | display: inline-block; |
| | | } |
| | | |
| | | .submit-status.can-submit { |
| | | background-color: rgba(39, 174, 96, 0.1); |
| | | color: #27ae60; |
| | | border: 1px solid rgba(39, 174, 96, 0.3); |
| | | } |
| | | |
| | | .submit-status.cannot-submit { |
| | | background-color: rgba(231, 76, 60, 0.1); |
| | | color: #e74c3c; |
| | | border: 1px solid rgba(231, 76, 60, 0.3); |
| | | } |
| | | |
| | | .stats-right { |
| | | display: flex; |
| | | gap: 16px; |
| | | } |
| | | |
| | | .stat-item { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | padding: 8px 12px; |
| | | border-radius: 6px; |
| | | min-width: 60px; |
| | | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); |
| | | } |
| | | |
| | | .stat-item.passed { |
| | | background: linear-gradient(135deg, rgba(39, 174, 96, 0.1), rgba(39, 174, 96, 0.2)); |
| | | border: 1px solid rgba(39, 174, 96, 0.3); |
| | | } |
| | | |
| | | .stat-item.failed { |
| | | background: linear-gradient(135deg, rgba(230, 126, 34, 0.1), rgba(230, 126, 34, 0.2)); |
| | | border: 1px solid rgba(230, 126, 34, 0.3); |
| | | } |
| | | |
| | | .stat-item.pending { |
| | | background: linear-gradient(135deg, rgba(243, 156, 18, 0.1), rgba(243, 156, 18, 0.2)); |
| | | border: 1px solid rgba(243, 156, 18, 0.3); |
| | | } |
| | | |
| | | .stat-count { |
| | | font-size: 20px; |
| | | font-weight: bold; |
| | | line-height: 1; |
| | | margin-bottom: 2px; |
| | | } |
| | | |
| | | .stat-item.passed .stat-count { |
| | | color: #27ae60; |
| | | } |
| | | |
| | | .stat-item.failed .stat-count { |
| | | color: #e67e22; |
| | | } |
| | | |
| | | .stat-item.pending .stat-count { |
| | | color: #f39c12; |
| | | } |
| | | |
| | | .stat-label { |
| | | font-size: 12px; |
| | | color: #7f8c8d; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .inspection-table table { |
| | |
| | | border-collapse: collapse; |
| | | } |
| | | |
| | | .inspection-table th, |
| | | .inspection-table td { |
| | | padding: 12px 15px; |
| | | border: 1px solid #ddd; |
| | | .inspection-table th, .inspection-table td { |
| | | padding: 16px 20px; |
| | | border: none; |
| | | text-align: left; |
| | | border-bottom: 1px solid #eee; |
| | | } |
| | | |
| | | .inspection-table th { |
| | | background-color: #f8f9fa; |
| | | font-weight: bold; |
| | | color: #34495e; |
| | | background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| | | font-weight: 600; |
| | | color: #fff; |
| | | font-size: 14px; |
| | | letter-spacing: 0.5px; |
| | | position: relative; |
| | | } |
| | | |
| | | .inspection-table tr:nth-child(even) { |
| | | background-color: #f9f9f9; |
| | | .inspection-table tbody tr { |
| | | transition: all 0.3s ease; |
| | | border-left: 4px solid transparent; |
| | | } |
| | | |
| | | .inspection-table tr:hover { |
| | | background-color: #f1f5f9; |
| | | .inspection-table tbody tr:nth-child(even) { |
| | | background-color: #f8fafc; |
| | | } |
| | | |
| | | .inspection-table tbody tr:hover { |
| | | background-color: #e8f4fd; |
| | | border-left-color: #3498db; |
| | | transform: translateY(-1px); |
| | | box-shadow: 0 4px 12px rgba(52, 152, 219, 0.15); |
| | | } |
| | | |
| | | /* 检验项目列样式 */ |
| | | .inspection-table td:first-child { |
| | | font-weight: 600; |
| | | color: #2c3e50; |
| | | font-size: 15px; |
| | | } |
| | | |
| | | /* 项目名称包装器 */ |
| | |
| | | box-shadow: 0 0 0 2px rgba(243, 156, 18, 0.3); |
| | | } |
| | | |
| | | /* 检验描述列特殊样式 */ |
| | | .inspection-table td:nth-child(2) { |
| | | position: relative; |
| | | min-height: 80px; |
| | | vertical-align: top; |
| | | padding: 16px 20px; |
| | | } |
| | | |
| | | /* 水印样式 */ |
| | | .watermark { |
| | | position: absolute; |
| | | font-size: 40px; |
| | | font-size: 32px; |
| | | font-weight: bold; |
| | | opacity: 1; |
| | | z-index: 1; |
| | | opacity: 0.4; |
| | | z-index: 3; |
| | | pointer-events: none; |
| | | top: 50%; |
| | | left: 50%; |
| | | transform: translate(-50%, -50%) rotate(-15deg); |
| | | text-shadow: 1px 1px 2px rgba(255, 255, 255, 0.8); |
| | | min-width: 60px; |
| | | text-align: center; |
| | | } |
| | | |
| | | .watermark.approved { |
| | | color: #2ecc71; |
| | | color: #27ae60; /* 更淡的绿色 */ |
| | | } |
| | | |
| | | .watermark.rejected { |
| | | color: #e74c3c; |
| | | color: #e67e22; /* 更淡的红色 */ |
| | | } |
| | | |
| | | .watermark.pending { |
| | | color: #f39c12; |
| | | color: #f39c12; /* 橙色 */ |
| | | } |
| | | |
| | | /* 描述文本容器 */ |
| | | /* 描述文本样式 */ |
| | | .description-text { |
| | | position: relative; |
| | | z-index: 2; |
| | | background-color: rgba(255, 255, 255, 0.7); |
| | | padding: 10px; |
| | | padding: 12px 16px; |
| | | background: transparent; |
| | | line-height: 1.6; |
| | | font-size: 14px; |
| | | color: #2c3e50; |
| | | color: #555; |
| | | margin: 0; |
| | | word-wrap: break-word; |
| | | word-break: break-word; |
| | | max-width: 100%; |
| | | /* 确保文字不会太长遮挡水印 */ |
| | | padding-right: 80px; |
| | | min-height: 20px; |
| | | display: block; |
| | | } |
| | | |
| | | /* 调整表格单元格 */ |
| | | .inspection-table td:nth-child(2) { |
| | | position: relative; |
| | | overflow: hidden; |
| | | padding: 0; |
| | | } |
| | | |
| | | /* 按钮样式 */ |
| | | .record-btn { |
| | | padding: 8px 16px; |
| | | background: linear-gradient(135deg, #3498db, #2980b9); |
| | |
| | | margin-top: 20px; |
| | | } |
| | | |
| | | .action-btn { |
| | | .primary-btn, |
| | | .secondary-btn { |
| | | padding: 10px 20px; |
| | | border: none; |
| | | border-radius: 4px; |
| | |
| | | transition: all 0.3s; |
| | | } |
| | | |
| | | .action-btn.primary { |
| | | .primary-btn { |
| | | background-color: #3498db; |
| | | color: white; |
| | | } |
| | | |
| | | .action-btn.primary:hover { |
| | | .primary-btn:hover { |
| | | background-color: #2980b9; |
| | | } |
| | | |
| | | .action-btn.secondary { |
| | | .primary-btn.disabled { |
| | | background: #bdc3c7; |
| | | color: #7f8c8d; |
| | | border-color: #bdc3c7; |
| | | cursor: not-allowed; |
| | | box-shadow: none; |
| | | } |
| | | |
| | | .primary-btn.disabled:hover { |
| | | background: #bdc3c7; |
| | | transform: none; |
| | | box-shadow: none; |
| | | } |
| | | |
| | | .secondary-btn { |
| | | background-color: #ecf0f1; |
| | | color: #7f8c8d; |
| | | } |
| | | |
| | | .action-btn.secondary:hover { |
| | | .secondary-btn:hover { |
| | | background-color: #d5dbdb; |
| | | } |
| | | |
| | | .action-btn.danger { |
| | | background-color: #e74c3c; |
| | | color: white; |
| | | } |
| | | |
| | | .action-btn.danger:hover { |
| | | background-color: #c0392b; |
| | | } |
| | | |
| | | .action-btn.success { |
| | | background: linear-gradient(135deg, #2ecc71, #27ae60); |
| | | color: white; |
| | | } |
| | | |
| | | .action-btn.success:hover { |
| | | background: linear-gradient(135deg, #27ae60, #229954); |
| | | } |
| | | |
| | | /* 弹出框样式 */ |
| | |
| | | justify-content: flex-end; |
| | | } |
| | | |
| | | /* 移动端表格头部统计 */ |
| | | @media (max-width: 500px) { |
| | | .table-header-stats { |
| | | flex-direction: column; |
| | | gap: 12px; |
| | | align-items: flex-start; |
| | | padding: 12px 16px; |
| | | } |
| | | |
| | | .stats-right { |
| | | width: 100%; |
| | | justify-content: space-around; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .stat-item { |
| | | flex: 1; |
| | | min-width: auto; |
| | | padding: 6px 8px; |
| | | } |
| | | |
| | | .stat-count { |
| | | font-size: 16px; |
| | | } |
| | | |
| | | .stat-label { |
| | | font-size: 11px; |
| | | } |
| | | |
| | | .stats-left .stats-title { |
| | | font-size: 16px; |
| | | } |
| | | |
| | | .stats-left .stats-subtitle { |
| | | font-size: 13px; |
| | | } |
| | | } |
| | | |
| | | /* 空状态样式 */ |
| | | .empty-state { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | padding: 60px 20px; |
| | | text-align: center; |
| | | background-color: #fafafa; |
| | | border-radius: 8px; |
| | | margin: 20px 0; |
| | | } |
| | | |
| | | .empty-icon { |
| | | font-size: 48px; |
| | | margin-bottom: 16px; |
| | | opacity: 0.6; |
| | | } |
| | | |
| | | .empty-text { |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | color: #666; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .empty-desc { |
| | | font-size: 14px; |
| | | color: #999; |
| | | line-height: 1.5; |
| | | } |
| | | |
| | | /* 响应式设计 */ |
| | | @media (max-width: 768px) { |
| | | .info-row { |
| | |
| | | margin-top: 10px; |
| | | width: 100%; |
| | | } |
| | | |
| | | .inspection-table table { |
| | | display: block; |
| | | overflow-x: auto; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | </view> |
| | | |
| | | <view class="filter-controls" style="margin-bottom: 5px;"> |
| | | <view class="dropdown-filter"> |
| | | <picker @change="onOptionsChange" :value="optionsIndex" :range="options"> |
| | | <view class="picker">{{options[optionsIndex]}}</view> |
| | | </picker> |
| | | </view> |
| | | <view class="search-container"> |
| | | <input class="search-input" v-model="searchValue" placeholder="请输入检验单号或物料编码" |
| | | <input class="search-input" v-model="searchValue" :placeholder="'请输入'+options[optionsIndex]" |
| | | @confirm="handleSearch" /> |
| | | <button class="search-button" @click="handleSearch">搜索</button> |
| | | </view> |
| | |
| | | <view class="badge normal" v-if="item.isFirst == 1">首次</view> |
| | | <view class="card-title">检验单号: {{item.billNo}}</view> |
| | | <view class="status" :class="{'status-pending': current === 0, 'status-assigned': current === 0 && item.statusUser, 'status-pass': current === 1 && item.result === '合格', 'status-fail': current === 1 && item.result === '不合格'}"> |
| | | {{current === 0 ? (item.statusUser ? '已分配' : '未提交') : (item.result ? item.result : '已完成')}} |
| | | {{current === 0 ? (item.statusUser ? '已分配' : '未提交') : (item.result ? item.result : '已提交')}} |
| | | </view> |
| | | </view> |
| | | |
| | |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 添加按钮 --> |
| | | <view class="plus-button" @click="handleFabClick" v-if="current === 0"> |
| | | <view class="plus-icon">+</view> |
| | | </view> |
| | | |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | tipShow: false, // 是否显示顶部提示框 |
| | | searchValue: '', |
| | | uncheckedCount: 0, |
| | | checkedCount: '已完成' |
| | | checkedCount: '已完成', |
| | | optionsIndex: 0, |
| | | options: ['物料编号', '工单单号', '检验单号', '产线'] |
| | | }; |
| | | }, |
| | | onLoad() { |
| | |
| | | limit: this.limit, |
| | | statusUser: userName, |
| | | result: result, |
| | | searchValue: this.searchValue |
| | | fsubmit: this.current === 0 ? 0 : 1, |
| | | searchValue: this.searchValue, |
| | | selectedIndex: this.optionsIndex |
| | | } |
| | | }).then(res => { |
| | | if (this.pageIndex === 1) { |
| | |
| | | this.isLoading = false; // 出现错误时结束加载 |
| | | }); |
| | | }, |
| | | handleFabClick() { |
| | | uni.navigateTo({ |
| | | url: 'Add?id' |
| | | }); |
| | | }, |
| | | onClickItem(index) { |
| | | if (this.current !== index.currentIndex) { |
| | | this.current = index.currentIndex; |
| | |
| | | this.pageIndex = 1; |
| | | this.init(); |
| | | } |
| | | }, |
| | | //搜索选项变化 |
| | | onOptionsChange(e) { |
| | | this.optionsIndex = e.detail.value; |
| | | // 根据选择的选项设置搜索字段 |
| | | const fieldMap = { |
| | | 0: 'itemNo', // 物料编号 |
| | | 1: 'daa001', // 工单单号 |
| | | 2: 'billNo', // 检验单号 |
| | | 3: 'line' // 产线 |
| | | }; |
| | | this.selectedField = fieldMap[this.optionsIndex]; |
| | | }, |
| | | handleSearch() { |
| | | this.pageIndex = 1; |
| | |
| | | } |
| | | |
| | | /* 顶部筛选区 */ |
| | | .filter-section { |
| | | /* margin-bottom: 24px; */ |
| | | } |
| | | |
| | | |
| | | .filter-section h1 { |
| | | font-size: 24px; |
| | |
| | | |
| | | .search-button:active { |
| | | transform: translateY(0); |
| | | } |
| | | |
| | | .dropdown-filter { |
| | | min-width: 70px; |
| | | } |
| | | |
| | | .picker { |
| | | padding: 8px 12px; |
| | | border: 1px solid #ddd; |
| | | border-radius: 4px; |
| | | background-color: white; |
| | | font-size: 14px; |
| | | min-width: 120px; |
| | | } |
| | | |
| | | .filter-controls { |
| | |
| | | transform: translateY(0); |
| | | } |
| | | |
| | | /* 添加按钮样式 */ |
| | | .plus-button { |
| | | position: fixed; |
| | | bottom: 20px; |
| | | right: 20px; |
| | | width: 60px; |
| | | height: 60px; |
| | | border-radius: 50%; |
| | | background: linear-gradient(135deg, #3498db, #2980b9); |
| | | color: #ffffff; |
| | | text-align: center; |
| | | line-height: 59px; |
| | | font-size: 24px; |
| | | cursor: pointer; |
| | | z-index: 1000; |
| | | box-shadow: 0 4px 12px rgba(52, 152, 219, 0.4); |
| | | transition: all 0.3s ease; |
| | | } |
| | | |
| | | .plus-button:hover { |
| | | transform: translateY(-2px); |
| | | box-shadow: 0 6px 16px rgba(52, 152, 219, 0.5); |
| | | } |
| | | |
| | | .plus-button:active { |
| | | transform: translateY(0); |
| | | } |
| | | |
| | | /* 响应式设计 */ |
| | | @media (min-width: 768px) { |
| | |
| | | </view> |
| | | |
| | | <view class="input-group input1"> |
| | | <view class="input-wrapper"> |
| | | <input v-if="tableData.length < formData.levelNum" class="result-input" type="number" v-model="formData.fcheckResu" placeholder="请输入检验结果..."/> |
| | | <button v-if="tableData.length < formData.levelNum" class="btn primary-btn" @click="submit">保存结果</button> |
| | | <button class="btn upload-btn" @click="previewImage" v-if="isShowImg"> |
| | | <uni-icons type="image" size="16" color="#fff"></uni-icons> |
| | | 查看图片 |
| | | <view class="input-wrapper llj-flex-row"> |
| | | <input v-if="tableData.length < formData.levelNum" |
| | | class="result-input" |
| | | type="number" |
| | | v-model="formData.fcheckResu" |
| | | placeholder="请输入检验结果..." /> |
| | | <button v-if="tableData.length < formData.levelNum" |
| | | class="llj-btn llj-btn-save" |
| | | @click="submit">保存结果</button> |
| | | <button |
| | | class="llj-btn llj-btn-image" |
| | | @click="previewImage" |
| | | v-if="isShowImg" |
| | | > |
| | | <uni-icons type="image" size="20" color="#fff" style="margin-right:6px;"/> |
| | | 上传/查看图片 |
| | | </button> |
| | | <button class="btn upload-btn" @click="saveRemarks"> |
| | | <uni-icons type="compose" size="16" color="#fff"></uni-icons> |
| | | <button |
| | | class="llj-btn llj-btn-desc" |
| | | @click="saveRemarks"> |
| | | <uni-icons type="compose" size="20" color="#fff" style="margin-right:6px;"/> |
| | | 不合格描述 |
| | | </button> |
| | | <view v-if="formData.remarks" class="llj-desc-tag"> |
| | | {{ formData.remarks.length > 10 ? formData.remarks.substr(0,10)+'...' : formData.remarks }} |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | |
| | | |
| | | <!-- NG/OK状态样式 --> |
| | | <view v-else class="simple-status-result"> |
| | | <view class="simple-status" :class="{'pass': item.fcheckResu === '1', 'fail': item.fcheckResu !== '1'}"> |
| | | {{ item.fcheckResu === '1' ? '合格' : '不合格' }} |
| | | <view class="simple-status" :class="{'pass': item.fcheckResu == 1 || item.fcheckResu == 'OK' || item.fcheckResu == 'ok', 'fail': item.fcheckResu != 1 && item.fcheckResu != 'OK' && item.fcheckResu != 'ok'}"> |
| | | {{ (item.fcheckResu == 1 || item.fcheckResu == 'OK' || item.fcheckResu == 'ok') ? '合格' : '不合格' }} |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | }); |
| | | }, |
| | | editResult(fcheckResu) { |
| | | if (fcheckResu == '1') { |
| | | if (fcheckResu == '1' || fcheckResu == 'OK' || fcheckResu == 'ok') { |
| | | return "改为不合格"; |
| | | } else { |
| | | return "改为合格"; |
| | |
| | | this.isShowImg = true; |
| | | this.base64Image = 'data:image/jpeg;base64,' + this.formData.imageData; |
| | | } |
| | | if (this.formData.maxValue && this.formData.minValue && this.formData.standardValue) { |
| | | if (this.formData.maxValue && this.formData.minValue) { |
| | | this.isNumber = true; |
| | | } else { |
| | | this.isNumber = false; |
| | | } |
| | | }).catch(error => { |
| | | console.error("获取检验项目失败:", error); |
| | |
| | | let fstand = "√"; |
| | | let fcheckResu = 1; |
| | | |
| | | if (item.fcheckResu == '1') { |
| | | if (item.fcheckResu == '1' || item.fcheckResu == 'OK' || item.fcheckResu == 'ok') { |
| | | fstand = "×"; |
| | | fcheckResu = 0; |
| | | } |
| | |
| | | font-size: 18px; |
| | | } |
| | | } |
| | | |
| | | .btn-disabled { |
| | | background-color: #ccc !important; |
| | | color: #fff !important; |
| | | cursor: not-allowed !important; |
| | | border: none !important; |
| | | } |
| | | |
| | | .llj-btn-group { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | gap: 24px; |
| | | margin: 24px 0 12px 0; |
| | | flex-wrap: wrap; |
| | | } |
| | | |
| | | .llj-btn { |
| | | display: flex; |
| | | align-items: center; |
| | | border: none; |
| | | border-radius: 24px; |
| | | font-size: 16px; |
| | | font-weight: 500; |
| | | height: 45px; |
| | | line-height: 1; /* 修复:使用line-height: 1避免与height冲突 */ |
| | | padding: 0 28px; |
| | | margin: 0; |
| | | box-shadow: 0 2px 8px rgba(64,158,255,0.10); |
| | | transition: background 0.2s, box-shadow 0.2s; |
| | | cursor: pointer; |
| | | box-sizing: border-box; /* 修复:确保盒模型一致性 */ |
| | | -webkit-appearance: none; /* 修复:移除移动端默认样式 */ |
| | | -moz-appearance: none; |
| | | appearance: none; |
| | | user-select: none; /* 防止文本选择 */ |
| | | touch-action: manipulation; /* 优化触摸体验 */ |
| | | } |
| | | |
| | | .llj-btn-save { |
| | | background: linear-gradient(90deg, #27ae60 0%, #43e97b 100%); |
| | | color: #fff; |
| | | margin-right: 12px; |
| | | } |
| | | .llj-btn-save:active { |
| | | background: linear-gradient(90deg, #43e97b 0%, #27ae60 100%); |
| | | } |
| | | |
| | | .llj-btn-image { |
| | | background: linear-gradient(90deg, #27ae60 0%, #43e97b 100%); |
| | | color: #fff; |
| | | } |
| | | .llj-btn-image:active { |
| | | background: linear-gradient(90deg, #43e97b 0%, #27ae60 100%); |
| | | } |
| | | |
| | | .llj-btn-desc { |
| | | background: linear-gradient(90deg, #F56C6C 0%, #e67e22 100%); |
| | | color: #fff; |
| | | margin-left: 12px; |
| | | } |
| | | .llj-btn-desc:active { |
| | | background: linear-gradient(90deg, #e67e22 0%, #F56C6C 100%); |
| | | } |
| | | |
| | | .llj-btn-disabled, |
| | | .llj-btn[disabled] { |
| | | background: #d3d3d3 !important; |
| | | color: #fff !important; |
| | | cursor: not-allowed !important; |
| | | box-shadow: none !important; |
| | | } |
| | | |
| | | .llj-desc-tag { |
| | | background: #f5f7fa; |
| | | color: #F56C6C; |
| | | border-radius: 16px; |
| | | padding: 6px 16px; |
| | | font-size: 14px; |
| | | margin-left: 12px; |
| | | margin-top: 8px; |
| | | max-width: 180px; |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | } |
| | | |
| | | .llj-flex-row { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12px; |
| | | width: 100%; |
| | | } |
| | | |
| | | .result-input { |
| | | flex: 1; |
| | | height: 45px; |
| | | padding: 0 12px; |
| | | border: 1px solid #DCDFE6; |
| | | border-radius: 4px; |
| | | font-size: 14px; |
| | | box-sizing: border-box; |
| | | min-width: 120px; |
| | | -webkit-appearance: none; /* 移除移动端默认样式 */ |
| | | -moz-appearance: none; |
| | | appearance: none; |
| | | } |
| | | |
| | | .llj-btn, .llj-btn-save, .llj-btn-image, .llj-btn-desc { |
| | | height: 45px; |
| | | line-height: 1; /* 修复:统一使用line-height: 1 */ |
| | | padding: 0 24px; |
| | | min-width: 90px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | box-sizing: border-box; /* 确保盒模型一致性 */ |
| | | } |
| | | |
| | | /* 移动端按钮优化 */ |
| | | @media (max-width: 768px) { |
| | | .llj-btn { |
| | | font-size: 14px; |
| | | padding: 0 20px; |
| | | height: 40px; |
| | | border-radius: 20px; |
| | | } |
| | | |
| | | .llj-btn, .llj-btn-save, .llj-btn-image, .llj-btn-desc { |
| | | height: 40px; |
| | | padding: 0 20px; |
| | | min-width: 80px; |
| | | } |
| | | |
| | | .result-input { |
| | | height: 40px; |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | |
| | | /* 防止移动端按钮点击时的缩放 */ |
| | | @media (max-width: 500px) { |
| | | .llj-btn { |
| | | -webkit-tap-highlight-color: transparent; |
| | | -webkit-touch-callout: none; |
| | | -webkit-user-select: none; |
| | | -khtml-user-select: none; |
| | | -moz-user-select: none; |
| | | -ms-user-select: none; |
| | | user-select: none; |
| | | } |
| | | } |
| | | |
| | | /* 移动端按钮点击效果优化 */ |
| | | .llj-btn:active { |
| | | transform: scale(0.98); |
| | | transition: transform 0.1s ease; |
| | | } |
| | | |
| | | /* 确保所有按钮在移动端都有正确的触摸区域 */ |
| | | .simple-btn { |
| | | padding: 10px 16px; |
| | | background: #007bff; |
| | | color: #fff; |
| | | border: none; |
| | | border-radius: 6px; |
| | | font-size: 14px; |
| | | font-weight: bold; |
| | | cursor: pointer; |
| | | min-width: 80px; |
| | | min-height: 44px; /* 确保触摸区域足够大 */ |
| | | box-sizing: border-box; |
| | | -webkit-appearance: none; |
| | | -moz-appearance: none; |
| | | appearance: none; |
| | | user-select: none; |
| | | touch-action: manipulation; |
| | | } |
| | | |
| | | .simple-btn:active { |
| | | background: #0056b3; |
| | | transform: scale(0.98); |
| | | } |
| | | |
| | | /* 移动端输入框优化 */ |
| | | @media (max-width: 768px) { |
| | | .result-input { |
| | | font-size: 16px; /* 防止iOS缩放 */ |
| | | -webkit-appearance: none; |
| | | border-radius: 8px; |
| | | } |
| | | |
| | | .simple-table-header { |
| | | padding: 10px 12px; |
| | | } |
| | | |
| | | .simple-header-cell, |
| | | .simple-data-cell { |
| | | padding: 10px 12px; |
| | | font-size: 13px; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <view class="sheet-header"> |
| | | <h1>巡检单</h1> |
| | | <view class="inspection-number">检验单号:{{formData.releaseNo}}</view> |
| | | <!-- 加载指示器 --> |
| | | <view v-if="isLoading" class="loading-indicator"> |
| | | <view class="loading-spinner"></view> |
| | | <span>加载中...</span> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 基本信息区 --> |
| | |
| | | <view class="material-info"> |
| | | <view class="info-block"> |
| | | <view class="info-label">线体编号:</view> |
| | | <view class="info-value" v-if="!isUpdate">{{formData.daa020}}</view> |
| | | <picker v-if="isUpdate" class="picker info-value-input" name="selector" :range="DAA020List" |
| | | @change="onDaa020Change"> |
| | | <view>{{ DAA020List[DAA020Index] }}</view> |
| | | </picker> |
| | | <view class="info-value">{{formData.daa020}}</view> |
| | | </view> |
| | | <view class="info-block"> |
| | | <view class="info-label">物料编码:</view> |
| | | <view class="info-value" v-if="!isUpdate">{{formData.itemNo}}</view> |
| | | <picker v-if="isUpdate" class="picker info-value-input" name="selector" :range="ItemList" |
| | | @change="onItemChange"> |
| | | <view>{{ ItemList[ItemIndex] }}</view> |
| | | </picker> |
| | | <view class="info-value">{{formData.itemNo}}</view> |
| | | </view> |
| | | <view class="info-block"> |
| | | <view class="info-label">计划编号:</view> |
| | | <view class="info-value" v-if="!isUpdate">{{formData.billNo}}</view> |
| | | <picker v-if="isUpdate" class="picker info-value-input" name="selector" :range="DAA001List" |
| | | @change="onDaa001Change"> |
| | | <view>{{ DAA001List[DAA001Index] }}</view> |
| | | </picker> |
| | | <view class="info-value">{{formData.billNo}}</view> |
| | | </view> |
| | | <view class="info-block"> |
| | | <view class="info-label">物料名称:</view> |
| | |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 操作按钮区 - 检验项目获取 --> |
| | | <view class="action-buttons" v-if="isUpdate && !isShowTable"> |
| | | <button class="primary-btn" @click="getItem">创建检验单</button> |
| | | </view> |
| | | |
| | | <view class="action-buttons" v-if="isShowTable"> |
| | | <button class="secondary-btn" @click="getTable">获取项目</button> |
| | | <button v-if="isUpdate" class="primary-btn" @click="saveTable">生成项目</button> |
| | | </view> |
| | | <!-- 操作按钮区 - 已移除重复的获取检验项目按钮 --> |
| | | |
| | | <!-- 检验项目表格 --> |
| | | <view class="inspection-table" v-if="tableData.length > 0"> |
| | | <view class="inspection-table"> |
| | | <!-- 表格头部统计信息 --> |
| | | <view class="table-header-stats"> |
| | | <view class="stats-left"> |
| | | <view class="stats-title">检验项目清单</view> |
| | | <view class="stats-subtitle">共 {{tableData.length}} 个检验项目</view> |
| | | <view class="submit-status" :class="{'can-submit': canSubmit, 'cannot-submit': !canSubmit}"> |
| | | {{canSubmit ? '✓ 可以提交' : '✗ 检验未完成,无法提交'}} |
| | | </view> |
| | | </view> |
| | | <view class="stats-right"> |
| | | <view class="stat-item passed"> |
| | |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <table> |
| | | <table v-if="tableData.length > 0"> |
| | | <thead> |
| | | <tr> |
| | | <th width="15%" style="text-align: center;">检验项目</th> |
| | |
| | | </tr> |
| | | </tbody> |
| | | </table> |
| | | <!-- 空状态显示 --> |
| | | <view v-else class="empty-state"> |
| | | <view class="empty-icon">📋</view> |
| | | <view class="empty-text">暂无检验项目</view> |
| | | <view class="empty-desc">该检验单还没有检验项目</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 操作按钮区 - 底部操作 --> |
| | | <view class="action-buttons" v-if="!isUpdate && !isShowTable"> |
| | | <button class="secondary-btn" @click="toImage">图片管理</button> |
| | | <button class="secondary-btn" @click="saveRemarks">添加描述</button> |
| | | <button v-if="!formData.fcheckResu" class="primary-btn" style="background: linear-gradient(135deg, #e74c3c, #c0392b);" @click="removeXJ">删除单据</button> |
| | | <!-- 操作按钮区 --> |
| | | <view class="action-buttons"> |
| | | <button class="secondary-btn" v-if="!isSubmitted" @click="genByProc">获取检验项目</button> |
| | | <button class="secondary-btn" @click="toImage">上传/查看图片</button> |
| | | <button class="secondary-btn" v-if="!isSubmitted" @click="saveRemarks">添加不合格描述</button> |
| | | <button class="primary-btn" v-if="!isSubmitted && canSubmit" @click="submit">提交检验</button> |
| | | <button class="primary-btn disabled" v-if="!isSubmitted && !canSubmit" disabled>提交检验</button> |
| | | </view> |
| | | |
| | | <!-- 不合格描述弹窗 --> |
| | | <!-- 弹窗 --> |
| | | <view v-if="remarksPopup" class="overlay"> |
| | | <view class="popup"> |
| | | <h3>修改不合格描述</h3> |
| | | <view class="form-group"> |
| | | <label class="form-label">不合格描述:</label> |
| | | <input v-model="remarks" class="form-input" type="text" placeholder="请输入不合格描述"/> |
| | | <view class="popup-header"> |
| | | <h3>修改不合格描述</h3> |
| | | </view> |
| | | <view class="popup-buttons"> |
| | | <button class="updateBut" @click="editRemarks">修改</button> |
| | | <button class="secondary-btn" @click="remarksPopup = !remarksPopup">取消</button> |
| | | <view class="popup-content"> |
| | | <view class="info-block"> |
| | | <view class="info-label">不合格描述:</view> |
| | | <input class="info-input" type="text" v-model="remarks" placeholder="请输入不合格描述,留空表示清除描述" /> |
| | | </view> |
| | | </view> |
| | | <view class="popup-actions"> |
| | | <button class="action-btn primary" @click="editRemarks">修改</button> |
| | | <button class="action-btn secondary" @click="remarksPopup = !remarksPopup">取消</button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | boardStyle: "" |
| | | }, |
| | | |
| | | DAA020List: [], |
| | | DAA020Index: -1, |
| | | |
| | | DAA001List: [], |
| | | DAA001Index: -1, |
| | | schemeResult: [], |
| | | |
| | | isShowTable: false, |
| | | |
| | | ItemList: [], |
| | | ItemIndex: -1, |
| | | boardItems: [], |
| | | |
| | | lineList: [], |
| | | |
| | | lineNo: "", |
| | | |
| | | tableData: [], |
| | | |
| | | isSubmit: true, |
| | | |
| | | isUpdate: true, |
| | | |
| | | remarks: "", |
| | | remarksPopup: false, |
| | | |
| | | // 添加加载状态 |
| | | isLoading: false, |
| | | isInitialized: false, |
| | | }; |
| | | }, |
| | | computed: { |
| | | isSubmitted() { |
| | | const val = this.formData && (this.formData.Fsubmit ?? this.formData.fsubmit ?? this.formData.FSUBMIT ?? this.formData.fSubmit); |
| | | if (val === null || val === undefined || val === '') return false; |
| | | return String(val).trim() === '1' || Number(val) === 1; |
| | | }, |
| | | canSubmit() { |
| | | // 检查是否有检验项目 |
| | | if (!Array.isArray(this.tableData) || this.tableData.length === 0) { |
| | | return false; |
| | | } |
| | | |
| | | // 检查是否所有检验项目都已完成 |
| | | const allCompleted = this.tableData.every(it => { |
| | | const checkedCount = Number(it?.isCheck ?? 0); |
| | | const requiredCount = Number(it?.levelNum ?? 0); |
| | | return checkedCount >= requiredCount; |
| | | }); |
| | | |
| | | // 检查是否所有检验项目都有结果 |
| | | const allHaveResult = this.tableData.every(it => |
| | | it.result && it.result !== '未完成' && it.result !== '未检测' |
| | | ); |
| | | |
| | | return allCompleted && allHaveResult; |
| | | } |
| | | }, |
| | | onLoad(options) { |
| | | //options中包含了url附带的参数 |
| | |
| | | let params = options; |
| | | |
| | | if (params["id"]) { |
| | | this.isUpdate = false; |
| | | this.formData.id = params["id"]; |
| | | this.formData.releaseNo = params["releaseNo"]; |
| | | //getQaItemXj02 |
| | | this.init(); |
| | | } else { |
| | | //初始化检验单号 |
| | | this.$post({ |
| | | url: "/XJ/getMaxReleaseNo" |
| | | }).then(res => { |
| | | this.formData.releaseNo = res.data.tbBillList; |
| | | this.formData.createBy = this.$loginInfo.account; |
| | | this.formData.createDate = this.$getDate("yyyy-mm-dd"); |
| | | }); |
| | | |
| | | //车间下拉框的初始化 |
| | | this.$post({ |
| | | url: "/XJ/getLineAll" |
| | | }).then(res => { |
| | | this.lineList = res.data.tbBillList; |
| | | this.DAA020List = res.data.tbBillList.map(item => item.lineName); |
| | | }) |
| | | // 自建单据功能已移除,只允许查看现有单据 |
| | | this.$showMessage("请从列表中选择检验单进行查看"); |
| | | uni.navigateBack(); |
| | | } |
| | | }, |
| | | methods: { |
| | |
| | | // 获取待检验项目数量 |
| | | getPendingCount() { |
| | | return this.tableData.filter(item => !item.result || item.result === '').length; |
| | | }, |
| | | genByProc() { |
| | | this.$post({ |
| | | url: "/XJ/GenUpdateXJ", |
| | | data: { |
| | | id: this.formData.id, |
| | | no: this.formData.billNo, |
| | | userNo: this.$loginInfo.account |
| | | } |
| | | }).then(res => { |
| | | if (res.status === 0) { |
| | | this.$showMessage("生成/获取检验项目成功"); |
| | | // 成功后刷新检验项目 |
| | | this.$post({ |
| | | url: "/XJ/getJYItem", |
| | | data: { pid: this.formData.id } |
| | | }).then(r => { |
| | | this.tableData = r.data.tbBillList || []; |
| | | }); |
| | | } else { |
| | | this.$showMessage(res.message || "生成失败"); |
| | | } |
| | | }); |
| | | }, |
| | | removeXJ() { |
| | | if (this.formData.id) { |
| | |
| | | this.$showMessage("请先选择检验单号"); |
| | | } |
| | | }, |
| | | getItem() { |
| | | |
| | | if (this.isSubmit) { |
| | | this.$showMessage("此物料无启用的检验项目,请维护!"); |
| | | return; |
| | | } |
| | | |
| | | if (!this.formData.billNo) { |
| | | this.$showMessage("请选择计划编号"); |
| | | return; |
| | | } |
| | | |
| | | this.$post({ |
| | | url: "/XJ/save", |
| | | data: { |
| | | from: this.formData, |
| | | userNo: this.$loginInfo.account, |
| | | items: this.tableData |
| | | } |
| | | }).then(res => { |
| | | this.formData.id = res.data.tbBillList; |
| | | this.$showMessage("生成检验项目成功"); |
| | | this.init(); |
| | | this.isUpdate = false; |
| | | }); |
| | | }, |
| | | //生产线别选择并初始话工单号 |
| | | onDaa020Change(event) { |
| | | //获取生产线别的下标地址 |
| | | this.DAA020Index = event.mp.detail.value; |
| | | |
| | | this.lineNo = this.lineList[this.DAA020Index].lineNo; |
| | | |
| | | this.$post({ |
| | | url: "/XJ/getBoardItem", |
| | | data: { |
| | | lineNo: this.lineNo |
| | | } |
| | | }).then(res => { |
| | | //填充工单号的数据源 |
| | | this.boardItems = res.data.tbBillList; |
| | | this.ItemList = this.boardItems.map(item => item.itemName); |
| | | //变为默认空值的状态 |
| | | this.ItemIndex = -1; |
| | | }) |
| | | |
| | | }, |
| | | onItemChange(event) { |
| | | this.ItemIndex = event.mp.detail.value; |
| | | this.formData.itemNo = this.boardItems[this.ItemIndex].itemNo;//主要是改这里 |
| | | this.formData.itemId = this.boardItems[this.ItemIndex].id;//主要是改这里 |
| | | this.formData.itemName = this.boardItems[this.ItemIndex].itemName;//主要是改这里 |
| | | this.formData.itemModel = this.boardItems[this.ItemIndex].itemModel;//主要是改这里 |
| | | this.$post({ |
| | | url: "/XJ/getDaa001", |
| | | data: { |
| | | daa020: this.lineNo, |
| | | item: this.formData.itemNo |
| | | } |
| | | }).then(res => { |
| | | //填充工单号的数据源 |
| | | this.schemeResult = res.data.tbBillList; |
| | | this.DAA001List = this.schemeResult.map(s => s.daa001); |
| | | //变为默认空值的状态 |
| | | this.DAA001Index = -1; |
| | | |
| | | this.formData.billNo = ""; |
| | | }) |
| | | }, |
| | | //选取工单填充物料号和其他信息 |
| | | onDaa001Change(event) { |
| | | this.DAA001Index = event.mp.detail.value; |
| | | this.formData.billNo = this.schemeResult[this.DAA001Index].daa001; |
| | | this.formData.planQty = this.schemeResult[this.DAA001Index].daa008; |
| | | //表单中的部分字段赋值 |
| | | this.$post({ |
| | | url: "/XJ/getItem", |
| | | data: { |
| | | daa001: this.formData.billNo |
| | | } |
| | | }).then(res => { |
| | | let data = res.data.tbBillList[0]; |
| | | //当返回的结果集为空时置空原有的值 |
| | | if (!data) { |
| | | this.formData.billNo = ""; |
| | | this.formData.itemNo = ""; |
| | | this.formData.planQty = ""; |
| | | this.tableData = []; |
| | | return; |
| | | } |
| | | |
| | | this.$post({ |
| | | url: "/XJ/setJYItem", |
| | | data: { |
| | | itemNo: this.formData.itemNo |
| | | } |
| | | }).then(res => { |
| | | if (res.data.tbBillList.length > 0) { |
| | | this.tableData = res.data.tbBillList; // 在箭头函数中,this 指向外层作用域的 this |
| | | this.isSubmit = false; |
| | | } else { |
| | | this.$showMessage("此物料没有启用的检验项目,请维护!"); |
| | | this.isSubmit = true; |
| | | this.tableData = []; |
| | | } |
| | | }); |
| | | }); |
| | | }, |
| | | init() { |
| | | // 防止重复加载 |
| | | if (this.isLoading || !this.formData.id) { |
| | | return; |
| | | } |
| | | |
| | | this.isLoading = true; |
| | | console.log('init: 开始加载数据,ID:', this.formData.id); |
| | | |
| | | this.$post({ |
| | | url: "/XJ/getPage", |
| | | data: { |
| | |
| | | } |
| | | }); |
| | | this.tableData = tableData; |
| | | if (this.tableData.length === 0) { |
| | | this.isShowTable = true; |
| | | } |
| | | }) |
| | | this.isInitialized = true; |
| | | this.isLoading = false; |
| | | |
| | | }).catch(error => { |
| | | console.error('获取检验项目失败:', error); |
| | | this.isLoading = false; |
| | | }); |
| | | } else { |
| | | this.isLoading = false; |
| | | } |
| | | }).catch(error => { |
| | | console.error('获取页面数据失败:', error); |
| | | this.isLoading = false; |
| | | }); |
| | | }, |
| | | toDetail(item) { |
| | | if (this.isUpdate) { |
| | | uni.showToast({ |
| | | icon: "none", |
| | | title: "请先生成检验项目", |
| | | duration: 2000, |
| | | }); |
| | | } else { |
| | | uni.navigateTo({ |
| | | url: 'detail?id=' + item.id + '&billNo=' + this.formData.billNo + '&gid=' + this.formData |
| | | .id |
| | | }); |
| | | } |
| | | uni.navigateTo({ |
| | | url: 'detail?id=' + item.id + '&billNo=' + this.formData.billNo + '&gid=' + this.formData.id |
| | | }); |
| | | }, saveRemarks() { |
| | | this.remarksPopup = !this.remarksPopup; |
| | | this.remarks = this.formData.remarks; |
| | | }, |
| | | editRemarks() { |
| | | if (this.remarks) { |
| | | //saveRemarksGid |
| | | this.$post({ |
| | | url: "/XJ/saveRemarksGid", |
| | | data: { |
| | | gid: this.formData.id, |
| | | remarks: this.remarks |
| | | } |
| | | }).then(res => { |
| | | if (res.data.tbBillList > 0) { |
| | | this.formData.remarks = this.remarks; |
| | | this.remarksPopup = !this.remarksPopup; |
| | | this.$showMessage("保存成功"); |
| | | } |
| | | }) |
| | | } |
| | | // 允许留空,留空代表清除描述 |
| | | this.$post({ |
| | | url: "/XJ/saveRemarksGid", |
| | | data: { |
| | | gid: this.formData.id, |
| | | remarks: this.remarks || "" // 留空时传递空字符串 |
| | | } |
| | | }).then(res => { |
| | | if (res.data.tbBillList > 0) { |
| | | this.formData.remarks = this.remarks || ""; // 更新本地数据 |
| | | this.remarksPopup = !this.remarksPopup; |
| | | this.$showMessage(this.remarks ? "保存成功" : "描述已清除"); |
| | | } |
| | | }).catch(error => { |
| | | this.$showMessage("保存失败,请重试"); |
| | | }); |
| | | }, |
| | | toImage() { |
| | | uni.navigateTo({ |
| | |
| | | }); |
| | | }, |
| | | getTable() { |
| | | // 调用存储过程生成检验项目 |
| | | this.$post({ |
| | | url: "/XJ/setJYItem", |
| | | url: "/XJ/GenUpdateXJ", |
| | | data: { |
| | | itemNo: this.formData.itemNo |
| | | } |
| | | }).then(res => { |
| | | if (res.data.tbBillList.length > 0) { |
| | | this.tableData = res.data.tbBillList; // 在箭头函数中,this 指向外层作用域的 this |
| | | this.isShowTable = true; |
| | | this.isUpdate = true; |
| | | } else { |
| | | this.$showMessage("此物料没有启用的检验项目,请维护!"); |
| | | this.isShowTable = true; |
| | | this.isUpdate = false; |
| | | this.tableData = []; |
| | | } |
| | | }); |
| | | }, |
| | | saveTable() { |
| | | if (this.tableData.length === 0) { |
| | | return; |
| | | } |
| | | this.$post({ |
| | | url: "/XJ/saveItem", |
| | | data: { |
| | | gid: this.formData.id, |
| | | items: this.tableData, |
| | | id: this.formData.id || 0, |
| | | no: this.formData.billNo, |
| | | userNo: this.$loginInfo.account |
| | | } |
| | | }).then(res => { |
| | | this.formData.id = res.data.tbBillList; |
| | | this.isShowTable = false; |
| | | this.isUpdate = false; |
| | | this.init(); |
| | | }) |
| | | if (res.status === 0) { |
| | | this.$showMessage("获取检验项目成功"); |
| | | this.init(); // 重新加载数据 |
| | | } else { |
| | | this.$showMessage(res.message || "获取检验项目失败"); |
| | | } |
| | | }).catch(error => { |
| | | this.$showMessage("网络错误,请重试"); |
| | | }); |
| | | }, |
| | | submit() { |
| | | // 校验是否有检验项目 |
| | | if (!Array.isArray(this.tableData) || this.tableData.length === 0) { |
| | | this.$showMessage("没有检验项目,无法提交"); |
| | | return; |
| | | } |
| | | |
| | | // 校验检验项目是否全部完成 |
| | | const unfinishedItems = []; |
| | | const hasUnfinished = this.tableData.some(it => { |
| | | const checkedCount = Number(it?.isCheck ?? 0); |
| | | const requiredCount = Number(it?.levelNum ?? 0); |
| | | if (checkedCount < requiredCount) { |
| | | unfinishedItems.push(it.projName); |
| | | return true; |
| | | } |
| | | return false; |
| | | }); |
| | | |
| | | if (hasUnfinished) { |
| | | const message = unfinishedItems.length > 0 |
| | | ? `以下检验项目未完成,不能提交:\n${unfinishedItems.join('、')}` |
| | | : "存在未完成的检验项目,不能提交"; |
| | | this.$showMessage(message); |
| | | return; |
| | | } |
| | | |
| | | // 校验是否所有检验项目都有结果 |
| | | const itemsWithoutResult = this.tableData.filter(it => |
| | | !it.result || it.result === '未完成' || it.result === '未检测' |
| | | ); |
| | | if (itemsWithoutResult.length > 0) { |
| | | const itemNames = itemsWithoutResult.map(it => it.projName); |
| | | this.$showMessage(`以下检验项目没有检验结果,不能提交:\n${itemNames.join('、')}`); |
| | | return; |
| | | } |
| | | |
| | | // 提交检验逻辑 |
| | | this.$post({ |
| | | url: "/XJ/XJQaSubmit", |
| | | data: { |
| | | gid: this.formData.id, |
| | | userNo: this.$loginInfo.account |
| | | } |
| | | }).then(res => { |
| | | if (res.status === 0) { |
| | | // 显示成功提示框 |
| | | uni.showModal({ |
| | | title: '提交成功', |
| | | content: res.message || '检验提交成功!', |
| | | showCancel: false, |
| | | confirmText: '确定', |
| | | confirmColor: '#27ae60', |
| | | success: (modalRes) => { |
| | | if (modalRes.confirm) { |
| | | // 提交成功后刷新当前单据,确保FSUBMIT最新,从而隐藏按钮 |
| | | this.init(); |
| | | } |
| | | } |
| | | }); |
| | | } else { |
| | | // 显示失败提示框 |
| | | uni.showModal({ |
| | | title: '提交失败', |
| | | content: res.message || '检验提交失败,请重试!', |
| | | showCancel: false, |
| | | confirmText: '确定' |
| | | }); |
| | | } |
| | | }).catch(error => { |
| | | uni.showModal({ |
| | | title: '提交失败', |
| | | content: '网络错误,请检查网络连接后重试!', |
| | | showCancel: false, |
| | | confirmText: '确定' |
| | | }); |
| | | }); |
| | | }, |
| | | // 刷新检验项目数据 |
| | | refreshTableData() { |
| | | if (!this.formData.id || this.isLoading) { |
| | | return; |
| | | } |
| | | |
| | | this.isLoading = true; |
| | | this.$post({ |
| | | url: "/XJ/getJYItem", |
| | | data: { |
| | | pid: this.formData.id |
| | | } |
| | | }).then(res => { |
| | | let tableData = res.data.tbBillList; |
| | | // 当已检验个数都不为空时按照检测结构排序 |
| | | tableData.sort((a, b) => { |
| | | if (a.result === '未完成' && b.result === '合格') { |
| | | return -1; |
| | | } else if (a.result === '合格' && b.result === '未完成') { |
| | | return 1; |
| | | } else { |
| | | return 0; |
| | | } |
| | | }); |
| | | this.tableData = tableData; |
| | | this.isLoading = false; |
| | | console.log('检验项目数据已刷新'); |
| | | }).catch(error => { |
| | | console.error('刷新检验项目失败:', error); |
| | | this.isLoading = false; |
| | | }); |
| | | } |
| | | }, |
| | | onShow() { |
| | | //每次进入页面都会执行的方法 |
| | | if (this.formData.id) { |
| | | this.init(); |
| | | // 只有在有ID且已经初始化过的情况下才刷新数据 |
| | | if (this.formData.id && this.formData.id !== '' && this.isInitialized) { |
| | | console.log('onShow: 页面显示,刷新检验项目数据,ID:', this.formData.id); |
| | | // 只刷新检验项目数据,不重新加载基本信息 |
| | | this.refreshTableData(); |
| | | } |
| | | } |
| | | }; |
| | |
| | | font-size: 16px; |
| | | font-weight: bold; |
| | | color: #3498db; |
| | | } |
| | | |
| | | /* 加载指示器样式 */ |
| | | .loading-indicator { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | gap: 8px; |
| | | margin-top: 10px; |
| | | padding: 8px 16px; |
| | | background: rgba(52, 152, 219, 0.1); |
| | | border-radius: 20px; |
| | | font-size: 14px; |
| | | color: #3498db; |
| | | } |
| | | |
| | | .loading-spinner { |
| | | width: 16px; |
| | | height: 16px; |
| | | border: 2px solid #e3f2fd; |
| | | border-top: 2px solid #3498db; |
| | | border-radius: 50%; |
| | | animation: spin 1s linear infinite; |
| | | } |
| | | |
| | | @keyframes spin { |
| | | 0% { transform: rotate(0deg); } |
| | | 100% { transform: rotate(360deg); } |
| | | } |
| | | |
| | | /* 基本信息区样式 */ |
| | |
| | | .stats-left .stats-subtitle { |
| | | font-size: 14px; |
| | | color: #7f8c8d; |
| | | } |
| | | |
| | | .submit-status { |
| | | font-size: 13px; |
| | | font-weight: 500; |
| | | margin-top: 4px; |
| | | padding: 4px 8px; |
| | | border-radius: 4px; |
| | | display: inline-block; |
| | | } |
| | | |
| | | .submit-status.can-submit { |
| | | background-color: rgba(39, 174, 96, 0.1); |
| | | color: #27ae60; |
| | | border: 1px solid rgba(39, 174, 96, 0.3); |
| | | } |
| | | |
| | | .submit-status.cannot-submit { |
| | | background-color: rgba(231, 76, 60, 0.1); |
| | | color: #e74c3c; |
| | | border: 1px solid rgba(231, 76, 60, 0.3); |
| | | } |
| | | |
| | | .stats-right { |
| | |
| | | .inspection-table td:nth-child(2) { |
| | | position: relative; |
| | | min-height: 80px; |
| | | vertical-align: top; |
| | | vertical-align: middle; |
| | | padding: 16px 20px; |
| | | } |
| | | |
| | |
| | | background-color: #2980b9; |
| | | } |
| | | |
| | | .primary-btn.disabled { |
| | | background: #bdc3c7; |
| | | color: #7f8c8d; |
| | | border-color: #bdc3c7; |
| | | cursor: not-allowed; |
| | | box-shadow: none; |
| | | } |
| | | |
| | | .primary-btn.disabled:hover { |
| | | background: #bdc3c7; |
| | | transform: none; |
| | | box-shadow: none; |
| | | } |
| | | |
| | | .secondary-btn { |
| | | background-color: #ecf0f1; |
| | | color: #7f8c8d; |
| | |
| | | |
| | | .secondary-btn:hover { |
| | | background-color: #d5dbdb; |
| | | } |
| | | |
| | | .info-btn { |
| | | background: linear-gradient(135deg, #17a2b8, #138496); |
| | | color: white; |
| | | } |
| | | |
| | | .info-btn:hover { |
| | | background: linear-gradient(135deg, #138496, #117a8b); |
| | | transform: translateY(-2px); |
| | | box-shadow: 0 4px 16px rgba(23, 162, 184, 0.4); |
| | | } |
| | | |
| | | .info-btn:active { |
| | | transform: translateY(0); |
| | | box-shadow: 0 2px 8px rgba(23, 162, 184, 0.3); |
| | | } |
| | | |
| | | .record-btn { |
| | |
| | | /* 水印样式 */ |
| | | .watermark { |
| | | position: absolute; |
| | | font-size: 32px; |
| | | font-size: 28px; |
| | | font-weight: bold; |
| | | opacity: 0.4; |
| | | opacity: 0.3; |
| | | z-index: 3; |
| | | pointer-events: none; |
| | | bottom: 8px; |
| | | right: 8px; |
| | | transform: rotate(-15deg); |
| | | transform-origin: bottom right; |
| | | top: 50%; |
| | | right: 12px; |
| | | transform: translateY(-50%) rotate(-15deg); |
| | | transform-origin: center; |
| | | text-shadow: 1px 1px 2px rgba(255, 255, 255, 0.8); |
| | | min-width: 60px; |
| | | text-align: center; |
| | |
| | | display: block; |
| | | } |
| | | |
| | | /* 弹出层样式 */ |
| | | /* 弹出框样式 */ |
| | | .overlay { |
| | | position: fixed; |
| | | top: 0; |
| | |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | z-index: 10; |
| | | z-index: 1000; |
| | | } |
| | | |
| | | .popup { |
| | | background-color: #fff; |
| | | padding: 20px; |
| | | border: 1px solid #ccc; |
| | | box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); |
| | | width: 68vw; |
| | | height: 25vh; |
| | | background-color: white; |
| | | border-radius: 8px; |
| | | box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); |
| | | width: 90%; |
| | | max-width: 400px; |
| | | max-height: 80vh; |
| | | overflow-y: auto; |
| | | } |
| | | |
| | | .popup h3 { |
| | | margin-top: 0; |
| | | color: #2c3e50; |
| | | .popup-header { |
| | | padding: 20px; |
| | | border-bottom: 1px solid #eee; |
| | | padding-bottom: 10px; |
| | | margin-bottom: 15px; |
| | | font-size: 16px; |
| | | text-align: center; |
| | | } |
| | | |
| | | .popup .form-group { |
| | | margin-bottom: 15px; |
| | | .popup-header h3 { |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | color: #2c3e50; |
| | | margin: 0; |
| | | } |
| | | |
| | | .popup-content { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .popup-actions { |
| | | padding: 20px; |
| | | border-top: 1px solid #eee; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .popup .form-label { |
| | | margin-bottom: 5px; |
| | | font-weight: bold; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .popup .form-input { |
| | | width: 100%; |
| | | padding: 8px; |
| | | border: 1px solid #ddd; |
| | | border-radius: 4px; |
| | | font-size: 14px; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | .popup-buttons { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | gap: 10px; |
| | | margin-top: 20px; |
| | | justify-content: flex-end; |
| | | } |
| | | |
| | | .updateBut { |
| | | background-color: #3498db; |
| | | color: white; |
| | | .action-btn { |
| | | padding: 10px 20px; |
| | | border: none; |
| | | padding: 8px 15px; |
| | | border-radius: 4px; |
| | | margin-right: 10px; |
| | | font-size: 14px; |
| | | cursor: pointer; |
| | | transition: all 0.3s; |
| | | } |
| | | |
| | | .updateBut:hover { |
| | | .action-btn.primary { |
| | | background-color: #3498db; |
| | | color: white; |
| | | } |
| | | |
| | | .action-btn.primary:hover { |
| | | background-color: #2980b9; |
| | | } |
| | | |
| | | .action-btn.secondary { |
| | | background-color: #ecf0f1; |
| | | color: #7f8c8d; |
| | | } |
| | | |
| | | .action-btn.secondary:hover { |
| | | background-color: #d5dbdb; |
| | | } |
| | | |
| | | /* 空状态样式 */ |
| | | .empty-state { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | padding: 60px 20px; |
| | | text-align: center; |
| | | background-color: #fafafa; |
| | | border-radius: 8px; |
| | | margin: 20px 0; |
| | | } |
| | | |
| | | .empty-icon { |
| | | font-size: 48px; |
| | | margin-bottom: 16px; |
| | | opacity: 0.6; |
| | | } |
| | | |
| | | .empty-text { |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | color: #666; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .empty-desc { |
| | | font-size: 14px; |
| | | color: #999; |
| | | line-height: 1.5; |
| | | } |
| | | |
| | | /* 响应式设计 */ |
| | | @media (max-width: 500px) { |
| | | .info-row, |
| | |
| | | </view> |
| | | |
| | | <view class="filter-controls" style="margin-bottom: 5px;"> |
| | | <view class="dropdown-filter"> |
| | | <picker @change="onLineChange" :value="lineIndex" :range="lineOptions"> |
| | | <view class="picker">{{lineOptions[lineIndex]}}</view> |
| | | </picker> |
| | | </view> |
| | | <view class="dropdown-filter"> |
| | | <picker @change="onOptionsChange" :value="optionsIndex" :range="options"> |
| | | <view class="picker">{{options[optionsIndex]}}</view> |
| | | </picker> |
| | | </view> |
| | | <view class="search-container"> |
| | | <input class="search-input" v-model="searchValue" placeholder="请输入检验单号或物料编码" |
| | | <input class="search-input" v-model="searchValue" :placeholder="'请输入'+options[optionsIndex]" |
| | | @confirm="handleSearch" /> |
| | | <button class="search-button" @click="handleSearch">搜索</button> |
| | | </view> |
| | |
| | | @click="navigateToDetail(item)"> |
| | | <view class="card-header"> |
| | | <view class="card-title">检验单号: {{item.releaseNo}}</view> |
| | | <view class="status" :class="{'status-pending': current === 0, 'status-pass': current === 1 && item.fcheckResu === '合格', 'status-fail': current === 1 && item.fcheckResu === '不合格'}"> |
| | | {{current === 0 ? '未提交' : (item.fcheckResu ? item.fcheckResu : '已提交')}} |
| | | <view class="status" :class="{'status-pending': item.fsubmit === 0 || item.fsubmit == null, 'status-pass': item.fsubmit === 1 && item.fcheckResu === '合格', 'status-fail': item.fsubmit === 1 && item.fcheckResu === '不合格'}"> |
| | | {{(item.fsubmit === 0 || item.fsubmit == null) ? '未提交' : (item.fcheckResu ? item.fcheckResu : '已提交')}} |
| | | </view> |
| | | </view> |
| | | |
| | |
| | | </view> |
| | | |
| | | <view class="card-actions"> |
| | | <button class="primary">{{current === 0 ? '继续检验' : '查看详情'}}</button> |
| | | <button class="primary">{{(item.fsubmit === 0 || item.fsubmit == null) ? '继续检验' : '查看详情'}}</button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 添加按钮 --> |
| | | <view class="plus-button" @click="handleFabClick" v-if="current === 0"> |
| | | <view class="plus-icon">+</view> |
| | | </view> |
| | | <!-- 添加按钮 - 已隐藏 --> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | tipShow: false, // 是否显示顶部提示框 |
| | | searchValue: '', |
| | | uncheckedCount: 0, |
| | | checkedCount: 0 |
| | | checkedCount: '已完成', |
| | | optionsIndex: 0, |
| | | options: ['物料编号', '物料名称', '检验单号'], |
| | | lineIndex: 0, |
| | | lineOptions: ['全部产线'], |
| | | lineData: [] |
| | | }; |
| | | }, |
| | | onLoad() { |
| | | //页面加载时调用的事件 |
| | | this.loadLineData(); |
| | | this.init(); |
| | | }, |
| | | methods: { |
| | | //加载产线数据 |
| | | loadLineData() { |
| | | this.$post({ |
| | | url: "/XJ/getLineAll", |
| | | data: {} |
| | | }).then(res => { |
| | | if (res.data && res.data.tbBillList) { |
| | | this.lineData = res.data.tbBillList; |
| | | this.lineOptions = ['全部产线', ...res.data.tbBillList.map(item => item.lineName)]; |
| | | } |
| | | }).catch(error => { |
| | | console.error('加载产线数据失败:', error); |
| | | }); |
| | | }, |
| | | //产线选择变化 |
| | | onLineChange(e) { |
| | | this.lineIndex = e.detail.value; |
| | | this.pageIndex = 1; |
| | | this.data = []; |
| | | this.init(); |
| | | }, |
| | | //搜索选项变化 |
| | | onOptionsChange(e) { |
| | | this.optionsIndex = e.detail.value; |
| | | // 根据选择的选项设置搜索字段 |
| | | const fieldMap = { |
| | | 0: 'itemNo', // 物料编号 |
| | | 1: 'itemName', // 物料名称 |
| | | 2: 'releaseNo' // 检验单号 |
| | | }; |
| | | this.selectedField = fieldMap[this.optionsIndex]; |
| | | }, |
| | | handleSearch() { |
| | | this.pageIndex = 1; |
| | | this.data = []; |
| | | this.init(); |
| | | }, |
| | | init() { |
| | | let result = "未完成"; |
| | | if (this.current === 1) { |
| | | result = "已完成"; |
| | | let fsubmit = null; |
| | | if (this.current === 0) { |
| | | fsubmit = 0; // 未提交 |
| | | } else if (this.current === 1) { |
| | | fsubmit = 1; // 已提交 |
| | | } |
| | | |
| | | if (this.isLoading) return; // 如果正在加载则不继续执行 |
| | | |
| | | this.isLoading = true; |
| | | |
| | | //获取当前登录的用户 |
| | | let userName = this.$loginInfo.account; |
| | | |
| | | //页面加载时调用的事件 |
| | | //页面加载时调用的事件 - 取消用户权限控制和产线过滤,所有人都可以看到所有表单 |
| | | this.$post({ |
| | | url: "/XJ/GetPage", |
| | | data: { |
| | | pageIndex: this.pageIndex, |
| | | limit: this.limit, |
| | | createUser: userName, |
| | | result: result, |
| | | searchValue: this.searchValue |
| | | fsubmit: fsubmit, |
| | | searchValue: this.searchValue, |
| | | SelectedIndex: this.optionsIndex |
| | | } |
| | | }).then(res => { |
| | | console.log('API响应数据:', res); |
| | | console.log('当前标签页:', this.current, 'FSUBMIT参数:', fsubmit); |
| | | |
| | | if (this.pageIndex === 1) { |
| | | // 如果是第一页,直接覆盖原数据 |
| | | this.data = res.data.tbBillList; |
| | | console.log('加载的数据:', this.data); |
| | | // 打印每条数据的FSUBMIT状态 |
| | | this.data.forEach((item, index) => { |
| | | console.log(`数据${index}: ID=${item.id}, FSUBMIT=${item.fsubmit}, FcheckResu=${item.fcheckResu}`); |
| | | }); |
| | | } else { |
| | | if (res.data.tbBillList.length > 0) { |
| | | // 如果是下一页,追加新数据 |
| | |
| | | this.noData = this.pageIndex >= this.totalPage; |
| | | this.isLoading = false; // 结束加载 |
| | | |
| | | // 更新计数 |
| | | // 更新计数 - 参考SJ的实现方式 |
| | | if (this.current === 1) { |
| | | this.checkedCount = this.totalCount; |
| | | this.checkedCount = '已完成(' + this.totalCount + ')'; |
| | | } else { |
| | | this.uncheckedCount = this.totalCount; |
| | | } |
| | |
| | | |
| | | /* 顶部筛选区 */ |
| | | .filter-section { |
| | | /* margin-bottom: 24px; */ |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | /* 搜索框样式 */ |
| | |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 5px; |
| | | } |
| | | |
| | | .dropdown-filter { |
| | | min-width: 70px; |
| | | } |
| | | |
| | | .picker { |
| | | padding: 8px 12px; |
| | | border: 1px solid #ddd; |
| | | border-radius: 4px; |
| | | background-color: white; |
| | | font-size: 14px; |
| | | min-width: 120px; |
| | | } |
| | | |
| | | .status-tabs { |
| | |
| | | transform: translateY(0); |
| | | } |
| | | |
| | | /* 添加按钮样式 */ |
| | | .plus-button { |
| | | position: fixed; |
| | | bottom: 20px; |
| | | right: 20px; |
| | | width: 60px; |
| | | height: 60px; |
| | | border-radius: 50%; |
| | | background: linear-gradient(135deg, #3498db, #2980b9); |
| | | color: #ffffff; |
| | | text-align: center; |
| | | line-height: 59px; |
| | | font-size: 24px; |
| | | cursor: pointer; |
| | | z-index: 1000; |
| | | box-shadow: 0 4px 12px rgba(52, 152, 219, 0.4); |
| | | transition: all 0.3s ease; |
| | | } |
| | | |
| | | .plus-button:hover { |
| | | transform: translateY(-2px); |
| | | box-shadow: 0 6px 16px rgba(52, 152, 219, 0.5); |
| | | } |
| | | |
| | | .plus-button:active { |
| | | transform: translateY(0); |
| | | } |
| | | |
| | | /* 响应式设计 */ |
| | | @media (min-width: 768px) { |
| | |
| | | </view> |
| | | |
| | | <view class="input-group input1"> |
| | | <view class="input-wrapper"> |
| | | <input v-if="tableData.length < formData.levelNum" class="result-input" type="number" v-model="formData.fcheckResu" placeholder="请输入检验结果..."/> |
| | | <button v-if="tableData.length < formData.levelNum" class="btn primary-btn" @click="submit">保存结果</button> |
| | | <button class="btn upload-btn" @click="previewImage" v-if="isShowImg"> |
| | | <uni-icons type="image" size="16" color="#fff"></uni-icons> |
| | | 查看图片 |
| | | <view class="input-wrapper llj-flex-row"> |
| | | <input v-if="tableData.length < formData.levelNum" |
| | | class="result-input" |
| | | type="number" |
| | | v-model="formData.fcheckResu" |
| | | placeholder="请输入检验结果..." /> |
| | | <button v-if="tableData.length < formData.levelNum" |
| | | class="llj-btn llj-btn-save" |
| | | @click="submit">保存结果</button> |
| | | <button |
| | | class="llj-btn llj-btn-image" |
| | | @click="previewImage" |
| | | v-if="isShowImg" |
| | | > |
| | | <uni-icons type="image" size="20" color="#fff" style="margin-right:6px;"/> |
| | | 上传/查看图片 |
| | | </button> |
| | | <button class="btn upload-btn" @click="saveRemarks"> |
| | | <uni-icons type="compose" size="16" color="#fff"></uni-icons> |
| | | <button |
| | | class="llj-btn llj-btn-desc" |
| | | @click="saveRemarks"> |
| | | <uni-icons type="compose" size="20" color="#fff" style="margin-right:6px;"/> |
| | | 不合格描述 |
| | | </button> |
| | | <view v-if="formData.remarks" class="llj-desc-tag"> |
| | | {{ formData.remarks.length > 10 ? formData.remarks.substr(0,10)+'...' : formData.remarks }} |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | |
| | | |
| | | <!-- NG/OK状态样式 --> |
| | | <view v-else class="simple-status-result"> |
| | | <view class="simple-status" :class="{'pass': item.fcheckResu === '1', 'fail': item.fcheckResu !== '1'}"> |
| | | {{ item.fcheckResu === '1' ? '合格' : '不合格' }} |
| | | <view class="simple-status" :class="{'pass': item.fcheckResu == 1 || item.fcheckResu == 'OK' || item.fcheckResu == 'ok', 'fail': item.fcheckResu != 1 && item.fcheckResu != 'OK' && item.fcheckResu != 'ok'}"> |
| | | {{ (item.fcheckResu == 1 || item.fcheckResu == 'OK' || item.fcheckResu == 'ok') ? '合格' : '不合格' }} |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | <form> |
| | | <view class="form-group"> |
| | | <label class="form-label">不合格描述:</label> |
| | | <input class="form-input" type="text" v-model="remarks" placeholder="请输入不合格描述"/> |
| | | <input class="form-input" type="text" v-model="remarks" placeholder="请输入不合格描述,留空表示清除描述"/> |
| | | </view> |
| | | <view class="popup-buttons"> |
| | | <button type="warn" class="btn primary-btn" @click="editRemarks">修改</button> |
| | |
| | | <input class="form-input" type="text" v-model="editData.fcheckResu" placeholder="请输入检验结果"/> |
| | | </view> |
| | | <view class="popup-buttons"> |
| | | <button type="warn" class="btn primary-btn" @click="eidt">修改</button> |
| | | <button type="warn" class="btn primary-btn" @click="edit">修改</button> |
| | | <button class="btn cancel-btn" @click="showPopup = !showPopup">取消</button> |
| | | </view> |
| | | </form> |
| | |
| | | }); |
| | | }, |
| | | editResult(fcheckResu) { |
| | | if (fcheckResu == '1') { |
| | | if (fcheckResu == '1' || fcheckResu == 'OK' || fcheckResu == 'ok') { |
| | | return "改为不合格"; |
| | | } else { |
| | | return "改为合格"; |
| | |
| | | this.$post({ |
| | | url: "/XJ/getXjDetail02ById", |
| | | data: { |
| | | pid: this.id |
| | | id: this.id |
| | | } |
| | | }).then(res => { |
| | | this.formData = res.data.tbBillList.itemXj01; |
| | |
| | | this.showPopup = !this.showPopup; |
| | | this.editData = item; |
| | | }, |
| | | eidt() { |
| | | edit() { |
| | | |
| | | if (!this.editData.fcheckResu) { |
| | | this.$showMessage("请输入检验结果"); |
| | | return; |
| | | } |
| | | |
| | | if (this.formData.fcheckResu == this.editData.fcheckResu) { |
| | | this.$showMessage("修改成功"); |
| | | // 检查是否有实际修改 |
| | | const originalValue = this.tableData.find(item => item.id === this.editData.id)?.fcheckResu; |
| | | if (originalValue == this.editData.fcheckResu) { |
| | | this.$showMessage("没有修改"); |
| | | return; |
| | | } |
| | | |
| | |
| | | let fstand = "√"; |
| | | let fcheckResu = 1; |
| | | |
| | | if (item.fcheckResu == '1') { |
| | | if (item.fcheckResu == '1' || item.fcheckResu == 'OK' || item.fcheckResu == 'ok') { |
| | | fstand = "×"; |
| | | fcheckResu = 0; |
| | | } |
| | |
| | | this.remarks = this.formData.remarks; |
| | | }, |
| | | editRemarks() { |
| | | if (this.remarks) { |
| | | //saveRemarksGid |
| | | this.$post({ |
| | | url: "/XJ/saveRemarksPid", |
| | | data: { |
| | | pid: this.formData.id, |
| | | remarks: this.remarks |
| | | } |
| | | }).then(res => { |
| | | if (res.data.tbBillList > 0) { |
| | | this.formData.remarks = this.remarks; |
| | | this.remarksPopup = !this.remarksPopup; |
| | | this.$showMessage("保存成功"); |
| | | } |
| | | }) |
| | | } |
| | | // 允许留空,留空代表清除描述 |
| | | this.$post({ |
| | | url: "/XJ/saveRemarksPid", |
| | | data: { |
| | | pid: this.formData.id, |
| | | remarks: this.remarks || "" // 留空时传递空字符串 |
| | | } |
| | | }).then(res => { |
| | | if (res.data.tbBillList > 0) { |
| | | this.formData.remarks = this.remarks || ""; // 更新本地数据 |
| | | this.remarksPopup = !this.remarksPopup; |
| | | this.$showMessage(this.remarks ? "保存成功" : "描述已清除"); |
| | | } |
| | | }).catch(error => { |
| | | this.$showMessage("保存失败,请重试"); |
| | | }); |
| | | }, |
| | | // 判断数字是否在范围内 |
| | | isInRange(value) { |
| | |
| | | } |
| | | } |
| | | |
| | | /* LLJ风格样式 */ |
| | | .llj-flex-row { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 12px; |
| | | align-items: center; |
| | | } |
| | | |
| | | .llj-btn { |
| | | padding: 10px 16px; |
| | | border: none; |
| | | border-radius: 6px; |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | cursor: pointer; |
| | | transition: all 0.3s ease; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | min-width: 100px; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); |
| | | } |
| | | |
| | | .llj-btn-save { |
| | | background: linear-gradient(135deg, #667eea, #764ba2); |
| | | color: #fff; |
| | | } |
| | | |
| | | .llj-btn-save:hover { |
| | | background: linear-gradient(135deg, #5a6fd8, #6a4190); |
| | | transform: translateY(-1px); |
| | | box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4); |
| | | } |
| | | |
| | | .llj-btn-image { |
| | | background: linear-gradient(135deg, #f093fb, #f5576c); |
| | | color: #fff; |
| | | } |
| | | |
| | | .llj-btn-image:hover { |
| | | background: linear-gradient(135deg, #e879f9, #f43f5e); |
| | | transform: translateY(-1px); |
| | | box-shadow: 0 4px 12px rgba(240, 147, 251, 0.4); |
| | | } |
| | | |
| | | .llj-btn-desc { |
| | | background: linear-gradient(135deg, #4facfe, #00f2fe); |
| | | color: #fff; |
| | | } |
| | | |
| | | .llj-btn-desc:hover { |
| | | background: linear-gradient(135deg, #3d8bfe, #00d4fe); |
| | | transform: translateY(-1px); |
| | | box-shadow: 0 4px 12px rgba(79, 172, 254, 0.4); |
| | | } |
| | | |
| | | .llj-desc-tag { |
| | | background: linear-gradient(135deg, #ffecd2, #fcb69f); |
| | | color: #8b4513; |
| | | padding: 6px 12px; |
| | | border-radius: 20px; |
| | | font-size: 12px; |
| | | font-weight: 600; |
| | | border: 1px solid #fcb69f; |
| | | max-width: 200px; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | /* 简洁表格样式 - 适合年长用户 */ |
| | | .simple-table-container { |
| | | margin: 20px 0; |