| | |
| | | <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> |