| | |
| | | data: query, |
| | | }) |
| | | } |
| | | |
| | | |
| | | // å·¥åºæ¥è¯¢ |
| | | export function list() { |
| | | return request({ |
| | | url: "/productProcess/list", |
| | | method: "get", |
| | | }); |
| | | } |
| | |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/qualityManagement/processInspection/index", |
| | | "style": { |
| | | "navigationBarTitleText": "è¿ç¨æ£éª", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/qualityManagement/processInspection/add", |
| | | "style": { |
| | | "navigationBarTitleText": "è¿ç¨æ£éªæ·»å ", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/qualityManagement/processInspection/detail", |
| | | "style": { |
| | | "navigationBarTitleText": "è¿ç¨æ£éªè¯¦æ
", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/qualityManagement/processInspection/fileList", |
| | | "style": { |
| | | "navigationBarTitleText": "è¿ç¨æ£éªéä»¶", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/qualityManagement/finalInspection/index", |
| | | "style": { |
| | | "navigationBarTitleText": "åºåæ£éª", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/qualityManagement/finalInspection/add", |
| | | "style": { |
| | | "navigationBarTitleText": "åºåæ£éªæ·»å ", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/qualityManagement/finalInspection/detail", |
| | | "style": { |
| | | "navigationBarTitleText": "åºåæ£éªè¯¦æ
", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/qualityManagement/finalInspection/fileList", |
| | | "style": { |
| | | "navigationBarTitleText": "åºåæ£éªéä»¶", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/message", |
| | | "style": { |
| | | "navigationBarTitleText": "æ¶æ¯ä¸å¿" |
| | |
| | | icon: "/static/images/icon/caigoutaizhang@2x.png", |
| | | label: "åæææ£éª", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/caigoutaizhang@2x.png", |
| | | label: "è¿ç¨æ£éª", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/caigoutaizhang@2x.png", |
| | | label: "åºåæ£éª", |
| | | }, |
| | | ]); |
| | | const safetyItems = reactive([ |
| | | { |
| | |
| | | url: "/pages/qualityManagement/materialInspection/index", |
| | | }); |
| | | break; |
| | | case "è¿ç¨æ£éª": |
| | | uni.navigateTo({ |
| | | url: "/pages/qualityManagement/processInspection/index", |
| | | }); |
| | | break; |
| | | case "åºåæ£éª": |
| | | uni.navigateTo({ |
| | | url: "/pages/qualityManagement/finalInspection/index", |
| | | }); |
| | | break; |
| | | default: |
| | | uni.showToast({ |
| | | title: `ç¹å»äº${item.label}`, |
| | |
| | | // è¿æ»¤è´¨é管çèå |
| | | const originalQuality = [ |
| | | { icon: "/static/images/icon/caigoutaizhang@2x.png", label: "åæææ£éª" }, |
| | | { icon: "/static/images/icon/caigoutaizhang@2x.png", label: "è¿ç¨æ£éª" }, |
| | | { icon: "/static/images/icon/caigoutaizhang@2x.png", label: "åºåæ£éª" }, |
| | | ]; |
| | | const filteredQuality = originalQuality.filter(item => { |
| | | return allowedMenuTitles.has(item.label); |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="material-inspection-add"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader :title="isEdit ? 'ç¼è¾åºåæ£éª' : 'æ°å¢åºåæ£éª'" |
| | | @back="goBack" /> |
| | | <!-- 表åå
容 --> |
| | | <up-form :model="form" |
| | | ref="formRef" |
| | | label-width="110" |
| | | :rules="rules"> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <!-- <up-form-item label="å·¥åº" |
| | | prop="process" |
| | | required |
| | | border-bottom> |
| | | <up-input v-model="form.process" |
| | | placeholder="è¯·éæ©å·¥åº" |
| | | readonly |
| | | :disabled="processQuantityDisabled" /> |
| | | <template #right> |
| | | <up-icon @click="showprocessSheet = true" |
| | | name="arrow-right" /> |
| | | </template> |
| | | </up-form-item> --> |
| | | <up-form-item label="产ååç§°" |
| | | prop="productId" |
| | | required |
| | | border-bottom> |
| | | <up-input v-model="form.productName" |
| | | placeholder="è¯·éæ©äº§å" |
| | | readonly |
| | | @click="showProductTree = true" |
| | | :disabled="isEdit" /> |
| | | <template #right> |
| | | <up-icon @click="showProductTree = true" |
| | | name="arrow-right" /> |
| | | </template> |
| | | </up-form-item> |
| | | <up-form-item label="è§æ ¼åå·" |
| | | prop="productModelId" |
| | | required |
| | | border-bottom> |
| | | <up-input v-model="form.model" |
| | | placeholder="è¯·éæ©è§æ ¼åå·" |
| | | readonly |
| | | :disabled="isEdit" /> |
| | | <template #right> |
| | | <up-icon @click="showModelSheet = true" |
| | | name="arrow-right" /> |
| | | </template> |
| | | </up-form-item> |
| | | <up-form-item label="ææ éæ©" |
| | | prop="testStandardId" |
| | | border-bottom> |
| | | <up-input v-model="testStandardDisplay" |
| | | placeholder="è¯·éæ©ææ " |
| | | readonly /> |
| | | <template #right> |
| | | <up-icon @click="openTestStandardSheet" |
| | | name="arrow-right" /> |
| | | </template> |
| | | </up-form-item> |
| | | <up-form-item label="åä½" |
| | | prop="unit" |
| | | border-bottom> |
| | | <up-input v-model="form.unit" |
| | | placeholder="请è¾å
¥åä½" |
| | | disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="æ°é" |
| | | prop="quantity" |
| | | required |
| | | border-bottom> |
| | | <up-input v-model="form.quantity" |
| | | type="number" |
| | | placeholder="请è¾å
¥æ°é" |
| | | :disabled="processQuantityDisabled" /> |
| | | </up-form-item> |
| | | <up-form-item label="æ£æµåä½" |
| | | prop="checkCompany" |
| | | border-bottom> |
| | | <up-input v-model="form.checkCompany" |
| | | placeholder="请è¾å
¥æ£æµåä½" |
| | | clearable /> |
| | | </up-form-item> |
| | | <up-form-item label="æ£æµç»æ" |
| | | prop="checkResult" |
| | | required |
| | | border-bottom> |
| | | <up-input v-model="form.checkResult" |
| | | placeholder="è¯·éæ©æ£æµç»æ" |
| | | readonly |
| | | @click="showResultSheet" /> |
| | | <template #right> |
| | | <up-icon @click="showResultSheet = true" |
| | | name="arrow-right" /> |
| | | </template> |
| | | </up-form-item> |
| | | <up-form-item label="æ£éªå" |
| | | prop="checkName" |
| | | border-bottom> |
| | | <up-input v-model="form.checkName" |
| | | placeholder="è¯·éæ©æ£éªå" |
| | | readonly |
| | | @click="showInspectorSheet" /> |
| | | <template #right> |
| | | <up-icon @click="showInspectorSheet = true" |
| | | name="arrow-right" /> |
| | | </template> |
| | | </up-form-item> |
| | | <up-form-item label="æ£æµæ¥æ" |
| | | prop="checkTime" |
| | | required |
| | | border-bottom> |
| | | <up-input v-model="form.checkTime" |
| | | placeholder="è¯·éæ©æ£æµæ¥æ" |
| | | readonly /> |
| | | <!-- <template #right> |
| | | <up-icon name="calendar" |
| | | @click="showDatePicker"></up-icon> |
| | | </template> --> |
| | | </up-form-item> |
| | | <!-- æ£éªé¡¹ç® --> |
| | | <view class="inspection-items-container"> |
| | | <view class="steps-header"> |
| | | <text class="steps-title">æ£éªé¡¹ç®</text> |
| | | <text class="steps-count">å
± {{ tableData.length }} 个项ç®</text> |
| | | </view> |
| | | <view class="steps-list"> |
| | | <view v-for="(item, index) in tableData" |
| | | :key="index" |
| | | class="exec-step-item"> |
| | | <view class="step-number"> |
| | | {{ index + 1 }} |
| | | </view> |
| | | <view class="step-content"> |
| | | <view class="step-row"> |
| | | <text class="step-label">ææ ï¼</text> |
| | | <text class="step-value">{{ item.parameterItem }}</text> |
| | | </view> |
| | | <view class="step-row"> |
| | | <text class="step-label">åä½ï¼</text> |
| | | <text class="step-value">{{ item.unit }}</text> |
| | | </view> |
| | | <view class="step-row"> |
| | | <text class="step-label">æ åå¼ï¼</text> |
| | | <text class="step-value">{{ item.standardValue }}</text> |
| | | </view> |
| | | <view class="step-row"> |
| | | <text class="step-label">å
æ§å¼ï¼</text> |
| | | <text class="step-value">{{ item.controlValue }}</text> |
| | | </view> |
| | | <view class="step-row"> |
| | | <text class="step-label">æ£éªå¼ï¼</text> |
| | | <up-input v-model="item.testValue" |
| | | placeholder="请è¾å
¥æ£éªå¼" |
| | | clearable |
| | | border-bottom |
| | | class="step-input" /> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-if="tableData.length === 0" |
| | | class="empty-data"> |
| | | <text>请å
éæ©ææ </text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </up-form> |
| | | <!-- åºé¨æé® --> |
| | | <view class="bottom-buttons"> |
| | | <up-button type="default" |
| | | size="default" |
| | | @click="goBack" |
| | | class="bottom-btn"> |
| | | åæ¶ |
| | | </up-button> |
| | | <up-button type="primary" |
| | | size="default" |
| | | @click="submitForm" |
| | | :loading="loading" |
| | | class="bottom-btn"> |
| | | {{ isEdit ? 'ä¿å' : 'æäº¤' }} |
| | | </up-button> |
| | | </view> |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <up-popup v-model:show="showDate" |
| | | mode="date" |
| | | :start-year="2020" |
| | | :end-year="2030" |
| | | @confirm="confirmDate" /> |
| | | <!-- å·¥åºéæ© --> |
| | | <up-action-sheet :show="showprocessSheet" |
| | | :actions="processOptions" |
| | | @select="selectprocess" |
| | | @close="showprocessSheet = false" |
| | | title="鿩工åº" /> |
| | | <!-- 产åéæ© --> |
| | | <up-action-sheet :show="showProductSheet" |
| | | :actions="productSheetOptions" |
| | | @select="selectProduct" |
| | | @close="showProductSheet = false" |
| | | title="éæ©äº§å" /> |
| | | <!-- è§æ ¼åå·éæ© --> |
| | | <up-action-sheet :show="showModelSheet" |
| | | :actions="modelSheetOptions" |
| | | @select="selectModel" |
| | | @close="showModelSheet = false" |
| | | title="éæ©è§æ ¼åå·" /> |
| | | <!-- æ£æµç»æéæ© --> |
| | | <up-action-sheet :show="showResultSheet" |
| | | :actions="resultSheetOptions" |
| | | @select="selectResult" |
| | | @close="showResultSheet = false" |
| | | title="éæ©æ£æµç»æ" /> |
| | | <!-- æ£éªåéæ© --> |
| | | <up-action-sheet :show="showInspectorSheet" |
| | | :actions="userSheetOptions" |
| | | @select="selectInspector" |
| | | @close="showInspectorSheet = false" |
| | | title="éæ©æ£éªå" /> |
| | | <!-- ææ éæ© --> |
| | | <up-action-sheet :show="showTestStandardSheet" |
| | | :actions="testStandardSheetOptions" |
| | | @select="selectTestStandard" |
| | | @close="showTestStandardSheet = false" |
| | | title="éæ©ææ " /> |
| | | <!-- äº§åæ å½¢éæ©å¨ --> |
| | | <up-popup v-model:show="showProductTree" |
| | | position="bottom" |
| | | :round="true" |
| | | :closeable="true" |
| | | @close="showProductTree = false"> |
| | | <view class="tree-selector"> |
| | | <view class="tree-header"> |
| | | <text class="tree-title">éæ©äº§å</text> |
| | | </view> |
| | | <view class="tree-content"> |
| | | <view class="tree-node" |
| | | v-for="(node, index) in productOptions" |
| | | :key="index"> |
| | | <view v-if="node.children && node.children.length > 0" |
| | | class="tree-node-header" |
| | | @click="toggleNode(node)"> |
| | | <up-icon :name="node.expanded ? 'arrow-down' : 'arrow-right'" |
| | | class="tree-node-icon" /> |
| | | <text class="tree-node-label">{{ node.label }}</text> |
| | | </view> |
| | | <view v-else |
| | | class="tree-node-header" |
| | | @click="selectTreeNode(node)"> |
| | | <text class="tree-node-icon-placeholder"></text> |
| | | <text class="tree-node-label">{{ node.label }}</text> |
| | | <up-icon name="checkmark" |
| | | v-if="form.productId == node.value" |
| | | class="tree-node-check" /> |
| | | </view> |
| | | <view v-if="node.children && node.children.length > 0 && node.expanded" |
| | | class="tree-node-children"> |
| | | <view class="tree-node" |
| | | v-for="(child, childIndex) in node.children" |
| | | :key="childIndex"> |
| | | <view v-if="child.children && child.children.length > 0" |
| | | class="tree-node-header" |
| | | @click="toggleNode(child)"> |
| | | <up-icon :name="child.expanded ? 'arrow-down' : 'arrow-right'" |
| | | class="tree-node-icon" /> |
| | | <text class="tree-node-label">{{ child.label }}</text> |
| | | </view> |
| | | <view v-else |
| | | class="tree-node-header" |
| | | @click="selectTreeNode(child)"> |
| | | <text class="tree-node-icon-placeholder"></text> |
| | | <text class="tree-node-label">{{ child.label }}</text> |
| | | <up-icon name="checkmark" |
| | | v-if="form.productId == child.value" |
| | | class="tree-node-check" /> |
| | | </view> |
| | | <view v-if="child.children && child.children.length > 0 && child.expanded" |
| | | class="tree-node-children"> |
| | | <view class="tree-node" |
| | | v-for="(grandchild, grandchildIndex) in child.children" |
| | | :key="grandchildIndex"> |
| | | <view class="tree-node-header" |
| | | @click="selectTreeNode(grandchild)"> |
| | | <text class="tree-node-icon-placeholder"></text> |
| | | <text class="tree-node-label">{{ grandchild.label }}</text> |
| | | <up-icon name="checkmark" |
| | | v-if="form.productId == grandchild.value" |
| | | class="tree-node-check" /> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </up-popup> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, computed, onMounted, nextTick } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import dayjs from "dayjs"; |
| | | import { getOptions } from "@/api/procurementManagement/procurementLedger.js"; |
| | | import { modelList, productTreeList } from "@/api/basicData/product.js"; |
| | | import { |
| | | qualityInspectAdd, |
| | | qualityInspectUpdate, |
| | | qualityInspectParamInfo, |
| | | qualityInspectDetailByProductId, |
| | | getQualityTestStandardParamByTestStandardId, |
| | | list, |
| | | } from "@/api/qualityManagement/materialInspection.js"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | |
| | | // æ¾ç¤ºæç¤ºä¿¡æ¯ |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | // 表åå¼ç¨ |
| | | const formRef = ref(null); |
| | | // å è½½ç¶æ |
| | | const loading = ref(false); |
| | | // æ¥æéæ©å¨ |
| | | const showDate = ref(false); |
| | | // å·¥åºéæ© |
| | | const showprocessSheet = ref(false); |
| | | // 产åéæ© |
| | | const showProductSheet = ref(false); |
| | | // äº§åæ å½¢éæ©å¨ |
| | | const showProductTree = ref(false); |
| | | // è§æ ¼åå·éæ© |
| | | const showModelSheet = ref(false); |
| | | // æ£æµç»æéæ© |
| | | const showResultSheet = ref(false); |
| | | // æ£éªåéæ© |
| | | const showInspectorSheet = ref(false); |
| | | // ææ éæ© |
| | | const showTestStandardSheet = ref(false); |
| | | |
| | | // è¡¨åæ°æ® |
| | | const form = ref({ |
| | | checkTime: dayjs().format("YYYY-MM-DD"), |
| | | process: "", |
| | | checkName: "", |
| | | productName: "", |
| | | productId: "", |
| | | productModelId: "", |
| | | model: "", |
| | | testStandardId: "", |
| | | unit: "", |
| | | quantity: "", |
| | | checkCompany: "", |
| | | checkResult: "", |
| | | productMainId: null, |
| | | purchaseLedgerId: null, |
| | | }); |
| | | |
| | | // æ¾ç¤ºç¨çåé |
| | | const testStandardDisplay = ref(""); |
| | | |
| | | // æ£éªé¡¹ç® |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | |
| | | // å·¥åºå表 |
| | | const processList = ref([]); |
| | | // 产åé项 |
| | | const productOptions = ref([]); |
| | | // åå·é项 |
| | | const modelOptions = ref([]); |
| | | // æ£éªåå表 |
| | | const userList = ref([]); |
| | | // æ£æµç»æé项 |
| | | const resultOptions = ref([ |
| | | { label: "åæ ¼", value: "åæ ¼" }, |
| | | { label: "ä¸åæ ¼", value: "ä¸åæ ¼" }, |
| | | ]); |
| | | // ææ é项 |
| | | const testStandardOptions = ref([]); |
| | | // å½å产åID |
| | | const currentProductId = ref(0); |
| | | |
| | | // ActionSheeté项 |
| | | const processOptions = computed(() => { |
| | | return processList.value.map(item => ({ |
| | | name: item.name, |
| | | value: item.name, |
| | | })); |
| | | }); |
| | | |
| | | const productSheetOptions = computed(() => { |
| | | return productOptions.value.map(item => ({ |
| | | name: item.label, |
| | | value: item.value, |
| | | })); |
| | | }); |
| | | |
| | | const modelSheetOptions = computed(() => { |
| | | return modelOptions.value.map(item => ({ |
| | | name: item.model, |
| | | value: item.id, |
| | | })); |
| | | }); |
| | | |
| | | const resultSheetOptions = computed(() => { |
| | | return resultOptions.value.map(item => ({ |
| | | name: item.label, |
| | | value: item.value, |
| | | })); |
| | | }); |
| | | |
| | | const userSheetOptions = computed(() => { |
| | | return userList.value.map(item => ({ |
| | | name: item.nickName, |
| | | value: item.nickName, |
| | | })); |
| | | }); |
| | | |
| | | const testStandardSheetOptions = computed(() => { |
| | | return testStandardOptions.value.map(item => ({ |
| | | name: item.standardName || item.standardNo, |
| | | value: item.id, |
| | | })); |
| | | }); |
| | | |
| | | // 表åéªè¯è§å |
| | | const rules = { |
| | | checkTime: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | process: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | checkName: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | productId: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | productModelId: [ |
| | | { required: true, message: "è¯·éæ©äº§ååå·", trigger: "change" }, |
| | | ], |
| | | testStandardId: [ |
| | | { required: false, message: "è¯·éæ©ææ ", trigger: "change" }, |
| | | ], |
| | | unit: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | quantity: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | checkCompany: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | checkResult: [ |
| | | { required: true, message: "è¯·éæ©æ£æµç»æ", trigger: "change" }, |
| | | ], |
| | | }; |
| | | |
| | | // æ¯å¦ä¸ºç¼è¾æ¨¡å¼ |
| | | const isEdit = computed(() => { |
| | | const id = getPageId(); |
| | | return !!id; |
| | | }); |
| | | |
| | | // ç¼è¾æ¶ï¼productMainId æ purchaseLedgerId 任䏿å¼åå·¥åºãæ°éç½®ç° |
| | | const processQuantityDisabled = computed(() => { |
| | | const v = form.value || {}; |
| | | return !!(v.productMainId != null || v.purchaseLedgerId != null); |
| | | }); |
| | | |
| | | // è·å页é¢ID |
| | | const getPageId = () => { |
| | | const pages = getCurrentPages(); |
| | | const currentPage = pages[pages.length - 1]; |
| | | return currentPage.options.id; |
| | | }; |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // æ¾ç¤ºæ¥æéæ©å¨ |
| | | const showDatePicker = () => { |
| | | showDate.value = true; |
| | | }; |
| | | |
| | | // ç¡®è®¤æ¥æéæ© |
| | | const confirmDate = e => { |
| | | form.value.checkTime = dayjs(e.value).format("YYYY-MM-DD"); |
| | | }; |
| | | |
| | | // éæ©å·¥åº |
| | | const selectprocess = e => { |
| | | form.value.process = e.value; |
| | | showprocessSheet.value = false; |
| | | }; |
| | | |
| | | // éæ©äº§å |
| | | const selectProduct = e => { |
| | | form.value.productId = e.value; |
| | | form.value.productName = e.name; |
| | | showProductSheet.value = false; |
| | | getModels(e.value); |
| | | }; |
| | | |
| | | // 忢æ å½¢èç¹å±å¼/æå |
| | | const toggleNode = node => { |
| | | node.expanded = !node.expanded; |
| | | }; |
| | | |
| | | // éæ©æ å½¢èç¹ |
| | | const selectTreeNode = node => { |
| | | // ç¡®ä¿åªéæ©æ«ç«¯èç¹ |
| | | if (!node.children || node.children.length == 0) { |
| | | form.value.productId = node.value; |
| | | form.value.productName = node.label; |
| | | showProductTree.value = false; |
| | | getModels(node.value); |
| | | } |
| | | }; |
| | | |
| | | // 转æ¢äº§åæ ç»æ |
| | | function convertIdToValue(data) { |
| | | return data.map(item => { |
| | | const { id, children, ...rest } = item; |
| | | const newItem = { |
| | | ...rest, |
| | | value: id, // å° id æ¹ä¸º value |
| | | }; |
| | | if (children && children.length > 0) { |
| | | newItem.children = convertIdToValue(children); |
| | | } |
| | | |
| | | return newItem; |
| | | }); |
| | | } |
| | | |
| | | // æ ¹æ®IDæ¥æ¾èç¹ |
| | | const findNodeById = (nodes, productId) => { |
| | | for (let i = 0; i < nodes.length; i++) { |
| | | if (nodes[i].value === productId) { |
| | | return nodes[i].label; // æ¾å°èç¹ï¼è¿å该èç¹ |
| | | } |
| | | if (nodes[i].children && nodes[i].children.length > 0) { |
| | | const foundNode = findNodeById(nodes[i].children, productId); |
| | | if (foundNode) { |
| | | return foundNode; // å¨åèç¹ä¸æ¾å°ï¼è¿å该èç¹ |
| | | } |
| | | } |
| | | } |
| | | return null; // æ²¡ææ¾å°èç¹ï¼è¿ånull |
| | | }; |
| | | |
| | | // éæ©è§æ ¼åå· |
| | | const selectModel = e => { |
| | | form.value.productModelId = e.value; |
| | | showModelSheet.value = false; |
| | | handleChangeModel(e.value); |
| | | }; |
| | | |
| | | // å¤çåå·åå |
| | | const handleChangeModel = value => { |
| | | form.value.model = |
| | | modelOptions.value.find(item => item.id == value)?.model || ""; |
| | | form.value.unit = |
| | | modelOptions.value.find(item => item.id == value)?.unit || ""; |
| | | }; |
| | | |
| | | // éæ©æ£æµç»æ |
| | | const selectResult = e => { |
| | | form.value.checkResult = e.value; |
| | | showResultSheet.value = false; |
| | | }; |
| | | |
| | | // éæ©æ£éªå |
| | | const selectInspector = e => { |
| | | form.value.checkName = e.value; |
| | | showInspectorSheet.value = false; |
| | | }; |
| | | |
| | | // éæ©ææ |
| | | const selectTestStandard = e => { |
| | | form.value.testStandardId = e.value; |
| | | testStandardDisplay.value = e.name; |
| | | showTestStandardSheet.value = false; |
| | | handleTestStandardChange(e.value); |
| | | }; |
| | | |
| | | // ææ éæ©ååå¤ç |
| | | const handleTestStandardChange = testStandardId => { |
| | | if (!testStandardId) { |
| | | tableData.value = []; |
| | | return; |
| | | } |
| | | tableLoading.value = true; |
| | | getQualityTestStandardParamByTestStandardId(testStandardId) |
| | | .then(res => { |
| | | tableData.value = res.data || []; |
| | | }) |
| | | .catch(error => { |
| | | console.error("è·åæ ååæ°å¤±è´¥:", error); |
| | | tableData.value = []; |
| | | }) |
| | | .finally(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | const openTestStandardSheet = () => { |
| | | console.log("openTestStandardSheet"); |
| | | showTestStandardSheet.value = true; |
| | | }; |
| | | |
| | | // è·åå·¥åºå表 |
| | | const getprocessList = () => { |
| | | list().then(res => { |
| | | processList.value = res.data; |
| | | }); |
| | | }; |
| | | |
| | | // è·å产åé项 |
| | | const getProductOptions = () => { |
| | | return productTreeList().then(res => { |
| | | productOptions.value = convertIdToValue(res); |
| | | return productOptions.value; |
| | | }); |
| | | }; |
| | | |
| | | // è·åç¨æ·å表 |
| | | const getUserList = async () => { |
| | | try { |
| | | const userRes = await userListNoPage(); |
| | | userList.value = userRes.data || []; |
| | | } catch (e) { |
| | | console.error("å è½½æ£éªåå表失败", e); |
| | | userList.value = []; |
| | | } |
| | | }; |
| | | |
| | | // è·ååå·å表 |
| | | const getModels = value => { |
| | | form.value.productModelId = ""; |
| | | form.value.unit = ""; |
| | | modelOptions.value = []; |
| | | currentProductId.value = value; |
| | | form.value.productName = findNodeById(productOptions.value, value); |
| | | modelList({ id: value }).then(res => { |
| | | modelOptions.value = res; |
| | | }); |
| | | if (currentProductId.value) { |
| | | getList(); |
| | | } |
| | | }; |
| | | |
| | | // è·åææ å表 |
| | | const getList = () => { |
| | | if (!currentProductId.value) { |
| | | testStandardOptions.value = []; |
| | | tableData.value = []; |
| | | return; |
| | | } |
| | | let params = { |
| | | productId: currentProductId.value, |
| | | inspectType: 2, |
| | | }; |
| | | qualityInspectDetailByProductId(params).then(res => { |
| | | // ä¿å䏿æ¡éé¡¹æ°æ® |
| | | testStandardOptions.value = res.data || []; |
| | | // æ¸
ç©ºè¡¨æ ¼æ°æ®ï¼çå¾
ç¨æ·éæ©ææ |
| | | tableData.value = []; |
| | | // æ¸
ç©ºææ éæ© |
| | | form.value.testStandardId = ""; |
| | | testStandardDisplay.value = ""; |
| | | }); |
| | | }; |
| | | |
| | | // è·åæ£éªåæ°å表ï¼ç¼è¾æ¨¡å¼ï¼ |
| | | const getQualityInspectParamList = id => { |
| | | qualityInspectParamInfo(id).then(res => { |
| | | tableData.value = res.data; |
| | | }); |
| | | }; |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = async () => { |
| | | console.log("submitForm", form.value, tableData.value); |
| | | try { |
| | | // await formRef.value.validate(); |
| | | if (!form.value.productModelId) { |
| | | showToast("è¯·éæ©è§æ ¼åå·"); |
| | | return; |
| | | } |
| | | // if (!form.value.process) { |
| | | // showToast("è¯·éæ©å·¥åº"); |
| | | // return; |
| | | // } |
| | | if (!form.value.quantity) { |
| | | showToast("请è¾å
¥æ°é"); |
| | | return; |
| | | } |
| | | if (!form.value.productId) { |
| | | showToast("è¯·éæ©äº§å"); |
| | | return; |
| | | } |
| | | if (!form.value.checkResult) { |
| | | showToast("è¯·éæ©æ£æµç»æ"); |
| | | return; |
| | | } |
| | | |
| | | loading.value = true; |
| | | |
| | | form.value.inspectType = 2; |
| | | if (isEdit.value) { |
| | | tableData.value.forEach(item => { |
| | | delete item.id; |
| | | }); |
| | | } |
| | | |
| | | const data = { ...form.value, qualityInspectParams: tableData.value }; |
| | | data.quantity = Number(data.quantity); |
| | | if (isEdit.value) { |
| | | const res = await qualityInspectUpdate(data); |
| | | showToast("ä¿åæå"); |
| | | setTimeout(() => { |
| | | uni.navigateBack(); |
| | | }, 1500); |
| | | } else { |
| | | const res = await qualityInspectAdd(data); |
| | | showToast("æäº¤æå"); |
| | | setTimeout(() => { |
| | | uni.navigateBack(); |
| | | }, 1500); |
| | | } |
| | | } catch (error) { |
| | | console.error("表åéªè¯å¤±è´¥:", error); |
| | | showToast("æäº¤å¤±è´¥ï¼è¯·éè¯"); |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | |
| | | // åå§å表å |
| | | const initForm = async () => { |
| | | const id = getPageId(); |
| | | if (id) { |
| | | // ç¼è¾æ¨¡å¼ï¼å è½½æ°æ® |
| | | // å
éç½®è¡¨åæ°æ® |
| | | form.value = { |
| | | checkTime: dayjs().format("YYYY-MM-DD"), |
| | | process: "", |
| | | checkName: "", |
| | | productName: "", |
| | | productId: "", |
| | | productModelId: "", |
| | | model: "", |
| | | testStandardId: "", |
| | | unit: "", |
| | | quantity: "", |
| | | checkCompany: "", |
| | | checkResult: "", |
| | | productMainId: null, |
| | | purchaseLedgerId: null, |
| | | }; |
| | | testStandardOptions.value = []; |
| | | tableData.value = []; |
| | | // å
ç¡®ä¿äº§åæ å·²å è½½ï¼å¦åç¼è¾æ¶äº§å/è§æ ¼åå·æ æ³åæ¾ |
| | | await getProductOptions(); |
| | | // 仿¬å°åå¨è·åç¼è¾æ°æ® |
| | | const row = uni.getStorageSync("finalInspectionEditData") || { |
| | | id: id, |
| | | checkTime: "2026-03-03", |
| | | process: "䏿µ·é屿ææéå
¬å¸", |
| | | checkName: "å¼ ä¸", |
| | | productName: "ä¸é颿¿æ", |
| | | productId: 1, |
| | | productModelId: 1, |
| | | model: "304", |
| | | testStandardId: "1", |
| | | unit: "kg", |
| | | quantity: 1000, |
| | | checkCompany: "ç¬¬ä¸æ¹æ£æµæºæ", |
| | | checkResult: "åæ ¼", |
| | | productMainId: null, |
| | | purchaseLedgerId: null, |
| | | }; |
| | | // å
ä¿å testStandardIdï¼é¿å
被æ¸
空 |
| | | const savedTestStandardId = row.testStandardId; |
| | | form.value = { ...row }; |
| | | currentProductId.value = row.productId || 0; |
| | | // å
³é®ï¼ç¼è¾æ¶å è½½è§æ ¼åå·ä¸æéé¡¹ï¼æè½åæ¾ productModelId |
| | | if (currentProductId.value) { |
| | | try { |
| | | const res = await modelList({ id: currentProductId.value }); |
| | | modelOptions.value = res || []; |
| | | // 忥åå¡« model / unit |
| | | if (form.value.productModelId) { |
| | | handleChangeModel(form.value.productModelId); |
| | | } |
| | | } catch (e) { |
| | | console.error("å è½½è§æ ¼åå·å¤±è´¥", e); |
| | | modelOptions.value = []; |
| | | } |
| | | } |
| | | // ç¼è¾æ¨¡å¼ä¸ï¼å
å è½½ææ é项ï¼ç¶åå è½½åæ°å表 |
| | | if (currentProductId.value) { |
| | | // å
å è½½ææ é项 |
| | | let params = { |
| | | productId: currentProductId.value, |
| | | inspectType: 2, |
| | | }; |
| | | qualityInspectDetailByProductId(params).then(res => { |
| | | testStandardOptions.value = res.data || []; |
| | | // ä½¿ç¨ nextTick ç¡®ä¿éé¡¹å·²ç»æ¸²æ |
| | | nextTick(() => { |
| | | // 妿ç¼è¾æ°æ®ä¸æ testStandardIdï¼å设置并å 载对åºçåæ° |
| | | if (savedTestStandardId) { |
| | | // ç¡®ä¿ç±»åå¹é
|
| | | const matchedOption = testStandardOptions.value.find( |
| | | item => |
| | | item.id == savedTestStandardId || |
| | | String(item.id) === String(savedTestStandardId) |
| | | ); |
| | | if (matchedOption) { |
| | | // ç¡®ä¿ä½¿ç¨å¹é
项ç id |
| | | form.value.testStandardId = matchedOption.id; |
| | | testStandardDisplay.value = |
| | | matchedOption.standardName || matchedOption.standardNo; |
| | | // ç¼è¾ä¿ç忣éªå¼ï¼ç´æ¥æåååæ°æ°æ® |
| | | getQualityInspectParamList(row.id); |
| | | } else { |
| | | // 妿æ¾ä¸å°å¹é
项ï¼å°è¯ç´æ¥ä½¿ç¨åå¼ |
| | | console.warn( |
| | | "æªæ¾å°å¹é
çææ é项ï¼testStandardId:", |
| | | savedTestStandardId |
| | | ); |
| | | form.value.testStandardId = savedTestStandardId; |
| | | getQualityInspectParamList(row.id); |
| | | } |
| | | } else { |
| | | // å¦åä½¿ç¨æ§çé»è¾ |
| | | getQualityInspectParamList(row.id); |
| | | } |
| | | }); |
| | | }); |
| | | } |
| | | // å±å¼äº§åæ å°å½åéä¸çèç¹ |
| | | expandProductTree(productOptions.value, row.productId); |
| | | } else { |
| | | // æ°å¢æ¨¡å¼ï¼åå§å表å |
| | | form.value = { |
| | | checkTime: dayjs().format("YYYY-MM-DD"), |
| | | process: "", |
| | | checkName: "", |
| | | productName: "", |
| | | productId: "", |
| | | productModelId: "", |
| | | model: "", |
| | | testStandardId: "", |
| | | unit: "", |
| | | quantity: "", |
| | | checkCompany: "", |
| | | checkResult: "", |
| | | productMainId: null, |
| | | purchaseLedgerId: null, |
| | | }; |
| | | } |
| | | }; |
| | | |
| | | // å±å¼äº§åæ å°æå®èç¹ |
| | | const expandProductTree = (nodes, targetId) => { |
| | | for (let i = 0; i < nodes.length; i++) { |
| | | const node = nodes[i]; |
| | | if (node.value === targetId) { |
| | | return true; // æ¾å°ç®æ èç¹ |
| | | } |
| | | if (node.children && node.children.length > 0) { |
| | | const found = expandProductTree(node.children, targetId); |
| | | if (found) { |
| | | node.expanded = true; // å±å¼ç¶èç¹ |
| | | return true; |
| | | } |
| | | } |
| | | } |
| | | return false; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getprocessList(); |
| | | getProductOptions(); |
| | | getUserList(); |
| | | initForm(); |
| | | }); |
| | | |
| | | onShow(() => { |
| | | initForm(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "@/static/scss/form-common.scss"; |
| | | |
| | | .material-inspection-add { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 100px; |
| | | } |
| | | |
| | | // æ£éªé¡¹ç®å®¹å¨ |
| | | .inspection-items-container { |
| | | padding: 20px; |
| | | background-color: #fff; |
| | | } |
| | | |
| | | .steps-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | padding-bottom: 12px; |
| | | border-bottom: 1px solid #e4e7ed; |
| | | } |
| | | |
| | | .steps-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | } |
| | | |
| | | .steps-count { |
| | | font-size: 14px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .steps-list { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .exec-step-item { |
| | | position: relative; |
| | | display: flex; |
| | | margin-bottom: 16px; |
| | | padding: 16px; |
| | | background-color: #ffffff; |
| | | border: 1px solid #e4e7ed; |
| | | border-radius: 8px; |
| | | transition: all 0.3s ease; |
| | | box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05); |
| | | } |
| | | |
| | | .exec-step-item:hover { |
| | | box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); |
| | | border-color: #409eff; |
| | | transform: translateY(-1px); |
| | | } |
| | | |
| | | .delete-btn { |
| | | position: absolute; |
| | | top: -25rpx; |
| | | right: -25rpx; |
| | | width: 50rpx; |
| | | height: 50rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | text-align: center; |
| | | font-size: 20px; |
| | | border-radius: 50%; |
| | | background-color: red; |
| | | border: none; |
| | | z-index: 10; |
| | | } |
| | | |
| | | .delete-btn:hover { |
| | | transform: scale(1.1); |
| | | box-shadow: 0 3px 6px rgba(245, 108, 108, 0.4); |
| | | } |
| | | |
| | | .step-number { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | width: 32px; |
| | | height: 32px; |
| | | margin-right: 16px; |
| | | background-color: #ecf5ff; |
| | | color: #409eff; |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | border-radius: 50%; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .step-content { |
| | | flex: 1; |
| | | min-width: 0; |
| | | } |
| | | |
| | | .step-row { |
| | | display: flex; |
| | | align-items: flex-start; |
| | | margin-bottom: 12px; |
| | | } |
| | | |
| | | .step-row:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .step-label { |
| | | display: inline-block; |
| | | width: 80px; |
| | | font-size: 14px; |
| | | color: #606266; |
| | | margin-right: 12px; |
| | | flex-shrink: 0; |
| | | line-height: 36px; |
| | | } |
| | | |
| | | .step-input { |
| | | flex: 1; |
| | | min-width: 0; |
| | | } |
| | | |
| | | .step-input input { |
| | | font-size: 14px; |
| | | color: #303133; |
| | | } |
| | | |
| | | .add-step-btn { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | width: 100%; |
| | | height: 44px; |
| | | line-height: 44px; |
| | | font-size: 14px; |
| | | border-radius: 8px; |
| | | transition: all 0.3s ease; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .add-step-btn:hover { |
| | | transform: translateY(-1px); |
| | | box-shadow: 0 2px 8px rgba(64, 158, 255, 0.3); |
| | | } |
| | | |
| | | .add-step-btn text { |
| | | font-size: 14px; |
| | | } |
| | | |
| | | // åºé¨æé® |
| | | .bottom-buttons { |
| | | position: fixed; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | display: flex; |
| | | padding: 16px 20px; |
| | | background: #ffffff; |
| | | border-top: 1px solid #f0f0f0; |
| | | gap: 16px; |
| | | } |
| | | |
| | | .bottom-btn { |
| | | flex: 1; |
| | | } |
| | | |
| | | // æ 形鿩卿 ·å¼ |
| | | .tree-selector { |
| | | width: 100%; |
| | | max-height: 70vh; |
| | | background: #ffffff; |
| | | border-radius: 16px 16px 0 0; |
| | | } |
| | | |
| | | .tree-header { |
| | | padding: 16px 20px; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | text-align: center; |
| | | } |
| | | |
| | | .tree-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | } |
| | | |
| | | .tree-content { |
| | | padding: 10px 0; |
| | | max-height: calc(70vh - 60px); |
| | | overflow-y: auto; |
| | | } |
| | | |
| | | .tree-node { |
| | | padding: 0 20px; |
| | | } |
| | | |
| | | .tree-node-header { |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 12px 0; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .tree-node-icon { |
| | | width: 20px; |
| | | height: 20px; |
| | | margin-right: 8px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .tree-node-icon-placeholder { |
| | | width: 20px; |
| | | height: 20px; |
| | | margin-right: 8px; |
| | | } |
| | | |
| | | .tree-node-label { |
| | | flex: 1; |
| | | font-size: 14px; |
| | | color: #303133; |
| | | } |
| | | |
| | | .tree-node-check { |
| | | width: 20px; |
| | | height: 20px; |
| | | color: #409eff; |
| | | } |
| | | |
| | | .tree-node-children { |
| | | margin-left: 28px; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="material-inspection-detail"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="åºåæ£éªè¯¦æ
" |
| | | @back="goBack" /> |
| | | <!-- 详æ
å
容 --> |
| | | <view class="detail-section" |
| | | v-if="detailData"> |
| | | <view class="detail-card"> |
| | | <view class="card-header"> |
| | | <view class="header-icon"> |
| | | <up-icon name="file-text" |
| | | size="20" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | <text class="header-title">{{ detailData.productName || '-' }}</text> |
| | | <view class="status-tags"> |
| | | <u-tag :type="getTagType(detailData.checkResult)" |
| | | size="small" |
| | | class="status-tag"> |
| | | {{ detailData.checkResult || '-' }} |
| | | </u-tag> |
| | | <u-tag :type="getStateTagType(detailData.inspectState)" |
| | | size="small" |
| | | class="status-tag"> |
| | | {{ detailData.inspectState ? 'å·²æäº¤' : 'æªæäº¤' }} |
| | | </u-tag> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="detail-content"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">æ£æµæ¥æ</text> |
| | | <text class="detail-value">{{ formatDateTime(detailData.checkTime) || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç产工åå·</text> |
| | | <text class="detail-value">{{ detailData.workOrderNo || '-' }}</text> |
| | | </view> |
| | | <!-- <view class="detail-row"> |
| | | <text class="detail-label">å·¥åº</text> |
| | | <text class="detail-value">{{ detailData.process || '-' }}</text> |
| | | </view> --> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">æ£éªå</text> |
| | | <text class="detail-value">{{ detailData.checkName || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">产ååç§°</text> |
| | | <text class="detail-value">{{ detailData.productName || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">è§æ ¼åå·</text> |
| | | <text class="detail-value">{{ detailData.model || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">åä½</text> |
| | | <text class="detail-value">{{ detailData.unit || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">æ°é</text> |
| | | <text class="detail-value">{{ detailData.quantity || 0 }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">æ£æµåä½</text> |
| | | <text class="detail-value">{{ detailData.checkCompany || '-' }}</text> |
| | | </view> |
| | | <!-- <view class="detail-row"> |
| | | <text class="detail-label">æ£éªæ å</text> |
| | | <text class="detail-value">{{ detailData.testStandardName || '-' }}</text> |
| | | </view> --> |
| | | </view> |
| | | </view> |
| | | <!-- æ£éªé¡¹ç® --> |
| | | <view class="detail-card" |
| | | v-if="inspectionItems.length > 0"> |
| | | <view class="card-header"> |
| | | <view class="header-icon secondary"> |
| | | <up-icon name="list" |
| | | size="20" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | <text class="header-title">æ£éªé¡¹ç®</text> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="inspection-items"> |
| | | <view v-for="(item, index) in inspectionItems" |
| | | :key="index" |
| | | class="inspection-item"> |
| | | <text class="item-name">{{ item.parameterItem || 'æ£éªé¡¹ç®' }}</text> |
| | | <view class="item-details"> |
| | | <view class="item-detail-row"> |
| | | <text class="item-detail-label">åä½:</text> |
| | | <text class="item-detail-value">{{ item.unit || '-' }}</text> |
| | | </view> |
| | | <view class="item-detail-row"> |
| | | <text class="item-detail-label">æ åå¼:</text> |
| | | <text class="item-detail-value">{{ item.standardValue || '-' }}</text> |
| | | </view> |
| | | <view class="item-detail-row"> |
| | | <text class="item-detail-label">å
æ§å¼:</text> |
| | | <text class="item-detail-value">{{ item.controlValue || '-' }}</text> |
| | | </view> |
| | | <view class="item-detail-row"> |
| | | <text class="item-detail-label">æ£éªå¼:</text> |
| | | <text class="item-detail-value result" |
| | | :class="getResultClass(item.testValue, item.standardValue)"> |
| | | {{ item.testValue || '-' }} |
| | | </text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- æä½æé® --> |
| | | <!-- <view class="action-buttons"> |
| | | <u-button type="primary" |
| | | class="action-btn" |
| | | @click="downloadReport"> |
| | | ä¸è½½æ¥å |
| | | </u-button> |
| | | </view> --> |
| | | </view> |
| | | <view v-else |
| | | class="no-data"> |
| | | <up-empty mode="data" |
| | | text="ææ æ£éªè¯¦æ
"></up-empty> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import dayjs from "dayjs"; |
| | | import { qualityInspectParamInfo } from "@/api/qualityManagement/materialInspection.js"; |
| | | |
| | | // æ¾ç¤ºæç¤ºä¿¡æ¯ |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | // 详æ
æ°æ® |
| | | const detailData = ref(null); |
| | | // æ£éªé¡¹ç® |
| | | const inspectionItems = ref([]); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // æ ¼å¼åæ¥ææ¶é´ |
| | | const formatDateTime = date => { |
| | | if (!date) return ""; |
| | | return dayjs(date).format("YYYY-MM-DD"); |
| | | }; |
| | | |
| | | // è·åæ ç¾ç±»å |
| | | const getTagType = result => { |
| | | switch (result) { |
| | | case "åæ ¼": |
| | | return "success"; |
| | | case "ä¸åæ ¼": |
| | | return "error"; |
| | | default: |
| | | return "info"; |
| | | } |
| | | }; |
| | | |
| | | // è·åç¶ææ ç¾ç±»å |
| | | const getStateTagType = state => { |
| | | return state ? "success" : "warning"; |
| | | }; |
| | | |
| | | // è·åç»ææ ·å¼ |
| | | const getResultClass = (testValue, standardValue) => { |
| | | // ç®åçç»æå¤æé»è¾ï¼å®é
项ç®ä¸å¯è½éè¦æ´å¤æç夿 |
| | | if (testValue === "åæ ¼") { |
| | | return "result-passed"; |
| | | } else if (testValue === "ä¸åæ ¼") { |
| | | return "result-rejected"; |
| | | } |
| | | return ""; |
| | | }; |
| | | |
| | | // ä¸è½½æ¥å |
| | | const downloadReport = () => { |
| | | uni.showToast({ |
| | | title: "æ¥åä¸è½½ä¸...", |
| | | icon: "loading", |
| | | }); |
| | | |
| | | // 模æä¸è½½ |
| | | setTimeout(() => { |
| | | uni.showToast({ |
| | | title: "æ¥åä¸è½½æå", |
| | | icon: "success", |
| | | }); |
| | | }, 1500); |
| | | }; |
| | | |
| | | // è·å页é¢ID |
| | | const getPageId = () => { |
| | | const pages = getCurrentPages(); |
| | | const currentPage = pages[pages.length - 1]; |
| | | return currentPage.options.id; |
| | | }; |
| | | |
| | | // è·å详æ
æ°æ® |
| | | const getDetail = () => { |
| | | const id = getPageId(); |
| | | if (!id) { |
| | | showToast("åæ°é误"); |
| | | return; |
| | | } |
| | | |
| | | // 仿¬å°åå¨è·å详æ
æ°æ® |
| | | try { |
| | | const detailDataFromStorage = uni.getStorageSync("finalInspectionEditData"); |
| | | if (detailDataFromStorage) { |
| | | detailData.value = detailDataFromStorage; |
| | | console.log(detailData.value, "detailData.value"); |
| | | // 使ç¨qualityInspectParamInfoè·åæ£éªé¡¹ç® |
| | | qualityInspectParamInfo(id) |
| | | .then(res => { |
| | | if (res.data && res.data.length > 0) { |
| | | inspectionItems.value = res.data; |
| | | } else if ( |
| | | detailDataFromStorage.qualityInspectParams && |
| | | detailDataFromStorage.qualityInspectParams.length > 0 |
| | | ) { |
| | | // 妿æ¥å£æ²¡æè¿åæ°æ®ï¼ä½¿ç¨æ¬å°åå¨ä¸çæ°æ® |
| | | inspectionItems.value = detailDataFromStorage.qualityInspectParams; |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error("è·åæ£éªé¡¹ç®å¤±è´¥:", error); |
| | | // æ¥å£è°ç¨å¤±è´¥æ¶ï¼ä½¿ç¨æ¬å°åå¨ä¸çæ°æ®ææ¨¡ææ°æ® |
| | | if ( |
| | | detailDataFromStorage.qualityInspectParams && |
| | | detailDataFromStorage.qualityInspectParams.length > 0 |
| | | ) { |
| | | inspectionItems.value = detailDataFromStorage.qualityInspectParams; |
| | | } |
| | | }); |
| | | } |
| | | } catch (error) { |
| | | console.error("å 载详æ
æ°æ®å¤±è´¥:", error); |
| | | showToast("å 载详æ
æ°æ®å¤±è´¥ï¼è¯·éè¯"); |
| | | } |
| | | }; |
| | | |
| | | onShow(() => { |
| | | getDetail(); |
| | | }); |
| | | |
| | | onMounted(() => { |
| | | getDetail(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .material-inspection-detail { |
| | | min-height: 100vh; |
| | | background: #f5f5f5; |
| | | padding-bottom: 20px; |
| | | } |
| | | |
| | | .detail-section { |
| | | padding: 15px; |
| | | } |
| | | |
| | | .detail-card { |
| | | background: #fff; |
| | | border-radius: 12px; |
| | | padding: 16px; |
| | | margin-bottom: 12px; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); |
| | | } |
| | | |
| | | .card-header { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-bottom: 12px; |
| | | } |
| | | |
| | | .header-icon { |
| | | width: 40px; |
| | | height: 40px; |
| | | background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| | | border-radius: 8px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | margin-right: 12px; |
| | | } |
| | | |
| | | .header-icon.secondary { |
| | | background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); |
| | | } |
| | | |
| | | .header-icon.tertiary { |
| | | background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); |
| | | } |
| | | |
| | | .header-title { |
| | | flex: 1; |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | |
| | | .status-tag { |
| | | margin-left: 20rpx; |
| | | } |
| | | |
| | | .detail-content { |
| | | padding-top: 8px; |
| | | } |
| | | |
| | | .detail-row { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 10px 0; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | } |
| | | |
| | | .detail-row:last-child { |
| | | border-bottom: none; |
| | | } |
| | | |
| | | .detail-label { |
| | | font-size: 14px; |
| | | color: #666; |
| | | min-width: 100px; |
| | | } |
| | | |
| | | .detail-value { |
| | | font-size: 14px; |
| | | color: #333; |
| | | text-align: right; |
| | | flex: 1; |
| | | } |
| | | |
| | | // æ£éªé¡¹ç® |
| | | .inspection-items { |
| | | padding-top: 8px; |
| | | } |
| | | |
| | | .inspection-item { |
| | | padding: 12px; |
| | | background: #f8f9fa; |
| | | border-radius: 8px; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .inspection-item:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .item-name { |
| | | display: block; |
| | | font-size: 14px; |
| | | font-weight: 500; |
| | | color: #333; |
| | | margin-bottom: 8px; |
| | | padding-bottom: 8px; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | } |
| | | |
| | | .item-details { |
| | | padding-top: 8px; |
| | | } |
| | | |
| | | .item-detail-row { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 6px; |
| | | } |
| | | |
| | | .item-detail-row:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .item-detail-label { |
| | | font-size: 12px; |
| | | color: #666; |
| | | min-width: 60px; |
| | | } |
| | | |
| | | .item-detail-value { |
| | | font-size: 12px; |
| | | color: #333; |
| | | text-align: right; |
| | | flex: 1; |
| | | } |
| | | |
| | | .item-detail-value.result { |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .result-passed { |
| | | color: #67c23a; |
| | | } |
| | | |
| | | .result-rejected { |
| | | color: #f56c6c; |
| | | } |
| | | |
| | | // ç©ºç¶æ |
| | | .no-data { |
| | | padding: 60px 20px; |
| | | text-align: center; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="file-list-page"> |
| | | <!-- 页é¢å¤´é¨ --> |
| | | <PageHeader title="é件管ç" |
| | | @back="goBack" /> |
| | | <!-- éä»¶å表 --> |
| | | <view class="file-list-container"> |
| | | <view v-if="fileList.length > 0" |
| | | class="file-list"> |
| | | <view v-for="(file, index) in fileList" |
| | | :key="file.id || index" |
| | | class="file-item"> |
| | | <!-- æä»¶å¾æ --> |
| | | <!-- <view class="file-icon" |
| | | :class="getFileIconClass(file.fileType)"> |
| | | <up-icon :name="getFileIcon(file.fileType)" |
| | | size="24" |
| | | color="#ffffff" /> |
| | | </view> --> |
| | | <!-- æä»¶ä¿¡æ¯ --> |
| | | <view class="file-info"> |
| | | <text class="file-name">{{ file.name }}</text> |
| | | <!-- <text class="file-meta">{{ formatFileSize(file.fileSize) }} · {{ file.uploadTime || file.createTime }}</text> --> |
| | | </view> |
| | | <!-- æä½æé® --> |
| | | <view class="file-actions"> |
| | | <!-- <u-button size="small" |
| | | type="primary" |
| | | plain |
| | | @click="previewFile(file)">é¢è§</u-button> --> |
| | | <u-button size="small" |
| | | type="info" |
| | | plain |
| | | @click="downloadFile(file)">ä¸è½½å¹¶é¢è§</u-button> |
| | | <u-button size="small" |
| | | type="error" |
| | | plain |
| | | @click="confirmDelete(file, index)">å é¤</u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- ç©ºç¶æ --> |
| | | <view v-else |
| | | class="empty-state"> |
| | | <up-icon name="document" |
| | | size="64" |
| | | color="#c0c4cc" /> |
| | | <text class="empty-text">ææ éä»¶</text> |
| | | </view> |
| | | </view> |
| | | <!-- <a rel="nofollow" |
| | | id="downloadLink" |
| | | href="#" |
| | | style="display:none;">ä¸è½½ææ¬æä»¶</a> --> |
| | | <!-- ä¸ä¼ æé® --> |
| | | <view class="upload-button" |
| | | @click="chooseFile"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff" /> |
| | | <text class="upload-text">ä¸ä¼ éä»¶</text> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import config from "@/config"; |
| | | import { getToken } from "@/utils/auth"; |
| | | // import { saveAs } from "file-saver"; |
| | | import { |
| | | listRuleFiles, |
| | | delRuleFile, |
| | | } from "@/api/managementMeetings/rulesRegulationsManagement"; |
| | | import { |
| | | qualityInspectFileAdd, |
| | | qualityInspectFileListPage, |
| | | qualityInspectFileDel, |
| | | } from "@/api/qualityManagement/materialInspection"; |
| | | import { blobValidate } from "@/utils/ruoyi"; |
| | | |
| | | // éä»¶å表 |
| | | const fileList = ref([]); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | // const request = axios.create({ |
| | | // baseURL: "URL.com", |
| | | // adapter: axiosAdapterUniapp, |
| | | // }); |
| | | // è·åæä»¶å¾æ |
| | | const getFileIcon = fileType => { |
| | | const iconMap = { |
| | | doc: "document", |
| | | docx: "document", |
| | | xls: "grid", |
| | | xlsx: "grid", |
| | | pdf: "document", |
| | | ppt: "copy", |
| | | pptx: "copy", |
| | | txt: "document", |
| | | jpg: "image", |
| | | jpeg: "image", |
| | | png: "image", |
| | | gif: "image", |
| | | zip: "folder", |
| | | rar: "folder", |
| | | }; |
| | | return iconMap[fileType.toLowerCase()] || "document"; |
| | | }; |
| | | |
| | | // è·åæä»¶å¾æ æ ·å¼ç±» |
| | | const getFileIconClass = fileType => { |
| | | const colorMap = { |
| | | doc: "blue", |
| | | docx: "blue", |
| | | xls: "green", |
| | | xlsx: "green", |
| | | pdf: "red", |
| | | ppt: "orange", |
| | | pptx: "orange", |
| | | txt: "gray", |
| | | jpg: "purple", |
| | | jpeg: "purple", |
| | | png: "purple", |
| | | gif: "purple", |
| | | zip: "yellow", |
| | | rar: "yellow", |
| | | }; |
| | | return colorMap[fileType.toLowerCase()] || "gray"; |
| | | }; |
| | | |
| | | // æ ¼å¼åæä»¶å¤§å° |
| | | const formatFileSize = bytes => { |
| | | if (bytes === 0) return "0 B"; |
| | | const k = 1024; |
| | | const sizes = ["B", "KB", "MB", "GB"]; |
| | | const i = Math.floor(Math.log(bytes) / Math.log(k)); |
| | | return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i]; |
| | | }; |
| | | |
| | | // éæ©æä»¶ |
| | | const chooseFile = () => { |
| | | uni.chooseImage({ |
| | | count: 9, |
| | | sizeType: ["original", "compressed"], |
| | | sourceType: ["album", "camera"], |
| | | success: res => { |
| | | console.log(res, "éæ©å¾çæå"); |
| | | uploadFiles(res.tempFiles); |
| | | }, |
| | | fail: err => { |
| | | console.error("éæ©å¾ç失败:", err); |
| | | showToast("éæ©æä»¶å¤±è´¥"); |
| | | }, |
| | | }); |
| | | // uni.chooseFile({ |
| | | // count: 9, |
| | | // extension: [ |
| | | // ".doc", |
| | | // ".docx", |
| | | // ".xls", |
| | | // ".xlsx", |
| | | // ".pdf", |
| | | // ".ppt", |
| | | // ".pptx", |
| | | // ".txt", |
| | | // ".jpg", |
| | | // ".jpeg", |
| | | // ".png", |
| | | // ".gif", |
| | | // ".zip", |
| | | // ".rar", |
| | | // ], |
| | | // success: res => { |
| | | // console.log(res, "éæ©æä»¶æå"); |
| | | // uploadFiles(res.tempFiles); |
| | | // }, |
| | | // fail: err => { |
| | | // showToast("éæ©æä»¶å¤±è´¥"); |
| | | // }, |
| | | // }); |
| | | }; |
| | | |
| | | // ä¸ä¼ æä»¶ |
| | | const uploadFiles = tempFiles => { |
| | | console.log(tempFiles, "ä¸ä¼ æä»¶1"); |
| | | tempFiles.forEach((tempFile, index) => { |
| | | // æ¾ç¤ºä¸ä¼ ä¸æç¤º |
| | | uni.showLoading({ |
| | | title: "ä¸ä¼ ä¸...", |
| | | mask: true, |
| | | }); |
| | | console.log(tempFile, "ä¸ä¼ æä»¶2"); |
| | | // 1. ç´æ¥ä½¿ç¨ uni.uploadFile ä¸ä¼ æä»¶ |
| | | uni.uploadFile({ |
| | | url: config.baseUrl + "/file/upload", |
| | | filePath: tempFile.path, |
| | | name: "file", |
| | | header: { |
| | | Authorization: "Bearer " + getToken(), |
| | | }, |
| | | success: uploadRes => { |
| | | uni.hideLoading(); |
| | | console.log(uploadRes, "ä¸ä¼ æä»¶3"); |
| | | |
| | | try { |
| | | const res = JSON.parse(uploadRes.data); |
| | | console.log(res, "ä¸ä¼ æä»¶4"); |
| | | if (res.code === 200) { |
| | | // 2. æåæä»¶ä¿¡æ¯ |
| | | const fileName = tempFile.name |
| | | ? tempFile.name |
| | | : tempFile.path.split("/").pop(); |
| | | // const fileType = fileName.split(".").pop(); |
| | | // 3. æé ä¿åæä»¶ä¿¡æ¯çåæ° |
| | | const saveData = { |
| | | name: fileName, |
| | | inspectId: rulesRegulationsManagementId.value, |
| | | url: res.data.tempPath || "", |
| | | }; |
| | | console.log(saveData, "ä¿åæä»¶ä¿¡æ¯åæ°"); |
| | | // 4. è°ç¨ addRuleFile æ¥å£ä¿åæä»¶ä¿¡æ¯ |
| | | qualityInspectFileAdd(saveData) |
| | | .then(addRes => { |
| | | if (addRes.code === 200) { |
| | | // 5. æ·»å å°æä»¶å表 |
| | | const newFile = { |
| | | ...addRes.data, |
| | | uploadTime: new Date().toLocaleString(), |
| | | }; |
| | | // fileList.value.push(newFile); |
| | | getFileList(); |
| | | showToast("ä¸ä¼ æå"); |
| | | } else { |
| | | showToast("ä¿åæä»¶ä¿¡æ¯å¤±è´¥"); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | console.error("ä¿åæä»¶ä¿¡æ¯å¤±è´¥:", err); |
| | | showToast("ä¿åæä»¶ä¿¡æ¯å¤±è´¥"); |
| | | }); |
| | | } else { |
| | | showToast("æä»¶ä¸ä¼ 失败"); |
| | | } |
| | | } catch (e) { |
| | | console.error("è§£æä¸ä¼ ç»æå¤±è´¥:", e); |
| | | showToast("ä¸ä¼ 失败"); |
| | | } |
| | | }, |
| | | fail: err => { |
| | | uni.hideLoading(); |
| | | console.error("ä¸ä¼ 失败:", err); |
| | | showToast("ä¸ä¼ 失败"); |
| | | }, |
| | | }); |
| | | }); |
| | | }; |
| | | // ä¸è½½æä»¶ |
| | | const downloadFile = file => { |
| | | var url = |
| | | config.baseUrl + |
| | | "/common/download?fileName=" + |
| | | encodeURIComponent(file.url) + |
| | | "&delete=true"; |
| | | console.log(url, "url"); |
| | | |
| | | uni |
| | | .downloadFile({ |
| | | url: url, |
| | | responseType: "blob", |
| | | header: { Authorization: "Bearer " + getToken() }, |
| | | }) |
| | | .then(res => { |
| | | let osType = uni.getStorageSync("deviceInfo").osName; |
| | | let filePath = res.tempFilePath; |
| | | if (osType === "ios") { |
| | | uni.openDocument({ |
| | | filePath: filePath, |
| | | showMenu: true, |
| | | success: res => { |
| | | resolve(res); |
| | | }, |
| | | fail: err => { |
| | | console.log("uni.openDocument--fail"); |
| | | reject(err); |
| | | }, |
| | | }); |
| | | } else { |
| | | uni.saveFile({ |
| | | tempFilePath: filePath, |
| | | success: fileRes => { |
| | | uni.showToast({ |
| | | icon: "none", |
| | | mask: true, |
| | | title: |
| | | "æä»¶å·²ä¿åï¼Android/data/uni.UNI720216F/apps/__UNI__720216F/" + |
| | | fileRes.savedFilePath, //ä¿åè·¯å¾ |
| | | duration: 3000, |
| | | }); |
| | | setTimeout(() => { |
| | | //æå¼ææ¡£æ¥ç |
| | | uni.openDocument({ |
| | | filePath: fileRes.savedFilePath, |
| | | success: function (res) { |
| | | resolve(fileRes); |
| | | }, |
| | | }); |
| | | }, 3000); |
| | | }, |
| | | fail: err => { |
| | | console.log("uni.save--fail"); |
| | | reject(err); |
| | | }, |
| | | }); |
| | | } |
| | | // const isBlob = blobValidate(res.data); |
| | | // if (isBlob) { |
| | | // const blob = new Blob([res.data], { type: "text/plain" }); |
| | | // const url = URL.createObjectURL(blob); |
| | | // const downloadLink = document.getElementById("downloadLink"); |
| | | // downloadLink.href = url; |
| | | // downloadLink.download = file.name; |
| | | // downloadLink.click(); |
| | | // showToast("ä¸è½½æå"); |
| | | // } else { |
| | | // showToast("ä¸è½½å¤±è´¥"); |
| | | // } |
| | | }) |
| | | .catch(err => { |
| | | console.error("ä¸è½½å¤±è´¥:", err); |
| | | showToast("ä¸è½½å¤±è´¥"); |
| | | }); |
| | | }; |
| | | |
| | | // 确认å é¤ |
| | | const confirmDelete = (file, index) => { |
| | | uni.showModal({ |
| | | title: "å é¤ç¡®è®¤", |
| | | content: `ç¡®å®è¦å é¤éä»¶ "${file.name}" åï¼`, |
| | | success: res => { |
| | | if (res.confirm) { |
| | | deleteFile(file.id, index); |
| | | } |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // å 餿件 |
| | | const deleteFile = (fileId, index) => { |
| | | uni.showLoading({ |
| | | title: "å é¤ä¸...", |
| | | mask: true, |
| | | }); |
| | | |
| | | qualityInspectFileDel([fileId]) |
| | | .then(res => { |
| | | uni.hideLoading(); |
| | | if (res.code === 200) { |
| | | // fileList.value.splice(index, 1); |
| | | getFileList(); |
| | | showToast("å 餿å"); |
| | | } else { |
| | | showToast("å é¤å¤±è´¥"); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | uni.hideLoading(); |
| | | showToast("å é¤å¤±è´¥"); |
| | | }); |
| | | }; |
| | | |
| | | // æ¾ç¤ºæç¤º |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | const rulesRegulationsManagementId = ref(""); |
| | | // 页é¢å è½½æ¶ |
| | | onMounted(() => { |
| | | rulesRegulationsManagementId.value = uni.getStorageSync( |
| | | "qualityInspectFileId" |
| | | ); |
| | | // ä» API è·åéä»¶å表 |
| | | getFileList(); |
| | | // 仿¬å°åå¨è·å rulesRegulationsManagementId |
| | | }); |
| | | |
| | | // è·åéä»¶å表 |
| | | const getFileList = () => { |
| | | uni.showLoading({ |
| | | title: "å è½½ä¸...", |
| | | mask: true, |
| | | }); |
| | | |
| | | qualityInspectFileListPage({ |
| | | inspectId: rulesRegulationsManagementId.value, |
| | | current: -1, |
| | | size: -1, |
| | | }) |
| | | .then(res => { |
| | | uni.hideLoading(); |
| | | if (res.code === 200) { |
| | | fileList.value = res.data.records || []; |
| | | } else { |
| | | showToast("è·åéä»¶å表失败"); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | uni.hideLoading(); |
| | | showToast("è·åéä»¶å表失败"); |
| | | }); |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "../../../styles/sales-common.scss"; |
| | | |
| | | .file-list-page { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 100rpx; |
| | | } |
| | | |
| | | .file-list-container { |
| | | padding: 20rpx; |
| | | } |
| | | |
| | | .file-list { |
| | | background: #ffffff; |
| | | border-radius: 8rpx; |
| | | overflow: hidden; |
| | | box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05); |
| | | } |
| | | |
| | | .file-item { |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 20rpx; |
| | | border-bottom: 1rpx solid #f0f0f0; |
| | | |
| | | &:last-child { |
| | | border-bottom: none; |
| | | } |
| | | } |
| | | |
| | | .file-icon { |
| | | width: 56rpx; |
| | | height: 56rpx; |
| | | border-radius: 8rpx; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | margin-right: 20rpx; |
| | | |
| | | &.blue { |
| | | background: #409eff; |
| | | } |
| | | |
| | | &.green { |
| | | background: #67c23a; |
| | | } |
| | | |
| | | &.red { |
| | | background: #f56c6c; |
| | | } |
| | | |
| | | &.orange { |
| | | background: #e6a23c; |
| | | } |
| | | |
| | | &.gray { |
| | | background: #909399; |
| | | } |
| | | |
| | | &.purple { |
| | | background: #909399; |
| | | } |
| | | |
| | | &.yellow { |
| | | background: #e6a23c; |
| | | } |
| | | } |
| | | |
| | | .file-info { |
| | | flex: 1; |
| | | min-width: 0; |
| | | } |
| | | |
| | | .file-name { |
| | | display: block; |
| | | font-size: 16px; |
| | | color: #303133; |
| | | margin-bottom: 8rpx; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | .file-meta { |
| | | display: block; |
| | | font-size: 12px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .file-actions { |
| | | display: flex; |
| | | gap: 12rpx; |
| | | } |
| | | |
| | | .empty-state { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | padding: 100rpx 0; |
| | | background: #ffffff; |
| | | border-radius: 8rpx; |
| | | box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05); |
| | | } |
| | | |
| | | .empty-text { |
| | | font-size: 14px; |
| | | color: #909399; |
| | | margin-top: 20rpx; |
| | | } |
| | | |
| | | .upload-button { |
| | | position: fixed; |
| | | bottom: 40rpx; |
| | | right: 40rpx; |
| | | width: 130rpx; |
| | | height: 130rpx; |
| | | border-radius: 50%; |
| | | background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | align-items: center; |
| | | box-shadow: 0 4rpx 16rpx rgba(102, 126, 234, 0.4); |
| | | z-index: 1000; |
| | | } |
| | | |
| | | .upload-text { |
| | | font-size: 10px; |
| | | color: #ffffff; |
| | | margin-top: 4rpx; |
| | | } |
| | | |
| | | .upload-progress { |
| | | padding: 40rpx 0; |
| | | } |
| | | |
| | | .upload-progress-text { |
| | | display: block; |
| | | text-align: center; |
| | | margin-top: 20rpx; |
| | | font-size: 14px; |
| | | color: #606266; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="material-inspection-page"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="åºåæ£éª" |
| | | @back="goBack" /> |
| | | <!-- æç´¢åºå --> |
| | | <view class="search-section"> |
| | | <view class="search-bar"> |
| | | <view class="search-input"> |
| | | <up-input class="search-text" |
| | | placeholder="请è¾å
¥äº§ååç§°æç´¢" |
| | | v-model="searchForm.productName" |
| | | @change="getList" |
| | | clearable /> |
| | | </view> |
| | | <!-- <view class="filter-button" |
| | | @click="showDatePicker"> |
| | | <up-icon name="calendar" |
| | | size="24" |
| | | color="#999"></up-icon> |
| | | </view> --> |
| | | <view class="filter-button" |
| | | @click="getList"> |
| | | <up-icon name="search" |
| | | size="24" |
| | | color="#999"></up-icon> |
| | | </view> |
| | | </view> |
| | | <!-- æ¥æéæ© --> |
| | | <!-- <view class="date-range" |
| | | v-if="searchForm.entryDate"> |
| | | <text class="date-text">{{ searchForm.entryDate[0] }} è³ {{ searchForm.entryDate[1] }}</text> |
| | | <up-icon name="close" |
| | | size="16" |
| | | color="#999" |
| | | @click="clearDateRange"></up-icon> |
| | | </view> --> |
| | | </view> |
| | | <!-- ç»è®¡ä¿¡æ¯å¡ç --> |
| | | <!-- <view class="stats-cards"> |
| | | <view class="stat-card"> |
| | | <text class="stat-number">{{ totalCount }}</text> |
| | | <text class="stat-label">æ»æ£éª</text> |
| | | </view> |
| | | <view class="stat-card"> |
| | | <text class="stat-number">{{ submittedCount }}</text> |
| | | <text class="stat-label">å·²æäº¤</text> |
| | | </view> |
| | | <view class="stat-card"> |
| | | <text class="stat-number">{{ pendingCount }}</text> |
| | | <text class="stat-label">å¾
æäº¤</text> |
| | | </view> |
| | | <view class="stat-card"> |
| | | <text class="stat-number">{{ qualifiedCount }}</text> |
| | | <text class="stat-label">å·²åæ ¼</text> |
| | | </view> |
| | | </view> --> |
| | | <!-- æ£éªå表 --> |
| | | <view class="inspection-list" |
| | | v-if="inspectionList.length > 0"> |
| | | <view v-for="(item, index) in inspectionList" |
| | | :key="index"> |
| | | <view class="inspection-item" |
| | | @click="viewDetail(item)"> |
| | | <view class="item-header"> |
| | | <view class="item-left"> |
| | | <!-- <view class="material-icon" |
| | | :class="getStateClass(item.inspectState)"> |
| | | <up-icon :name="getStateIcon(item.inspectState)" |
| | | size="16" |
| | | color="#ffffff"></up-icon> |
| | | </view> --> |
| | | <view class="material-info"> |
| | | <text class="material-name">{{ item.productName }}</text> |
| | | <text class="material-code">{{ item.model }}</text> |
| | | </view> |
| | | </view> |
| | | <view class="status-tags"> |
| | | <u-tag :type="getTagType(item.checkResult)" |
| | | size="mini" |
| | | class="status-tag"> |
| | | {{ item.checkResult }} |
| | | </u-tag> |
| | | <u-tag :type="getStateTagType(item.inspectState)" |
| | | size="mini" |
| | | class="status-tag"> |
| | | {{ item.inspectState ? 'å·²æäº¤' : 'æªæäº¤' }} |
| | | </u-tag> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="item-details"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">æ£æµæ¥æ</text> |
| | | <text class="detail-value">{{ formatDateTime(item.checkTime) || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç产工åå·</text> |
| | | <text class="detail-value">{{ item.workOrderNo || '-' }}</text> |
| | | </view> |
| | | <!-- <view class="detail-row"> |
| | | <text class="detail-label">å·¥åº</text> |
| | | <text class="detail-value">{{ item.process || '-' }}</text> |
| | | </view> --> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">æ£éªå</text> |
| | | <text class="detail-value">{{ item.checkName || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">æ°é</text> |
| | | <text class="detail-value">{{ item.quantity || 0 }} {{ item.unit || '' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">æ£æµåä½</text> |
| | | <text class="detail-value">{{ item.checkCompany || '-' }}</text> |
| | | </view> |
| | | </view> |
| | | <!-- æä½æé® --> |
| | | <view class="action-buttons"> |
| | | <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.inspectState" |
| | | @click.stop="startInspection(item)"> |
| | | ç¼è¾ |
| | | </u-button> |
| | | <u-button type="info" |
| | | size="small" |
| | | class="action-btn" |
| | | @click.stop="viewDetail(item)"> |
| | | 详æ
|
| | | </u-button> |
| | | <u-button type="success" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.inspectState" |
| | | @click.stop="submitInspection(item)"> |
| | | æäº¤ |
| | | </u-button> |
| | | </view> |
| | | <view class="action-buttons"> |
| | | <u-button type="info" |
| | | size="small" |
| | | class="action-btn" |
| | | @click.stop="viewFileList(item)"> |
| | | éä»¶ |
| | | </u-button> |
| | | <u-button type="warning" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.inspectState || item.checkName !== ''" |
| | | @click.stop="assignInspector(item)"> |
| | | åé
æ£éªå |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else |
| | | class="no-data"> |
| | | <up-empty mode="data" |
| | | text="ææ æ£éªä»»å¡"></up-empty> |
| | | </view> |
| | | <!-- å页ç»ä»¶ --> |
| | | <!-- æµ®å¨æ°å¢æé® --> |
| | | <view class="fab-button" |
| | | @click="addInspection"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <up-popup v-model:show="showDate" |
| | | mode="date" |
| | | :start-year="2020" |
| | | :end-year="2030" |
| | | :range="true" |
| | | @confirm="confirmDate" /> |
| | | <!-- åé
æ£éªåå¼¹çª --> |
| | | <up-popup v-model:show="showAssignDialog" |
| | | mode="center" |
| | | round |
| | | style="width: 80%"> |
| | | <view class="assign-dialog"> |
| | | <view class="dialog-header"> |
| | | <text class="dialog-title">åé
æ£éªå</text> |
| | | <up-icon name="close" |
| | | size="20" |
| | | color="#999" |
| | | @click="showAssignDialog = false"></up-icon> |
| | | </view> |
| | | <view class="dialog-content"> |
| | | <up-form-item label="æ£éªå" |
| | | prop="checkName" |
| | | :label-width="60" |
| | | required> |
| | | <up-input v-model="assignForm.checkName" |
| | | placeholder="è¯·éæ©æ£éªå" |
| | | readonly /> |
| | | <template #right> |
| | | <up-icon @click="showInspectorSheet = true" |
| | | name="arrow-right" /> |
| | | </template> |
| | | </up-form-item> |
| | | </view> |
| | | <view class="dialog-footer"> |
| | | <u-button type="default" |
| | | class="footer-btn" |
| | | @click="showAssignDialog = false"> |
| | | åæ¶ |
| | | </u-button> |
| | | <u-button type="primary" |
| | | class="footer-btn" |
| | | @click="submitAssign"> |
| | | ç¡®å® |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </up-popup> |
| | | <!-- æ£éªåéæ© --> |
| | | <up-action-sheet :show="showInspectorSheet" |
| | | :actions="userSheetOptions" |
| | | @select="selectInspector" |
| | | title="éæ©æ£éªå" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, computed, onMounted } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import dayjs from "dayjs"; |
| | | import { |
| | | submitQualityInspect, |
| | | qualityInspectUpdate, |
| | | qualityInspectListPage, |
| | | } from "@/api/qualityManagement/materialInspection.js"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | |
| | | // æ¾ç¤ºæç¤ºä¿¡æ¯ |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | // æç´¢è¡¨å |
| | | const searchForm = ref({ |
| | | productName: "", |
| | | entryDate: undefined, |
| | | entryDateStart: undefined, |
| | | entryDateEnd: undefined, |
| | | }); |
| | | |
| | | // æ¥æéæ©å¨ |
| | | const showDate = ref(false); |
| | | |
| | | // åé
æ£éªåå¼¹çª |
| | | const showAssignDialog = ref(false); |
| | | const showInspectorSheet = ref(false); |
| | | const assignForm = ref({ |
| | | checkName: "", |
| | | }); |
| | | const currentAssignRow = ref(null); |
| | | |
| | | // æ£éªåè¡¨æ°æ® |
| | | const inspectionList = ref([]); |
| | | |
| | | // åé¡µæ°æ® |
| | | const page = ref({ |
| | | current: -1, |
| | | size: -1, |
| | | total: 0, |
| | | }); |
| | | |
| | | // å è½½ç¶æ |
| | | const tableLoading = ref(false); |
| | | |
| | | // ç»è®¡æ°æ® |
| | | const totalCount = ref(0); |
| | | const submittedCount = ref(0); |
| | | const pendingCount = ref(0); |
| | | const qualifiedCount = ref(0); |
| | | |
| | | // æ£éªåå表 |
| | | const userList = ref([]); |
| | | |
| | | // ActionSheeté项 |
| | | const userSheetOptions = computed(() => { |
| | | return userList.value.map(item => ({ |
| | | name: item.nickName, |
| | | value: item.nickName, |
| | | })); |
| | | }); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // æ ¼å¼åæ¥ææ¶é´ |
| | | const formatDateTime = dateStr => { |
| | | if (!dateStr) return ""; |
| | | return dayjs(dateStr).format("YYYY-MM-DD"); |
| | | }; |
| | | |
| | | // è·åç¶ææ ·å¼ |
| | | const getStateClass = inspectState => { |
| | | return inspectState ? "state-submitted" : "state-pending"; |
| | | }; |
| | | |
| | | // è·åç¶æå¾æ |
| | | const getStateIcon = inspectState => { |
| | | return inspectState ? "checkmark-circle" : "time"; |
| | | }; |
| | | |
| | | // è·åæ ç¾ç±»å |
| | | const getTagType = checkResult => { |
| | | if (checkResult === "åæ ¼") return "success"; |
| | | if (checkResult === "ä¸åæ ¼") return "error"; |
| | | return "default"; |
| | | }; |
| | | |
| | | // è·åç¶ææ ç¾ç±»å |
| | | const getStateTagType = inspectState => { |
| | | return inspectState ? "success" : "warning"; |
| | | }; |
| | | |
| | | // æ¾ç¤ºæ¥æéæ©å¨ |
| | | const showDatePicker = () => { |
| | | showDate.value = true; |
| | | }; |
| | | |
| | | // ç¡®è®¤æ¥æéæ© |
| | | const confirmDate = e => { |
| | | searchForm.value.entryDate = e.value; |
| | | searchForm.value.entryDateStart = dayjs(e.value[0]).format("YYYY-MM-DD"); |
| | | searchForm.value.entryDateEnd = dayjs(e.value[1]).format("YYYY-MM-DD"); |
| | | getList(); |
| | | }; |
| | | const viewFileList = item => { |
| | | uni.setStorageSync("qualityInspectFileId", item.id); |
| | | uni.navigateTo({ |
| | | url: "/pages/qualityManagement/finalInspection/fileList", |
| | | }); |
| | | }; |
| | | |
| | | // æ¸
餿¥æèå´ |
| | | const clearDateRange = () => { |
| | | searchForm.value.entryDate = undefined; |
| | | searchForm.value.entryDateStart = undefined; |
| | | searchForm.value.entryDateEnd = undefined; |
| | | getList(); |
| | | }; |
| | | |
| | | // è·åç¨æ·å表 |
| | | const getUserList = async () => { |
| | | try { |
| | | const userRes = await userListNoPage(); |
| | | userList.value = userRes.data || []; |
| | | } catch (e) { |
| | | console.error("å è½½æ£éªåå表失败", e); |
| | | userList.value = []; |
| | | } |
| | | }; |
| | | |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | const params = { ...searchForm.value, ...page.value }; |
| | | params.entryDate = undefined; |
| | | qualityInspectListPage({ ...params, inspectType: 2 }) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | inspectionList.value = res.data.records || []; |
| | | page.value.total = res.data.total || 0; |
| | | totalCount.value = res.data.total || 0; |
| | | submittedCount.value = inspectionList.value.filter( |
| | | item => item.inspectState |
| | | ).length; |
| | | pendingCount.value = inspectionList.value.filter( |
| | | item => !item.inspectState |
| | | ).length; |
| | | qualifiedCount.value = inspectionList.value.filter( |
| | | item => item.checkResult === "åæ ¼" |
| | | ).length; |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | console.error("è·åå表失败:", err); |
| | | showToast("è·åå表失败ï¼è¯·éè¯"); |
| | | }); |
| | | }; |
| | | |
| | | // ç¼è¾æ£éª |
| | | const startInspection = item => { |
| | | if (!item) { |
| | | showToast("åæ°é误"); |
| | | return; |
| | | } |
| | | console.log(item, "item"); |
| | | // åå¨å®æ´çæ£éªæ°æ® |
| | | uni.setStorageSync("finalInspectionEditData", item); |
| | | // 跳转å°ç¼è¾é¡µé¢ |
| | | uni.navigateTo({ |
| | | url: `/pages/qualityManagement/finalInspection/add?id=${item.id}&isEdit=true`, |
| | | }); |
| | | }; |
| | | |
| | | // æ¥ç详æ
|
| | | const viewDetail = item => { |
| | | if (!item) { |
| | | showToast("åæ°é误"); |
| | | return; |
| | | } |
| | | uni.setStorageSync("finalInspectionEditData", item); |
| | | // 跳转å°è¯¦æ
é¡µé¢ |
| | | uni.navigateTo({ |
| | | url: `/pages/qualityManagement/finalInspection/detail?id=${item.id}`, |
| | | }); |
| | | }; |
| | | |
| | | // æ°å¢æ£éª |
| | | const addInspection = () => { |
| | | uni.navigateTo({ |
| | | url: "/pages/qualityManagement/finalInspection/add", |
| | | }); |
| | | }; |
| | | |
| | | // æäº¤æ£éª |
| | | const submitInspection = async item => { |
| | | if (!item) { |
| | | showToast("åæ°é误"); |
| | | return; |
| | | } |
| | | try { |
| | | const res = await submitQualityInspect({ id: item.id }); |
| | | if (res.code === 200) { |
| | | showToast("æäº¤æå"); |
| | | setTimeout(() => { |
| | | getList(); |
| | | }, 1000); |
| | | } else { |
| | | showToast("æäº¤å¤±è´¥ï¼" + (res.msg || "æªç¥é误")); |
| | | } |
| | | } catch (error) { |
| | | console.error("æäº¤å¤±è´¥:", error); |
| | | showToast("æäº¤å¤±è´¥ï¼è¯·éè¯"); |
| | | } |
| | | }; |
| | | |
| | | // åé
æ£éªå |
| | | const assignInspector = item => { |
| | | if (!item) { |
| | | showToast("åæ°é误"); |
| | | return; |
| | | } |
| | | currentAssignRow.value = item; |
| | | getUserList(); |
| | | showAssignDialog.value = true; |
| | | }; |
| | | |
| | | // éæ©æ£éªå |
| | | const selectInspector = e => { |
| | | assignForm.value.checkName = e.value; |
| | | showInspectorSheet.value = false; |
| | | }; |
| | | |
| | | // æäº¤åé
|
| | | const submitAssign = async () => { |
| | | if (!currentAssignRow.value || !assignForm.value.checkName) { |
| | | showToast("è¯·éæ©æ£éªå"); |
| | | return; |
| | | } |
| | | try { |
| | | const data = { |
| | | ...assignForm.value, |
| | | id: currentAssignRow.value.id, |
| | | }; |
| | | const res = await qualityInspectUpdate(data); |
| | | if (res.code === 200) { |
| | | showToast("åé
æå"); |
| | | showAssignDialog.value = false; |
| | | setTimeout(() => { |
| | | getList(); |
| | | }, 1000); |
| | | } else { |
| | | showToast("åé
失败ï¼" + (res.msg || "æªç¥é误")); |
| | | } |
| | | } catch (error) { |
| | | console.error("åé
失败:", error); |
| | | showToast("åé
失败ï¼è¯·éè¯"); |
| | | } |
| | | }; |
| | | |
| | | // å¤çå页 |
| | | const handlePagination = obj => { |
| | | page.value.current = obj.current; |
| | | page.value.size = obj.size; |
| | | getList(); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | getUserList(); |
| | | }); |
| | | |
| | | onShow(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "../../../styles/sales-common.scss"; |
| | | |
| | | .material-inspection-page { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 80px; |
| | | } |
| | | |
| | | // æç´¢åºå |
| | | .search-section { |
| | | padding: 10px 15px; |
| | | background: #fff; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | } |
| | | |
| | | .search-bar { |
| | | display: flex; |
| | | align-items: center; |
| | | background: #f8f9fa; |
| | | border-radius: 20px; |
| | | padding: 0 15px; |
| | | height: 40px; |
| | | } |
| | | |
| | | .search-input { |
| | | flex: 1; |
| | | } |
| | | |
| | | .search-text { |
| | | background: transparent; |
| | | border: none; |
| | | } |
| | | |
| | | .filter-button { |
| | | margin-left: 10px; |
| | | padding: 5px; |
| | | } |
| | | |
| | | // ç»è®¡å¡ç |
| | | .stats-cards { |
| | | display: flex; |
| | | padding: 15px; |
| | | gap: 10px; |
| | | background: #fff; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .stat-card { |
| | | flex: 1; |
| | | background: #2979ff; |
| | | border-radius: 12px; |
| | | padding: 15px; |
| | | text-align: center; |
| | | color: #fff; |
| | | box-shadow: 0 2px 8px rgba(41, 121, 255, 0.2); |
| | | } |
| | | |
| | | .stat-number { |
| | | display: block; |
| | | font-size: 20px; |
| | | font-weight: 600; |
| | | margin-bottom: 5px; |
| | | } |
| | | |
| | | .stat-label { |
| | | font-size: 12px; |
| | | opacity: 0.9; |
| | | } |
| | | |
| | | // æ£éªå表 |
| | | .inspection-list { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .inspection-item { |
| | | background: #ffffff; |
| | | border-radius: 12px; |
| | | margin-bottom: 16px; |
| | | overflow: hidden; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); |
| | | padding: 0 16px; |
| | | |
| | | &:active { |
| | | transform: scale(0.98); |
| | | box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1); |
| | | } |
| | | } |
| | | |
| | | .item-header { |
| | | padding: 16px 0; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .item-left { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .material-icon { |
| | | width: 24px; |
| | | height: 24px; |
| | | background: #2979ff; |
| | | border-radius: 4px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .state-pending { |
| | | background: #ff9900; |
| | | } |
| | | |
| | | .state-submitted { |
| | | background: #52c41a; |
| | | } |
| | | |
| | | .material-info { |
| | | flex: 1; |
| | | } |
| | | |
| | | .material-name { |
| | | font-size: 14px; |
| | | color: #333; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .material-code { |
| | | font-size: 12px; |
| | | color: #999; |
| | | margin-left: 8px; |
| | | } |
| | | |
| | | .status-tags { |
| | | display: flex; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .status-tag { |
| | | margin: 0; |
| | | } |
| | | |
| | | .date-range { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | margin-top: 10px; |
| | | padding: 8px 12px; |
| | | background: #f8f9fa; |
| | | border-radius: 8px; |
| | | } |
| | | |
| | | .date-text { |
| | | font-size: 12px; |
| | | color: #666; |
| | | } |
| | | |
| | | // 详æ
è¡ |
| | | .item-details { |
| | | padding: 16px 0; |
| | | } |
| | | |
| | | .detail-row { |
| | | display: flex; |
| | | align-items: flex-end; |
| | | justify-content: space-between; |
| | | margin-bottom: 8px; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | } |
| | | |
| | | .detail-label { |
| | | font-size: 12px; |
| | | color: #777777; |
| | | min-width: 60px; |
| | | } |
| | | |
| | | .detail-value { |
| | | font-size: 12px; |
| | | color: #000000; |
| | | text-align: right; |
| | | flex: 1; |
| | | margin-left: 16px; |
| | | } |
| | | |
| | | // æä½æé® |
| | | .action-buttons { |
| | | display: flex; |
| | | gap: 12px; |
| | | padding: 0 0 16px 0; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .action-btn { |
| | | flex: 1; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | gap: 8px; |
| | | } |
| | | |
| | | // ç©ºç¶æ |
| | | .no-data { |
| | | padding: 60px 20px; |
| | | text-align: center; |
| | | } |
| | | |
| | | // æµ®å¨æé® |
| | | .fab-button { |
| | | position: fixed; |
| | | bottom: 20px; |
| | | right: 20px; |
| | | width: 56px; |
| | | height: 56px; |
| | | background: #2979ff; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | box-shadow: 0 4px 16px rgba(41, 121, 255, 0.3); |
| | | z-index: 1000; |
| | | } |
| | | |
| | | // åé
æ£éªåå¼¹çª |
| | | .assign-dialog { |
| | | padding: 24px; |
| | | background: #ffffff; |
| | | border-radius: 12px; |
| | | } |
| | | |
| | | .dialog-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 24px; |
| | | padding-bottom: 16px; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | } |
| | | |
| | | .dialog-title { |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | } |
| | | |
| | | .dialog-content { |
| | | margin-bottom: 24px; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | display: flex; |
| | | gap: 16px; |
| | | padding-top: 16px; |
| | | border-top: 1px solid #f0f0f0; |
| | | } |
| | | |
| | | .footer-btn { |
| | | flex: 1; |
| | | height: 44px; |
| | | font-size: 16px; |
| | | } |
| | | |
| | | // è¾å
¥æ¡æ ·å¼ |
| | | :deep(.up-input__inner) { |
| | | border-radius: 8px; |
| | | height: 44px; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | // 表åé¡¹æ ·å¼ |
| | | :deep(.up-form-item) { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | :deep(.up-form-item__label) { |
| | | font-size: 14px; |
| | | color: #606266; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | // æé®æ ·å¼ |
| | | :deep(.up-button--primary) { |
| | | border-radius: 8px; |
| | | } |
| | | |
| | | :deep(.up-button--default) { |
| | | border-radius: 8px; |
| | | } |
| | | |
| | | // å页ç»ä»¶ |
| | | .pagination { |
| | | padding: 20px; |
| | | background: #fff; |
| | | margin-top: 10px; |
| | | display: flex; |
| | | justify-content: center; |
| | | } |
| | | </style> |
| | |
| | | ) { |
| | | // 妿æ¥å£æ²¡æè¿åæ°æ®ï¼ä½¿ç¨æ¬å°åå¨ä¸çæ°æ® |
| | | inspectionItems.value = detailDataFromStorage.qualityInspectParams; |
| | | } else { |
| | | // æ¨¡ææ£éªé¡¹ç® |
| | | inspectionItems.value = [ |
| | | { |
| | | parameterItem: "å度", |
| | | unit: "mm", |
| | | standardValue: "2.0 ± 0.1", |
| | | controlValue: "2.0 ± 0.05", |
| | | testValue: "2.05", |
| | | }, |
| | | { |
| | | parameterItem: "硬度", |
| | | unit: "HB", |
| | | standardValue: "⥠200", |
| | | controlValue: "⥠210", |
| | | testValue: "220", |
| | | }, |
| | | { |
| | | parameterItem: "表é¢è´¨é", |
| | | unit: "", |
| | | standardValue: "æ åçãæ éè", |
| | | controlValue: "æ åçãæ éè", |
| | | testValue: "åæ ¼", |
| | | }, |
| | | ]; |
| | | } |
| | | }) |
| | | .catch(error => { |
| | |
| | | inspectionItems.value = detailDataFromStorage.qualityInspectParams; |
| | | } |
| | | }); |
| | | } else { |
| | | // æ¨¡ææ°æ® |
| | | detailData.value = { |
| | | id: id, |
| | | checkTime: "2026-03-03", |
| | | purchaseContractNo: "PO20260303001", |
| | | supplier: "䏿µ·é屿ææéå
¬å¸", |
| | | checkName: "å¼ ä¸", |
| | | productName: "ä¸é颿¿æ", |
| | | model: "304", |
| | | unit: "kg", |
| | | quantity: 1000, |
| | | checkCompany: "ç¬¬ä¸æ¹æ£æµæºæ", |
| | | checkResult: "åæ ¼", |
| | | inspectState: true, |
| | | }; |
| | | |
| | | // æ¨¡ææ£éªé¡¹ç® |
| | | inspectionItems.value = [ |
| | | { |
| | | parameterItem: "å度", |
| | | unit: "mm", |
| | | standardValue: "2.0 ± 0.1", |
| | | controlValue: "2.0 ± 0.05", |
| | | testValue: "2.05", |
| | | }, |
| | | { |
| | | parameterItem: "硬度", |
| | | unit: "HB", |
| | | standardValue: "⥠200", |
| | | controlValue: "⥠210", |
| | | testValue: "220", |
| | | }, |
| | | { |
| | | parameterItem: "表é¢è´¨é", |
| | | unit: "", |
| | | standardValue: "æ åçãæ éè", |
| | | controlValue: "æ åçãæ éè", |
| | | testValue: "åæ ¼", |
| | | }, |
| | | ]; |
| | | } |
| | | } catch (error) { |
| | | console.error("å 载详æ
æ°æ®å¤±è´¥:", error); |
| | | showToast("å 载详æ
æ°æ®å¤±è´¥ï¼è¯·éè¯"); |
| | | // å 载失败æ¶ä½¿ç¨æ¨¡ææ°æ® |
| | | detailData.value = { |
| | | id: id, |
| | | checkTime: "2026-03-03", |
| | | purchaseContractNo: "PO20260303001", |
| | | supplier: "䏿µ·é屿ææéå
¬å¸", |
| | | checkName: "å¼ ä¸", |
| | | productName: "ä¸é颿¿æ", |
| | | model: "304", |
| | | unit: "kg", |
| | | quantity: 1000, |
| | | checkCompany: "ç¬¬ä¸æ¹æ£æµæºæ", |
| | | checkResult: "åæ ¼", |
| | | inspectState: true, |
| | | }; |
| | | |
| | | inspectionItems.value = [ |
| | | { |
| | | parameterItem: "å度", |
| | | unit: "mm", |
| | | standardValue: "2.0 ± 0.1", |
| | | controlValue: "2.0 ± 0.05", |
| | | testValue: "2.05", |
| | | }, |
| | | { |
| | | parameterItem: "硬度", |
| | | unit: "HB", |
| | | standardValue: "⥠200", |
| | | controlValue: "⥠210", |
| | | testValue: "220", |
| | | }, |
| | | { |
| | | parameterItem: "表é¢è´¨é", |
| | | unit: "", |
| | | standardValue: "æ åçãæ éè", |
| | | controlValue: "æ åçãæ éè", |
| | | testValue: "åæ ¼", |
| | | }, |
| | | ]; |
| | | } |
| | | }; |
| | | |
| | |
| | | showToast("åæ°é误"); |
| | | return; |
| | | } |
| | | uni.setStorageSync("inspectionEditData", item); |
| | | // 跳转å°è¯¦æ
é¡µé¢ |
| | | uni.navigateTo({ |
| | | url: `/pages/qualityManagement/materialInspection/detail?id=${item.id}`, |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="material-inspection-add"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader :title="isEdit ? 'ç¼è¾è¿ç¨æ£éª' : 'æ°å¢è¿ç¨æ£éª'" |
| | | @back="goBack" /> |
| | | <!-- 表åå
容 --> |
| | | <up-form :model="form" |
| | | ref="formRef" |
| | | label-width="110" |
| | | :rules="rules"> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <up-form-item label="å·¥åº" |
| | | prop="process" |
| | | required |
| | | border-bottom> |
| | | <up-input v-model="form.process" |
| | | placeholder="è¯·éæ©å·¥åº" |
| | | readonly |
| | | :disabled="processQuantityDisabled" /> |
| | | <template #right> |
| | | <up-icon @click="showprocessSheet = true" |
| | | name="arrow-right" /> |
| | | </template> |
| | | </up-form-item> |
| | | <up-form-item label="产ååç§°" |
| | | prop="productId" |
| | | required |
| | | border-bottom> |
| | | <up-input v-model="form.productName" |
| | | placeholder="è¯·éæ©äº§å" |
| | | readonly |
| | | @click="showProductTree = true" |
| | | :disabled="isEdit" /> |
| | | <template #right> |
| | | <up-icon @click="showProductTree = true" |
| | | name="arrow-right" /> |
| | | </template> |
| | | </up-form-item> |
| | | <up-form-item label="è§æ ¼åå·" |
| | | prop="productModelId" |
| | | required |
| | | border-bottom> |
| | | <up-input v-model="form.model" |
| | | placeholder="è¯·éæ©è§æ ¼åå·" |
| | | readonly |
| | | :disabled="isEdit" /> |
| | | <template #right> |
| | | <up-icon @click="showModelSheet = true" |
| | | name="arrow-right" /> |
| | | </template> |
| | | </up-form-item> |
| | | <up-form-item label="ææ éæ©" |
| | | prop="testStandardId" |
| | | border-bottom> |
| | | <up-input v-model="testStandardDisplay" |
| | | placeholder="è¯·éæ©ææ " |
| | | readonly /> |
| | | <template #right> |
| | | <up-icon @click="openTestStandardSheet" |
| | | name="arrow-right" /> |
| | | </template> |
| | | </up-form-item> |
| | | <up-form-item label="åä½" |
| | | prop="unit" |
| | | border-bottom> |
| | | <up-input v-model="form.unit" |
| | | placeholder="请è¾å
¥åä½" |
| | | disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="æ°é" |
| | | prop="quantity" |
| | | required |
| | | border-bottom> |
| | | <up-input v-model="form.quantity" |
| | | type="number" |
| | | placeholder="请è¾å
¥æ°é" |
| | | :disabled="processQuantityDisabled" /> |
| | | </up-form-item> |
| | | <up-form-item label="æ£æµåä½" |
| | | prop="checkCompany" |
| | | border-bottom> |
| | | <up-input v-model="form.checkCompany" |
| | | placeholder="请è¾å
¥æ£æµåä½" |
| | | clearable /> |
| | | </up-form-item> |
| | | <up-form-item label="æ£æµç»æ" |
| | | prop="checkResult" |
| | | required |
| | | border-bottom> |
| | | <up-input v-model="form.checkResult" |
| | | placeholder="è¯·éæ©æ£æµç»æ" |
| | | readonly |
| | | @click="showResultSheet" /> |
| | | <template #right> |
| | | <up-icon @click="showResultSheet = true" |
| | | name="arrow-right" /> |
| | | </template> |
| | | </up-form-item> |
| | | <up-form-item label="æ£éªå" |
| | | prop="checkName" |
| | | border-bottom> |
| | | <up-input v-model="form.checkName" |
| | | placeholder="è¯·éæ©æ£éªå" |
| | | readonly |
| | | @click="showInspectorSheet" /> |
| | | <template #right> |
| | | <up-icon @click="showInspectorSheet = true" |
| | | name="arrow-right" /> |
| | | </template> |
| | | </up-form-item> |
| | | <up-form-item label="æ£æµæ¥æ" |
| | | prop="checkTime" |
| | | required |
| | | border-bottom> |
| | | <up-input v-model="form.checkTime" |
| | | placeholder="è¯·éæ©æ£æµæ¥æ" |
| | | readonly /> |
| | | <!-- <template #right> |
| | | <up-icon name="calendar" |
| | | @click="showDatePicker"></up-icon> |
| | | </template> --> |
| | | </up-form-item> |
| | | <!-- æ£éªé¡¹ç® --> |
| | | <view class="inspection-items-container"> |
| | | <view class="steps-header"> |
| | | <text class="steps-title">æ£éªé¡¹ç®</text> |
| | | <text class="steps-count">å
± {{ tableData.length }} 个项ç®</text> |
| | | </view> |
| | | <view class="steps-list"> |
| | | <view v-for="(item, index) in tableData" |
| | | :key="index" |
| | | class="exec-step-item"> |
| | | <view class="step-number"> |
| | | {{ index + 1 }} |
| | | </view> |
| | | <view class="step-content"> |
| | | <view class="step-row"> |
| | | <text class="step-label">ææ ï¼</text> |
| | | <text class="step-value">{{ item.parameterItem }}</text> |
| | | </view> |
| | | <view class="step-row"> |
| | | <text class="step-label">åä½ï¼</text> |
| | | <text class="step-value">{{ item.unit }}</text> |
| | | </view> |
| | | <view class="step-row"> |
| | | <text class="step-label">æ åå¼ï¼</text> |
| | | <text class="step-value">{{ item.standardValue }}</text> |
| | | </view> |
| | | <view class="step-row"> |
| | | <text class="step-label">å
æ§å¼ï¼</text> |
| | | <text class="step-value">{{ item.controlValue }}</text> |
| | | </view> |
| | | <view class="step-row"> |
| | | <text class="step-label">æ£éªå¼ï¼</text> |
| | | <up-input v-model="item.testValue" |
| | | placeholder="请è¾å
¥æ£éªå¼" |
| | | clearable |
| | | border-bottom |
| | | class="step-input" /> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-if="tableData.length === 0" |
| | | class="empty-data"> |
| | | <text>请å
éæ©ææ </text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </up-form> |
| | | <!-- åºé¨æé® --> |
| | | <view class="bottom-buttons"> |
| | | <up-button type="default" |
| | | size="default" |
| | | @click="goBack" |
| | | class="bottom-btn"> |
| | | åæ¶ |
| | | </up-button> |
| | | <up-button type="primary" |
| | | size="default" |
| | | @click="submitForm" |
| | | :loading="loading" |
| | | class="bottom-btn"> |
| | | {{ isEdit ? 'ä¿å' : 'æäº¤' }} |
| | | </up-button> |
| | | </view> |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <up-popup v-model:show="showDate" |
| | | mode="date" |
| | | :start-year="2020" |
| | | :end-year="2030" |
| | | @confirm="confirmDate" /> |
| | | <!-- å·¥åºéæ© --> |
| | | <up-action-sheet :show="showprocessSheet" |
| | | :actions="processOptions" |
| | | @select="selectprocess" |
| | | @close="showprocessSheet = false" |
| | | title="鿩工åº" /> |
| | | <!-- 产åéæ© --> |
| | | <up-action-sheet :show="showProductSheet" |
| | | :actions="productSheetOptions" |
| | | @select="selectProduct" |
| | | @close="showProductSheet = false" |
| | | title="éæ©äº§å" /> |
| | | <!-- è§æ ¼åå·éæ© --> |
| | | <up-action-sheet :show="showModelSheet" |
| | | :actions="modelSheetOptions" |
| | | @select="selectModel" |
| | | @close="showModelSheet = false" |
| | | title="éæ©è§æ ¼åå·" /> |
| | | <!-- æ£æµç»æéæ© --> |
| | | <up-action-sheet :show="showResultSheet" |
| | | :actions="resultSheetOptions" |
| | | @select="selectResult" |
| | | @close="showResultSheet = false" |
| | | title="éæ©æ£æµç»æ" /> |
| | | <!-- æ£éªåéæ© --> |
| | | <up-action-sheet :show="showInspectorSheet" |
| | | :actions="userSheetOptions" |
| | | @select="selectInspector" |
| | | @close="showInspectorSheet = false" |
| | | title="éæ©æ£éªå" /> |
| | | <!-- ææ éæ© --> |
| | | <up-action-sheet :show="showTestStandardSheet" |
| | | :actions="testStandardSheetOptions" |
| | | @select="selectTestStandard" |
| | | @close="showTestStandardSheet = false" |
| | | title="éæ©ææ " /> |
| | | <!-- äº§åæ å½¢éæ©å¨ --> |
| | | <up-popup v-model:show="showProductTree" |
| | | position="bottom" |
| | | :round="true" |
| | | :closeable="true" |
| | | @close="showProductTree = false"> |
| | | <view class="tree-selector"> |
| | | <view class="tree-header"> |
| | | <text class="tree-title">éæ©äº§å</text> |
| | | </view> |
| | | <view class="tree-content"> |
| | | <view class="tree-node" |
| | | v-for="(node, index) in productOptions" |
| | | :key="index"> |
| | | <view v-if="node.children && node.children.length > 0" |
| | | class="tree-node-header" |
| | | @click="toggleNode(node)"> |
| | | <up-icon :name="node.expanded ? 'arrow-down' : 'arrow-right'" |
| | | class="tree-node-icon" /> |
| | | <text class="tree-node-label">{{ node.label }}</text> |
| | | </view> |
| | | <view v-else |
| | | class="tree-node-header" |
| | | @click="selectTreeNode(node)"> |
| | | <text class="tree-node-icon-placeholder"></text> |
| | | <text class="tree-node-label">{{ node.label }}</text> |
| | | <up-icon name="checkmark" |
| | | v-if="form.productId == node.value" |
| | | class="tree-node-check" /> |
| | | </view> |
| | | <view v-if="node.children && node.children.length > 0 && node.expanded" |
| | | class="tree-node-children"> |
| | | <view class="tree-node" |
| | | v-for="(child, childIndex) in node.children" |
| | | :key="childIndex"> |
| | | <view v-if="child.children && child.children.length > 0" |
| | | class="tree-node-header" |
| | | @click="toggleNode(child)"> |
| | | <up-icon :name="child.expanded ? 'arrow-down' : 'arrow-right'" |
| | | class="tree-node-icon" /> |
| | | <text class="tree-node-label">{{ child.label }}</text> |
| | | </view> |
| | | <view v-else |
| | | class="tree-node-header" |
| | | @click="selectTreeNode(child)"> |
| | | <text class="tree-node-icon-placeholder"></text> |
| | | <text class="tree-node-label">{{ child.label }}</text> |
| | | <up-icon name="checkmark" |
| | | v-if="form.productId == child.value" |
| | | class="tree-node-check" /> |
| | | </view> |
| | | <view v-if="child.children && child.children.length > 0 && child.expanded" |
| | | class="tree-node-children"> |
| | | <view class="tree-node" |
| | | v-for="(grandchild, grandchildIndex) in child.children" |
| | | :key="grandchildIndex"> |
| | | <view class="tree-node-header" |
| | | @click="selectTreeNode(grandchild)"> |
| | | <text class="tree-node-icon-placeholder"></text> |
| | | <text class="tree-node-label">{{ grandchild.label }}</text> |
| | | <up-icon name="checkmark" |
| | | v-if="form.productId == grandchild.value" |
| | | class="tree-node-check" /> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </up-popup> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, computed, onMounted, nextTick } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import dayjs from "dayjs"; |
| | | import { getOptions } from "@/api/procurementManagement/procurementLedger.js"; |
| | | import { modelList, productTreeList } from "@/api/basicData/product.js"; |
| | | import { |
| | | qualityInspectAdd, |
| | | qualityInspectUpdate, |
| | | qualityInspectParamInfo, |
| | | qualityInspectDetailByProductId, |
| | | getQualityTestStandardParamByTestStandardId, |
| | | list, |
| | | } from "@/api/qualityManagement/materialInspection.js"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | |
| | | // æ¾ç¤ºæç¤ºä¿¡æ¯ |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | // 表åå¼ç¨ |
| | | const formRef = ref(null); |
| | | // å è½½ç¶æ |
| | | const loading = ref(false); |
| | | // æ¥æéæ©å¨ |
| | | const showDate = ref(false); |
| | | // å·¥åºéæ© |
| | | const showprocessSheet = ref(false); |
| | | // 产åéæ© |
| | | const showProductSheet = ref(false); |
| | | // äº§åæ å½¢éæ©å¨ |
| | | const showProductTree = ref(false); |
| | | // è§æ ¼åå·éæ© |
| | | const showModelSheet = ref(false); |
| | | // æ£æµç»æéæ© |
| | | const showResultSheet = ref(false); |
| | | // æ£éªåéæ© |
| | | const showInspectorSheet = ref(false); |
| | | // ææ éæ© |
| | | const showTestStandardSheet = ref(false); |
| | | |
| | | // è¡¨åæ°æ® |
| | | const form = ref({ |
| | | checkTime: dayjs().format("YYYY-MM-DD"), |
| | | process: "", |
| | | checkName: "", |
| | | productName: "", |
| | | productId: "", |
| | | productModelId: "", |
| | | model: "", |
| | | testStandardId: "", |
| | | unit: "", |
| | | quantity: "", |
| | | checkCompany: "", |
| | | checkResult: "", |
| | | productMainId: null, |
| | | purchaseLedgerId: null, |
| | | }); |
| | | |
| | | // æ¾ç¤ºç¨çåé |
| | | const testStandardDisplay = ref(""); |
| | | |
| | | // æ£éªé¡¹ç® |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | |
| | | // å·¥åºå表 |
| | | const processList = ref([]); |
| | | // 产åé项 |
| | | const productOptions = ref([]); |
| | | // åå·é项 |
| | | const modelOptions = ref([]); |
| | | // æ£éªåå表 |
| | | const userList = ref([]); |
| | | // æ£æµç»æé项 |
| | | const resultOptions = ref([ |
| | | { label: "åæ ¼", value: "åæ ¼" }, |
| | | { label: "ä¸åæ ¼", value: "ä¸åæ ¼" }, |
| | | ]); |
| | | // ææ é项 |
| | | const testStandardOptions = ref([]); |
| | | // å½å产åID |
| | | const currentProductId = ref(0); |
| | | |
| | | // ActionSheeté项 |
| | | const processOptions = computed(() => { |
| | | return processList.value.map(item => ({ |
| | | name: item.name, |
| | | value: item.name, |
| | | })); |
| | | }); |
| | | |
| | | const productSheetOptions = computed(() => { |
| | | return productOptions.value.map(item => ({ |
| | | name: item.label, |
| | | value: item.value, |
| | | })); |
| | | }); |
| | | |
| | | const modelSheetOptions = computed(() => { |
| | | return modelOptions.value.map(item => ({ |
| | | name: item.model, |
| | | value: item.id, |
| | | })); |
| | | }); |
| | | |
| | | const resultSheetOptions = computed(() => { |
| | | return resultOptions.value.map(item => ({ |
| | | name: item.label, |
| | | value: item.value, |
| | | })); |
| | | }); |
| | | |
| | | const userSheetOptions = computed(() => { |
| | | return userList.value.map(item => ({ |
| | | name: item.nickName, |
| | | value: item.nickName, |
| | | })); |
| | | }); |
| | | |
| | | const testStandardSheetOptions = computed(() => { |
| | | return testStandardOptions.value.map(item => ({ |
| | | name: item.standardName || item.standardNo, |
| | | value: item.id, |
| | | })); |
| | | }); |
| | | |
| | | // 表åéªè¯è§å |
| | | const rules = { |
| | | checkTime: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | process: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | checkName: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | productId: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | productModelId: [ |
| | | { required: true, message: "è¯·éæ©äº§ååå·", trigger: "change" }, |
| | | ], |
| | | testStandardId: [ |
| | | { required: false, message: "è¯·éæ©ææ ", trigger: "change" }, |
| | | ], |
| | | unit: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | quantity: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | checkCompany: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | checkResult: [ |
| | | { required: true, message: "è¯·éæ©æ£æµç»æ", trigger: "change" }, |
| | | ], |
| | | }; |
| | | |
| | | // æ¯å¦ä¸ºç¼è¾æ¨¡å¼ |
| | | const isEdit = computed(() => { |
| | | const id = getPageId(); |
| | | return !!id; |
| | | }); |
| | | |
| | | // ç¼è¾æ¶ï¼productMainId æ purchaseLedgerId 任䏿å¼åå·¥åºãæ°éç½®ç° |
| | | const processQuantityDisabled = computed(() => { |
| | | const v = form.value || {}; |
| | | return !!(v.productMainId != null || v.purchaseLedgerId != null); |
| | | }); |
| | | |
| | | // è·å页é¢ID |
| | | const getPageId = () => { |
| | | const pages = getCurrentPages(); |
| | | const currentPage = pages[pages.length - 1]; |
| | | return currentPage.options.id; |
| | | }; |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // æ¾ç¤ºæ¥æéæ©å¨ |
| | | const showDatePicker = () => { |
| | | showDate.value = true; |
| | | }; |
| | | |
| | | // ç¡®è®¤æ¥æéæ© |
| | | const confirmDate = e => { |
| | | form.value.checkTime = dayjs(e.value).format("YYYY-MM-DD"); |
| | | }; |
| | | |
| | | // éæ©å·¥åº |
| | | const selectprocess = e => { |
| | | form.value.process = e.value; |
| | | showprocessSheet.value = false; |
| | | }; |
| | | |
| | | // éæ©äº§å |
| | | const selectProduct = e => { |
| | | form.value.productId = e.value; |
| | | form.value.productName = e.name; |
| | | showProductSheet.value = false; |
| | | getModels(e.value); |
| | | }; |
| | | |
| | | // 忢æ å½¢èç¹å±å¼/æå |
| | | const toggleNode = node => { |
| | | node.expanded = !node.expanded; |
| | | }; |
| | | |
| | | // éæ©æ å½¢èç¹ |
| | | const selectTreeNode = node => { |
| | | // ç¡®ä¿åªéæ©æ«ç«¯èç¹ |
| | | if (!node.children || node.children.length == 0) { |
| | | form.value.productId = node.value; |
| | | form.value.productName = node.label; |
| | | showProductTree.value = false; |
| | | getModels(node.value); |
| | | } |
| | | }; |
| | | |
| | | // 转æ¢äº§åæ ç»æ |
| | | function convertIdToValue(data) { |
| | | return data.map(item => { |
| | | const { id, children, ...rest } = item; |
| | | const newItem = { |
| | | ...rest, |
| | | value: id, // å° id æ¹ä¸º value |
| | | }; |
| | | if (children && children.length > 0) { |
| | | newItem.children = convertIdToValue(children); |
| | | } |
| | | |
| | | return newItem; |
| | | }); |
| | | } |
| | | |
| | | // æ ¹æ®IDæ¥æ¾èç¹ |
| | | const findNodeById = (nodes, productId) => { |
| | | for (let i = 0; i < nodes.length; i++) { |
| | | if (nodes[i].value === productId) { |
| | | return nodes[i].label; // æ¾å°èç¹ï¼è¿å该èç¹ |
| | | } |
| | | if (nodes[i].children && nodes[i].children.length > 0) { |
| | | const foundNode = findNodeById(nodes[i].children, productId); |
| | | if (foundNode) { |
| | | return foundNode; // å¨åèç¹ä¸æ¾å°ï¼è¿å该èç¹ |
| | | } |
| | | } |
| | | } |
| | | return null; // æ²¡ææ¾å°èç¹ï¼è¿ånull |
| | | }; |
| | | |
| | | // éæ©è§æ ¼åå· |
| | | const selectModel = e => { |
| | | form.value.productModelId = e.value; |
| | | showModelSheet.value = false; |
| | | handleChangeModel(e.value); |
| | | }; |
| | | |
| | | // å¤çåå·åå |
| | | const handleChangeModel = value => { |
| | | form.value.model = |
| | | modelOptions.value.find(item => item.id == value)?.model || ""; |
| | | form.value.unit = |
| | | modelOptions.value.find(item => item.id == value)?.unit || ""; |
| | | }; |
| | | |
| | | // éæ©æ£æµç»æ |
| | | const selectResult = e => { |
| | | form.value.checkResult = e.value; |
| | | showResultSheet.value = false; |
| | | }; |
| | | |
| | | // éæ©æ£éªå |
| | | const selectInspector = e => { |
| | | form.value.checkName = e.value; |
| | | showInspectorSheet.value = false; |
| | | }; |
| | | |
| | | // éæ©ææ |
| | | const selectTestStandard = e => { |
| | | form.value.testStandardId = e.value; |
| | | testStandardDisplay.value = e.name; |
| | | showTestStandardSheet.value = false; |
| | | handleTestStandardChange(e.value); |
| | | }; |
| | | |
| | | // ææ éæ©ååå¤ç |
| | | const handleTestStandardChange = testStandardId => { |
| | | if (!testStandardId) { |
| | | tableData.value = []; |
| | | return; |
| | | } |
| | | tableLoading.value = true; |
| | | getQualityTestStandardParamByTestStandardId(testStandardId) |
| | | .then(res => { |
| | | tableData.value = res.data || []; |
| | | }) |
| | | .catch(error => { |
| | | console.error("è·åæ ååæ°å¤±è´¥:", error); |
| | | tableData.value = []; |
| | | }) |
| | | .finally(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | const openTestStandardSheet = () => { |
| | | console.log("openTestStandardSheet"); |
| | | showTestStandardSheet.value = true; |
| | | }; |
| | | |
| | | // è·åå·¥åºå表 |
| | | const getprocessList = () => { |
| | | list().then(res => { |
| | | processList.value = res.data; |
| | | }); |
| | | }; |
| | | |
| | | // è·å产åé项 |
| | | const getProductOptions = () => { |
| | | return productTreeList().then(res => { |
| | | productOptions.value = convertIdToValue(res); |
| | | return productOptions.value; |
| | | }); |
| | | }; |
| | | |
| | | // è·åç¨æ·å表 |
| | | const getUserList = async () => { |
| | | try { |
| | | const userRes = await userListNoPage(); |
| | | userList.value = userRes.data || []; |
| | | } catch (e) { |
| | | console.error("å è½½æ£éªåå表失败", e); |
| | | userList.value = []; |
| | | } |
| | | }; |
| | | |
| | | // è·ååå·å表 |
| | | const getModels = value => { |
| | | form.value.productModelId = ""; |
| | | form.value.unit = ""; |
| | | modelOptions.value = []; |
| | | currentProductId.value = value; |
| | | form.value.productName = findNodeById(productOptions.value, value); |
| | | modelList({ id: value }).then(res => { |
| | | modelOptions.value = res; |
| | | }); |
| | | if (currentProductId.value) { |
| | | getList(); |
| | | } |
| | | }; |
| | | |
| | | // è·åææ å表 |
| | | const getList = () => { |
| | | if (!currentProductId.value) { |
| | | testStandardOptions.value = []; |
| | | tableData.value = []; |
| | | return; |
| | | } |
| | | let params = { |
| | | productId: currentProductId.value, |
| | | inspectType: 1, |
| | | }; |
| | | qualityInspectDetailByProductId(params).then(res => { |
| | | // ä¿å䏿æ¡éé¡¹æ°æ® |
| | | testStandardOptions.value = res.data || []; |
| | | // æ¸
ç©ºè¡¨æ ¼æ°æ®ï¼çå¾
ç¨æ·éæ©ææ |
| | | tableData.value = []; |
| | | // æ¸
ç©ºææ éæ© |
| | | form.value.testStandardId = ""; |
| | | testStandardDisplay.value = ""; |
| | | }); |
| | | }; |
| | | |
| | | // è·åæ£éªåæ°å表ï¼ç¼è¾æ¨¡å¼ï¼ |
| | | const getQualityInspectParamList = id => { |
| | | qualityInspectParamInfo(id).then(res => { |
| | | tableData.value = res.data; |
| | | }); |
| | | }; |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = async () => { |
| | | console.log("submitForm", form.value, tableData.value); |
| | | try { |
| | | // await formRef.value.validate(); |
| | | if (!form.value.productModelId) { |
| | | showToast("è¯·éæ©è§æ ¼åå·"); |
| | | return; |
| | | } |
| | | if (!form.value.process) { |
| | | showToast("è¯·éæ©å·¥åº"); |
| | | return; |
| | | } |
| | | if (!form.value.quantity) { |
| | | showToast("请è¾å
¥æ°é"); |
| | | return; |
| | | } |
| | | if (!form.value.productId) { |
| | | showToast("è¯·éæ©äº§å"); |
| | | return; |
| | | } |
| | | if (!form.value.checkResult) { |
| | | showToast("è¯·éæ©æ£æµç»æ"); |
| | | return; |
| | | } |
| | | |
| | | loading.value = true; |
| | | |
| | | form.value.inspectType = 1; |
| | | if (isEdit.value) { |
| | | tableData.value.forEach(item => { |
| | | delete item.id; |
| | | }); |
| | | } |
| | | |
| | | const data = { ...form.value, qualityInspectParams: tableData.value }; |
| | | data.quantity = Number(data.quantity); |
| | | if (isEdit.value) { |
| | | const res = await qualityInspectUpdate(data); |
| | | showToast("ä¿åæå"); |
| | | setTimeout(() => { |
| | | uni.navigateBack(); |
| | | }, 1500); |
| | | } else { |
| | | const res = await qualityInspectAdd(data); |
| | | showToast("æäº¤æå"); |
| | | setTimeout(() => { |
| | | uni.navigateBack(); |
| | | }, 1500); |
| | | } |
| | | } catch (error) { |
| | | console.error("表åéªè¯å¤±è´¥:", error); |
| | | showToast("æäº¤å¤±è´¥ï¼è¯·éè¯"); |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | |
| | | // åå§å表å |
| | | const initForm = async () => { |
| | | const id = getPageId(); |
| | | if (id) { |
| | | // ç¼è¾æ¨¡å¼ï¼å è½½æ°æ® |
| | | // å
éç½®è¡¨åæ°æ® |
| | | form.value = { |
| | | checkTime: dayjs().format("YYYY-MM-DD"), |
| | | process: "", |
| | | checkName: "", |
| | | productName: "", |
| | | productId: "", |
| | | productModelId: "", |
| | | model: "", |
| | | testStandardId: "", |
| | | unit: "", |
| | | quantity: "", |
| | | checkCompany: "", |
| | | checkResult: "", |
| | | productMainId: null, |
| | | purchaseLedgerId: null, |
| | | }; |
| | | testStandardOptions.value = []; |
| | | tableData.value = []; |
| | | // å
ç¡®ä¿äº§åæ å·²å è½½ï¼å¦åç¼è¾æ¶äº§å/è§æ ¼åå·æ æ³åæ¾ |
| | | await getProductOptions(); |
| | | // 仿¬å°åå¨è·åç¼è¾æ°æ® |
| | | const row = uni.getStorageSync("processInspectionEditData") || { |
| | | id: id, |
| | | checkTime: "2026-03-03", |
| | | process: "䏿µ·é屿ææéå
¬å¸", |
| | | checkName: "å¼ ä¸", |
| | | productName: "ä¸é颿¿æ", |
| | | productId: 1, |
| | | productModelId: 1, |
| | | model: "304", |
| | | testStandardId: "1", |
| | | unit: "kg", |
| | | quantity: 1000, |
| | | checkCompany: "ç¬¬ä¸æ¹æ£æµæºæ", |
| | | checkResult: "åæ ¼", |
| | | productMainId: null, |
| | | purchaseLedgerId: null, |
| | | }; |
| | | // å
ä¿å testStandardIdï¼é¿å
被æ¸
空 |
| | | const savedTestStandardId = row.testStandardId; |
| | | form.value = { ...row }; |
| | | currentProductId.value = row.productId || 0; |
| | | // å
³é®ï¼ç¼è¾æ¶å è½½è§æ ¼åå·ä¸æéé¡¹ï¼æè½åæ¾ productModelId |
| | | if (currentProductId.value) { |
| | | try { |
| | | const res = await modelList({ id: currentProductId.value }); |
| | | modelOptions.value = res || []; |
| | | // 忥åå¡« model / unit |
| | | if (form.value.productModelId) { |
| | | handleChangeModel(form.value.productModelId); |
| | | } |
| | | } catch (e) { |
| | | console.error("å è½½è§æ ¼åå·å¤±è´¥", e); |
| | | modelOptions.value = []; |
| | | } |
| | | } |
| | | // ç¼è¾æ¨¡å¼ä¸ï¼å
å è½½ææ é项ï¼ç¶åå è½½åæ°å表 |
| | | if (currentProductId.value) { |
| | | // å
å è½½ææ é项 |
| | | let params = { |
| | | productId: currentProductId.value, |
| | | inspectType: 1, |
| | | }; |
| | | qualityInspectDetailByProductId(params).then(res => { |
| | | testStandardOptions.value = res.data || []; |
| | | // ä½¿ç¨ nextTick ç¡®ä¿éé¡¹å·²ç»æ¸²æ |
| | | nextTick(() => { |
| | | // 妿ç¼è¾æ°æ®ä¸æ testStandardIdï¼å设置并å 载对åºçåæ° |
| | | if (savedTestStandardId) { |
| | | // ç¡®ä¿ç±»åå¹é
|
| | | const matchedOption = testStandardOptions.value.find( |
| | | item => |
| | | item.id == savedTestStandardId || |
| | | String(item.id) === String(savedTestStandardId) |
| | | ); |
| | | if (matchedOption) { |
| | | // ç¡®ä¿ä½¿ç¨å¹é
项ç id |
| | | form.value.testStandardId = matchedOption.id; |
| | | testStandardDisplay.value = |
| | | matchedOption.standardName || matchedOption.standardNo; |
| | | // ç¼è¾ä¿ç忣éªå¼ï¼ç´æ¥æåååæ°æ°æ® |
| | | getQualityInspectParamList(row.id); |
| | | } else { |
| | | // 妿æ¾ä¸å°å¹é
项ï¼å°è¯ç´æ¥ä½¿ç¨åå¼ |
| | | console.warn( |
| | | "æªæ¾å°å¹é
çææ é项ï¼testStandardId:", |
| | | savedTestStandardId |
| | | ); |
| | | form.value.testStandardId = savedTestStandardId; |
| | | getQualityInspectParamList(row.id); |
| | | } |
| | | } else { |
| | | // å¦åä½¿ç¨æ§çé»è¾ |
| | | getQualityInspectParamList(row.id); |
| | | } |
| | | }); |
| | | }); |
| | | } |
| | | // å±å¼äº§åæ å°å½åéä¸çèç¹ |
| | | expandProductTree(productOptions.value, row.productId); |
| | | } else { |
| | | // æ°å¢æ¨¡å¼ï¼åå§å表å |
| | | form.value = { |
| | | checkTime: dayjs().format("YYYY-MM-DD"), |
| | | process: "", |
| | | checkName: "", |
| | | productName: "", |
| | | productId: "", |
| | | productModelId: "", |
| | | model: "", |
| | | testStandardId: "", |
| | | unit: "", |
| | | quantity: "", |
| | | checkCompany: "", |
| | | checkResult: "", |
| | | productMainId: null, |
| | | purchaseLedgerId: null, |
| | | }; |
| | | } |
| | | }; |
| | | |
| | | // å±å¼äº§åæ å°æå®èç¹ |
| | | const expandProductTree = (nodes, targetId) => { |
| | | for (let i = 0; i < nodes.length; i++) { |
| | | const node = nodes[i]; |
| | | if (node.value === targetId) { |
| | | return true; // æ¾å°ç®æ èç¹ |
| | | } |
| | | if (node.children && node.children.length > 0) { |
| | | const found = expandProductTree(node.children, targetId); |
| | | if (found) { |
| | | node.expanded = true; // å±å¼ç¶èç¹ |
| | | return true; |
| | | } |
| | | } |
| | | } |
| | | return false; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getprocessList(); |
| | | getProductOptions(); |
| | | getUserList(); |
| | | initForm(); |
| | | }); |
| | | |
| | | onShow(() => { |
| | | initForm(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "@/static/scss/form-common.scss"; |
| | | |
| | | .material-inspection-add { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 100px; |
| | | } |
| | | |
| | | // æ£éªé¡¹ç®å®¹å¨ |
| | | .inspection-items-container { |
| | | padding: 20px; |
| | | background-color: #fff; |
| | | } |
| | | |
| | | .steps-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | padding-bottom: 12px; |
| | | border-bottom: 1px solid #e4e7ed; |
| | | } |
| | | |
| | | .steps-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | } |
| | | |
| | | .steps-count { |
| | | font-size: 14px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .steps-list { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .exec-step-item { |
| | | position: relative; |
| | | display: flex; |
| | | margin-bottom: 16px; |
| | | padding: 16px; |
| | | background-color: #ffffff; |
| | | border: 1px solid #e4e7ed; |
| | | border-radius: 8px; |
| | | transition: all 0.3s ease; |
| | | box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05); |
| | | } |
| | | |
| | | .exec-step-item:hover { |
| | | box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); |
| | | border-color: #409eff; |
| | | transform: translateY(-1px); |
| | | } |
| | | |
| | | .delete-btn { |
| | | position: absolute; |
| | | top: -25rpx; |
| | | right: -25rpx; |
| | | width: 50rpx; |
| | | height: 50rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | text-align: center; |
| | | font-size: 20px; |
| | | border-radius: 50%; |
| | | background-color: red; |
| | | border: none; |
| | | z-index: 10; |
| | | } |
| | | |
| | | .delete-btn:hover { |
| | | transform: scale(1.1); |
| | | box-shadow: 0 3px 6px rgba(245, 108, 108, 0.4); |
| | | } |
| | | |
| | | .step-number { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | width: 32px; |
| | | height: 32px; |
| | | margin-right: 16px; |
| | | background-color: #ecf5ff; |
| | | color: #409eff; |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | border-radius: 50%; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .step-content { |
| | | flex: 1; |
| | | min-width: 0; |
| | | } |
| | | |
| | | .step-row { |
| | | display: flex; |
| | | align-items: flex-start; |
| | | margin-bottom: 12px; |
| | | } |
| | | |
| | | .step-row:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .step-label { |
| | | display: inline-block; |
| | | width: 80px; |
| | | font-size: 14px; |
| | | color: #606266; |
| | | margin-right: 12px; |
| | | flex-shrink: 0; |
| | | line-height: 36px; |
| | | } |
| | | |
| | | .step-input { |
| | | flex: 1; |
| | | min-width: 0; |
| | | } |
| | | |
| | | .step-input input { |
| | | font-size: 14px; |
| | | color: #303133; |
| | | } |
| | | |
| | | .add-step-btn { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | width: 100%; |
| | | height: 44px; |
| | | line-height: 44px; |
| | | font-size: 14px; |
| | | border-radius: 8px; |
| | | transition: all 0.3s ease; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .add-step-btn:hover { |
| | | transform: translateY(-1px); |
| | | box-shadow: 0 2px 8px rgba(64, 158, 255, 0.3); |
| | | } |
| | | |
| | | .add-step-btn text { |
| | | font-size: 14px; |
| | | } |
| | | |
| | | // åºé¨æé® |
| | | .bottom-buttons { |
| | | position: fixed; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | display: flex; |
| | | padding: 16px 20px; |
| | | background: #ffffff; |
| | | border-top: 1px solid #f0f0f0; |
| | | gap: 16px; |
| | | } |
| | | |
| | | .bottom-btn { |
| | | flex: 1; |
| | | } |
| | | |
| | | // æ 形鿩卿 ·å¼ |
| | | .tree-selector { |
| | | width: 100%; |
| | | max-height: 70vh; |
| | | background: #ffffff; |
| | | border-radius: 16px 16px 0 0; |
| | | } |
| | | |
| | | .tree-header { |
| | | padding: 16px 20px; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | text-align: center; |
| | | } |
| | | |
| | | .tree-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | } |
| | | |
| | | .tree-content { |
| | | padding: 10px 0; |
| | | max-height: calc(70vh - 60px); |
| | | overflow-y: auto; |
| | | } |
| | | |
| | | .tree-node { |
| | | padding: 0 20px; |
| | | } |
| | | |
| | | .tree-node-header { |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 12px 0; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .tree-node-icon { |
| | | width: 20px; |
| | | height: 20px; |
| | | margin-right: 8px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .tree-node-icon-placeholder { |
| | | width: 20px; |
| | | height: 20px; |
| | | margin-right: 8px; |
| | | } |
| | | |
| | | .tree-node-label { |
| | | flex: 1; |
| | | font-size: 14px; |
| | | color: #303133; |
| | | } |
| | | |
| | | .tree-node-check { |
| | | width: 20px; |
| | | height: 20px; |
| | | color: #409eff; |
| | | } |
| | | |
| | | .tree-node-children { |
| | | margin-left: 28px; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="material-inspection-detail"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="è¿ç¨æ£éªè¯¦æ
" |
| | | @back="goBack" /> |
| | | <!-- 详æ
å
容 --> |
| | | <view class="detail-section" |
| | | v-if="detailData"> |
| | | <view class="detail-card"> |
| | | <view class="card-header"> |
| | | <view class="header-icon"> |
| | | <up-icon name="file-text" |
| | | size="20" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | <text class="header-title">{{ detailData.productName || '-' }}</text> |
| | | <view class="status-tags"> |
| | | <u-tag :type="getTagType(detailData.checkResult)" |
| | | size="small" |
| | | class="status-tag"> |
| | | {{ detailData.checkResult || '-' }} |
| | | </u-tag> |
| | | <u-tag :type="getStateTagType(detailData.inspectState)" |
| | | size="small" |
| | | class="status-tag"> |
| | | {{ detailData.inspectState ? 'å·²æäº¤' : 'æªæäº¤' }} |
| | | </u-tag> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="detail-content"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">æ£æµæ¥æ</text> |
| | | <text class="detail-value">{{ formatDateTime(detailData.checkTime) || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç产工åå·</text> |
| | | <text class="detail-value">{{ detailData.workOrderNo || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å·¥åº</text> |
| | | <text class="detail-value">{{ detailData.process || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">æ£éªå</text> |
| | | <text class="detail-value">{{ detailData.checkName || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">产ååç§°</text> |
| | | <text class="detail-value">{{ detailData.productName || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">è§æ ¼åå·</text> |
| | | <text class="detail-value">{{ detailData.model || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">åä½</text> |
| | | <text class="detail-value">{{ detailData.unit || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">æ°é</text> |
| | | <text class="detail-value">{{ detailData.quantity || 0 }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">æ£æµåä½</text> |
| | | <text class="detail-value">{{ detailData.checkCompany || '-' }}</text> |
| | | </view> |
| | | <!-- <view class="detail-row"> |
| | | <text class="detail-label">æ£éªæ å</text> |
| | | <text class="detail-value">{{ detailData.testStandardName || '-' }}</text> |
| | | </view> --> |
| | | </view> |
| | | </view> |
| | | <!-- æ£éªé¡¹ç® --> |
| | | <view class="detail-card" |
| | | v-if="inspectionItems.length > 0"> |
| | | <view class="card-header"> |
| | | <view class="header-icon secondary"> |
| | | <up-icon name="list" |
| | | size="20" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | <text class="header-title">æ£éªé¡¹ç®</text> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="inspection-items"> |
| | | <view v-for="(item, index) in inspectionItems" |
| | | :key="index" |
| | | class="inspection-item"> |
| | | <text class="item-name">{{ item.parameterItem || 'æ£éªé¡¹ç®' }}</text> |
| | | <view class="item-details"> |
| | | <view class="item-detail-row"> |
| | | <text class="item-detail-label">åä½:</text> |
| | | <text class="item-detail-value">{{ item.unit || '-' }}</text> |
| | | </view> |
| | | <view class="item-detail-row"> |
| | | <text class="item-detail-label">æ åå¼:</text> |
| | | <text class="item-detail-value">{{ item.standardValue || '-' }}</text> |
| | | </view> |
| | | <view class="item-detail-row"> |
| | | <text class="item-detail-label">å
æ§å¼:</text> |
| | | <text class="item-detail-value">{{ item.controlValue || '-' }}</text> |
| | | </view> |
| | | <view class="item-detail-row"> |
| | | <text class="item-detail-label">æ£éªå¼:</text> |
| | | <text class="item-detail-value result" |
| | | :class="getResultClass(item.testValue, item.standardValue)"> |
| | | {{ item.testValue || '-' }} |
| | | </text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- æä½æé® --> |
| | | <!-- <view class="action-buttons"> |
| | | <u-button type="primary" |
| | | class="action-btn" |
| | | @click="downloadReport"> |
| | | ä¸è½½æ¥å |
| | | </u-button> |
| | | </view> --> |
| | | </view> |
| | | <view v-else |
| | | class="no-data"> |
| | | <up-empty mode="data" |
| | | text="ææ æ£éªè¯¦æ
"></up-empty> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import dayjs from "dayjs"; |
| | | import { qualityInspectParamInfo } from "@/api/qualityManagement/materialInspection.js"; |
| | | |
| | | // æ¾ç¤ºæç¤ºä¿¡æ¯ |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | // 详æ
æ°æ® |
| | | const detailData = ref(null); |
| | | // æ£éªé¡¹ç® |
| | | const inspectionItems = ref([]); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // æ ¼å¼åæ¥ææ¶é´ |
| | | const formatDateTime = date => { |
| | | if (!date) return ""; |
| | | return dayjs(date).format("YYYY-MM-DD"); |
| | | }; |
| | | |
| | | // è·åæ ç¾ç±»å |
| | | const getTagType = result => { |
| | | switch (result) { |
| | | case "åæ ¼": |
| | | return "success"; |
| | | case "ä¸åæ ¼": |
| | | return "error"; |
| | | default: |
| | | return "info"; |
| | | } |
| | | }; |
| | | |
| | | // è·åç¶ææ ç¾ç±»å |
| | | const getStateTagType = state => { |
| | | return state ? "success" : "warning"; |
| | | }; |
| | | |
| | | // è·åç»ææ ·å¼ |
| | | const getResultClass = (testValue, standardValue) => { |
| | | // ç®åçç»æå¤æé»è¾ï¼å®é
项ç®ä¸å¯è½éè¦æ´å¤æç夿 |
| | | if (testValue === "åæ ¼") { |
| | | return "result-passed"; |
| | | } else if (testValue === "ä¸åæ ¼") { |
| | | return "result-rejected"; |
| | | } |
| | | return ""; |
| | | }; |
| | | |
| | | // ä¸è½½æ¥å |
| | | const downloadReport = () => { |
| | | uni.showToast({ |
| | | title: "æ¥åä¸è½½ä¸...", |
| | | icon: "loading", |
| | | }); |
| | | |
| | | // 模æä¸è½½ |
| | | setTimeout(() => { |
| | | uni.showToast({ |
| | | title: "æ¥åä¸è½½æå", |
| | | icon: "success", |
| | | }); |
| | | }, 1500); |
| | | }; |
| | | |
| | | // è·å页é¢ID |
| | | const getPageId = () => { |
| | | const pages = getCurrentPages(); |
| | | const currentPage = pages[pages.length - 1]; |
| | | return currentPage.options.id; |
| | | }; |
| | | |
| | | // è·å详æ
æ°æ® |
| | | const getDetail = () => { |
| | | const id = getPageId(); |
| | | if (!id) { |
| | | showToast("åæ°é误"); |
| | | return; |
| | | } |
| | | |
| | | // 仿¬å°åå¨è·å详æ
æ°æ® |
| | | try { |
| | | const detailDataFromStorage = uni.getStorageSync( |
| | | "processInspectionEditData" |
| | | ); |
| | | if (detailDataFromStorage) { |
| | | detailData.value = detailDataFromStorage; |
| | | // 使ç¨qualityInspectParamInfoè·åæ£éªé¡¹ç® |
| | | qualityInspectParamInfo(id) |
| | | .then(res => { |
| | | if (res.data && res.data.length > 0) { |
| | | inspectionItems.value = res.data; |
| | | } else if ( |
| | | detailDataFromStorage.qualityInspectParams && |
| | | detailDataFromStorage.qualityInspectParams.length > 0 |
| | | ) { |
| | | // 妿æ¥å£æ²¡æè¿åæ°æ®ï¼ä½¿ç¨æ¬å°åå¨ä¸çæ°æ® |
| | | inspectionItems.value = detailDataFromStorage.qualityInspectParams; |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error("è·åæ£éªé¡¹ç®å¤±è´¥:", error); |
| | | // æ¥å£è°ç¨å¤±è´¥æ¶ï¼ä½¿ç¨æ¬å°åå¨ä¸çæ°æ®ææ¨¡ææ°æ® |
| | | if ( |
| | | detailDataFromStorage.qualityInspectParams && |
| | | detailDataFromStorage.qualityInspectParams.length > 0 |
| | | ) { |
| | | inspectionItems.value = detailDataFromStorage.qualityInspectParams; |
| | | } |
| | | }); |
| | | } |
| | | } catch (error) { |
| | | console.error("å 载详æ
æ°æ®å¤±è´¥:", error); |
| | | showToast("å 载详æ
æ°æ®å¤±è´¥ï¼è¯·éè¯"); |
| | | } |
| | | }; |
| | | |
| | | onShow(() => { |
| | | getDetail(); |
| | | }); |
| | | |
| | | onMounted(() => { |
| | | getDetail(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .material-inspection-detail { |
| | | min-height: 100vh; |
| | | background: #f5f5f5; |
| | | padding-bottom: 20px; |
| | | } |
| | | |
| | | .detail-section { |
| | | padding: 15px; |
| | | } |
| | | |
| | | .detail-card { |
| | | background: #fff; |
| | | border-radius: 12px; |
| | | padding: 16px; |
| | | margin-bottom: 12px; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); |
| | | } |
| | | |
| | | .card-header { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-bottom: 12px; |
| | | } |
| | | |
| | | .header-icon { |
| | | width: 40px; |
| | | height: 40px; |
| | | background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| | | border-radius: 8px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | margin-right: 12px; |
| | | } |
| | | |
| | | .header-icon.secondary { |
| | | background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); |
| | | } |
| | | |
| | | .header-icon.tertiary { |
| | | background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); |
| | | } |
| | | |
| | | .header-title { |
| | | flex: 1; |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | |
| | | .status-tag { |
| | | margin-left: 20rpx; |
| | | } |
| | | |
| | | .detail-content { |
| | | padding-top: 8px; |
| | | } |
| | | |
| | | .detail-row { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 10px 0; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | } |
| | | |
| | | .detail-row:last-child { |
| | | border-bottom: none; |
| | | } |
| | | |
| | | .detail-label { |
| | | font-size: 14px; |
| | | color: #666; |
| | | min-width: 100px; |
| | | } |
| | | |
| | | .detail-value { |
| | | font-size: 14px; |
| | | color: #333; |
| | | text-align: right; |
| | | flex: 1; |
| | | } |
| | | |
| | | // æ£éªé¡¹ç® |
| | | .inspection-items { |
| | | padding-top: 8px; |
| | | } |
| | | |
| | | .inspection-item { |
| | | padding: 12px; |
| | | background: #f8f9fa; |
| | | border-radius: 8px; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .inspection-item:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .item-name { |
| | | display: block; |
| | | font-size: 14px; |
| | | font-weight: 500; |
| | | color: #333; |
| | | margin-bottom: 8px; |
| | | padding-bottom: 8px; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | } |
| | | |
| | | .item-details { |
| | | padding-top: 8px; |
| | | } |
| | | |
| | | .item-detail-row { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 6px; |
| | | } |
| | | |
| | | .item-detail-row:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .item-detail-label { |
| | | font-size: 12px; |
| | | color: #666; |
| | | min-width: 60px; |
| | | } |
| | | |
| | | .item-detail-value { |
| | | font-size: 12px; |
| | | color: #333; |
| | | text-align: right; |
| | | flex: 1; |
| | | } |
| | | |
| | | .item-detail-value.result { |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .result-passed { |
| | | color: #67c23a; |
| | | } |
| | | |
| | | .result-rejected { |
| | | color: #f56c6c; |
| | | } |
| | | |
| | | // ç©ºç¶æ |
| | | .no-data { |
| | | padding: 60px 20px; |
| | | text-align: center; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="file-list-page"> |
| | | <!-- 页é¢å¤´é¨ --> |
| | | <PageHeader title="é件管ç" |
| | | @back="goBack" /> |
| | | <!-- éä»¶å表 --> |
| | | <view class="file-list-container"> |
| | | <view v-if="fileList.length > 0" |
| | | class="file-list"> |
| | | <view v-for="(file, index) in fileList" |
| | | :key="file.id || index" |
| | | class="file-item"> |
| | | <!-- æä»¶å¾æ --> |
| | | <!-- <view class="file-icon" |
| | | :class="getFileIconClass(file.fileType)"> |
| | | <up-icon :name="getFileIcon(file.fileType)" |
| | | size="24" |
| | | color="#ffffff" /> |
| | | </view> --> |
| | | <!-- æä»¶ä¿¡æ¯ --> |
| | | <view class="file-info"> |
| | | <text class="file-name">{{ file.name }}</text> |
| | | <!-- <text class="file-meta">{{ formatFileSize(file.fileSize) }} · {{ file.uploadTime || file.createTime }}</text> --> |
| | | </view> |
| | | <!-- æä½æé® --> |
| | | <view class="file-actions"> |
| | | <!-- <u-button size="small" |
| | | type="primary" |
| | | plain |
| | | @click="previewFile(file)">é¢è§</u-button> --> |
| | | <u-button size="small" |
| | | type="info" |
| | | plain |
| | | @click="downloadFile(file)">ä¸è½½å¹¶é¢è§</u-button> |
| | | <u-button size="small" |
| | | type="error" |
| | | plain |
| | | @click="confirmDelete(file, index)">å é¤</u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- ç©ºç¶æ --> |
| | | <view v-else |
| | | class="empty-state"> |
| | | <up-icon name="document" |
| | | size="64" |
| | | color="#c0c4cc" /> |
| | | <text class="empty-text">ææ éä»¶</text> |
| | | </view> |
| | | </view> |
| | | <!-- <a rel="nofollow" |
| | | id="downloadLink" |
| | | href="#" |
| | | style="display:none;">ä¸è½½ææ¬æä»¶</a> --> |
| | | <!-- ä¸ä¼ æé® --> |
| | | <view class="upload-button" |
| | | @click="chooseFile"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff" /> |
| | | <text class="upload-text">ä¸ä¼ éä»¶</text> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import config from "@/config"; |
| | | import { getToken } from "@/utils/auth"; |
| | | // import { saveAs } from "file-saver"; |
| | | import { |
| | | listRuleFiles, |
| | | delRuleFile, |
| | | } from "@/api/managementMeetings/rulesRegulationsManagement"; |
| | | import { |
| | | qualityInspectFileAdd, |
| | | qualityInspectFileListPage, |
| | | qualityInspectFileDel, |
| | | } from "@/api/qualityManagement/materialInspection"; |
| | | import { blobValidate } from "@/utils/ruoyi"; |
| | | |
| | | // éä»¶å表 |
| | | const fileList = ref([]); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | // const request = axios.create({ |
| | | // baseURL: "URL.com", |
| | | // adapter: axiosAdapterUniapp, |
| | | // }); |
| | | // è·åæä»¶å¾æ |
| | | const getFileIcon = fileType => { |
| | | const iconMap = { |
| | | doc: "document", |
| | | docx: "document", |
| | | xls: "grid", |
| | | xlsx: "grid", |
| | | pdf: "document", |
| | | ppt: "copy", |
| | | pptx: "copy", |
| | | txt: "document", |
| | | jpg: "image", |
| | | jpeg: "image", |
| | | png: "image", |
| | | gif: "image", |
| | | zip: "folder", |
| | | rar: "folder", |
| | | }; |
| | | return iconMap[fileType.toLowerCase()] || "document"; |
| | | }; |
| | | |
| | | // è·åæä»¶å¾æ æ ·å¼ç±» |
| | | const getFileIconClass = fileType => { |
| | | const colorMap = { |
| | | doc: "blue", |
| | | docx: "blue", |
| | | xls: "green", |
| | | xlsx: "green", |
| | | pdf: "red", |
| | | ppt: "orange", |
| | | pptx: "orange", |
| | | txt: "gray", |
| | | jpg: "purple", |
| | | jpeg: "purple", |
| | | png: "purple", |
| | | gif: "purple", |
| | | zip: "yellow", |
| | | rar: "yellow", |
| | | }; |
| | | return colorMap[fileType.toLowerCase()] || "gray"; |
| | | }; |
| | | |
| | | // æ ¼å¼åæä»¶å¤§å° |
| | | const formatFileSize = bytes => { |
| | | if (bytes === 0) return "0 B"; |
| | | const k = 1024; |
| | | const sizes = ["B", "KB", "MB", "GB"]; |
| | | const i = Math.floor(Math.log(bytes) / Math.log(k)); |
| | | return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i]; |
| | | }; |
| | | |
| | | // éæ©æä»¶ |
| | | const chooseFile = () => { |
| | | uni.chooseImage({ |
| | | count: 9, |
| | | sizeType: ["original", "compressed"], |
| | | sourceType: ["album", "camera"], |
| | | success: res => { |
| | | console.log(res, "éæ©å¾çæå"); |
| | | uploadFiles(res.tempFiles); |
| | | }, |
| | | fail: err => { |
| | | console.error("éæ©å¾ç失败:", err); |
| | | showToast("éæ©æä»¶å¤±è´¥"); |
| | | }, |
| | | }); |
| | | // uni.chooseFile({ |
| | | // count: 9, |
| | | // extension: [ |
| | | // ".doc", |
| | | // ".docx", |
| | | // ".xls", |
| | | // ".xlsx", |
| | | // ".pdf", |
| | | // ".ppt", |
| | | // ".pptx", |
| | | // ".txt", |
| | | // ".jpg", |
| | | // ".jpeg", |
| | | // ".png", |
| | | // ".gif", |
| | | // ".zip", |
| | | // ".rar", |
| | | // ], |
| | | // success: res => { |
| | | // console.log(res, "éæ©æä»¶æå"); |
| | | // uploadFiles(res.tempFiles); |
| | | // }, |
| | | // fail: err => { |
| | | // showToast("éæ©æä»¶å¤±è´¥"); |
| | | // }, |
| | | // }); |
| | | }; |
| | | |
| | | // ä¸ä¼ æä»¶ |
| | | const uploadFiles = tempFiles => { |
| | | console.log(tempFiles, "ä¸ä¼ æä»¶1"); |
| | | tempFiles.forEach((tempFile, index) => { |
| | | // æ¾ç¤ºä¸ä¼ ä¸æç¤º |
| | | uni.showLoading({ |
| | | title: "ä¸ä¼ ä¸...", |
| | | mask: true, |
| | | }); |
| | | console.log(tempFile, "ä¸ä¼ æä»¶2"); |
| | | // 1. ç´æ¥ä½¿ç¨ uni.uploadFile ä¸ä¼ æä»¶ |
| | | uni.uploadFile({ |
| | | url: config.baseUrl + "/file/upload", |
| | | filePath: tempFile.path, |
| | | name: "file", |
| | | header: { |
| | | Authorization: "Bearer " + getToken(), |
| | | }, |
| | | success: uploadRes => { |
| | | uni.hideLoading(); |
| | | console.log(uploadRes, "ä¸ä¼ æä»¶3"); |
| | | |
| | | try { |
| | | const res = JSON.parse(uploadRes.data); |
| | | console.log(res, "ä¸ä¼ æä»¶4"); |
| | | if (res.code === 200) { |
| | | // 2. æåæä»¶ä¿¡æ¯ |
| | | const fileName = tempFile.name |
| | | ? tempFile.name |
| | | : tempFile.path.split("/").pop(); |
| | | // const fileType = fileName.split(".").pop(); |
| | | // 3. æé ä¿åæä»¶ä¿¡æ¯çåæ° |
| | | const saveData = { |
| | | name: fileName, |
| | | inspectId: rulesRegulationsManagementId.value, |
| | | url: res.data.tempPath || "", |
| | | }; |
| | | console.log(saveData, "ä¿åæä»¶ä¿¡æ¯åæ°"); |
| | | // 4. è°ç¨ addRuleFile æ¥å£ä¿åæä»¶ä¿¡æ¯ |
| | | qualityInspectFileAdd(saveData) |
| | | .then(addRes => { |
| | | if (addRes.code === 200) { |
| | | // 5. æ·»å å°æä»¶å表 |
| | | const newFile = { |
| | | ...addRes.data, |
| | | uploadTime: new Date().toLocaleString(), |
| | | }; |
| | | // fileList.value.push(newFile); |
| | | getFileList(); |
| | | showToast("ä¸ä¼ æå"); |
| | | } else { |
| | | showToast("ä¿åæä»¶ä¿¡æ¯å¤±è´¥"); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | console.error("ä¿åæä»¶ä¿¡æ¯å¤±è´¥:", err); |
| | | showToast("ä¿åæä»¶ä¿¡æ¯å¤±è´¥"); |
| | | }); |
| | | } else { |
| | | showToast("æä»¶ä¸ä¼ 失败"); |
| | | } |
| | | } catch (e) { |
| | | console.error("è§£æä¸ä¼ ç»æå¤±è´¥:", e); |
| | | showToast("ä¸ä¼ 失败"); |
| | | } |
| | | }, |
| | | fail: err => { |
| | | uni.hideLoading(); |
| | | console.error("ä¸ä¼ 失败:", err); |
| | | showToast("ä¸ä¼ 失败"); |
| | | }, |
| | | }); |
| | | }); |
| | | }; |
| | | // ä¸è½½æä»¶ |
| | | const downloadFile = file => { |
| | | var url = |
| | | config.baseUrl + |
| | | "/common/download?fileName=" + |
| | | encodeURIComponent(file.url) + |
| | | "&delete=true"; |
| | | console.log(url, "url"); |
| | | |
| | | uni |
| | | .downloadFile({ |
| | | url: url, |
| | | responseType: "blob", |
| | | header: { Authorization: "Bearer " + getToken() }, |
| | | }) |
| | | .then(res => { |
| | | let osType = uni.getStorageSync("deviceInfo").osName; |
| | | let filePath = res.tempFilePath; |
| | | if (osType === "ios") { |
| | | uni.openDocument({ |
| | | filePath: filePath, |
| | | showMenu: true, |
| | | success: res => { |
| | | resolve(res); |
| | | }, |
| | | fail: err => { |
| | | console.log("uni.openDocument--fail"); |
| | | reject(err); |
| | | }, |
| | | }); |
| | | } else { |
| | | uni.saveFile({ |
| | | tempFilePath: filePath, |
| | | success: fileRes => { |
| | | uni.showToast({ |
| | | icon: "none", |
| | | mask: true, |
| | | title: |
| | | "æä»¶å·²ä¿åï¼Android/data/uni.UNI720216F/apps/__UNI__720216F/" + |
| | | fileRes.savedFilePath, //ä¿åè·¯å¾ |
| | | duration: 3000, |
| | | }); |
| | | setTimeout(() => { |
| | | //æå¼ææ¡£æ¥ç |
| | | uni.openDocument({ |
| | | filePath: fileRes.savedFilePath, |
| | | success: function (res) { |
| | | resolve(fileRes); |
| | | }, |
| | | }); |
| | | }, 3000); |
| | | }, |
| | | fail: err => { |
| | | console.log("uni.save--fail"); |
| | | reject(err); |
| | | }, |
| | | }); |
| | | } |
| | | // const isBlob = blobValidate(res.data); |
| | | // if (isBlob) { |
| | | // const blob = new Blob([res.data], { type: "text/plain" }); |
| | | // const url = URL.createObjectURL(blob); |
| | | // const downloadLink = document.getElementById("downloadLink"); |
| | | // downloadLink.href = url; |
| | | // downloadLink.download = file.name; |
| | | // downloadLink.click(); |
| | | // showToast("ä¸è½½æå"); |
| | | // } else { |
| | | // showToast("ä¸è½½å¤±è´¥"); |
| | | // } |
| | | }) |
| | | .catch(err => { |
| | | console.error("ä¸è½½å¤±è´¥:", err); |
| | | showToast("ä¸è½½å¤±è´¥"); |
| | | }); |
| | | }; |
| | | |
| | | // 确认å é¤ |
| | | const confirmDelete = (file, index) => { |
| | | uni.showModal({ |
| | | title: "å é¤ç¡®è®¤", |
| | | content: `ç¡®å®è¦å é¤éä»¶ "${file.name}" åï¼`, |
| | | success: res => { |
| | | if (res.confirm) { |
| | | deleteFile(file.id, index); |
| | | } |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // å 餿件 |
| | | const deleteFile = (fileId, index) => { |
| | | uni.showLoading({ |
| | | title: "å é¤ä¸...", |
| | | mask: true, |
| | | }); |
| | | |
| | | qualityInspectFileDel([fileId]) |
| | | .then(res => { |
| | | uni.hideLoading(); |
| | | if (res.code === 200) { |
| | | // fileList.value.splice(index, 1); |
| | | getFileList(); |
| | | showToast("å 餿å"); |
| | | } else { |
| | | showToast("å é¤å¤±è´¥"); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | uni.hideLoading(); |
| | | showToast("å é¤å¤±è´¥"); |
| | | }); |
| | | }; |
| | | |
| | | // æ¾ç¤ºæç¤º |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | const rulesRegulationsManagementId = ref(""); |
| | | // 页é¢å è½½æ¶ |
| | | onMounted(() => { |
| | | rulesRegulationsManagementId.value = uni.getStorageSync( |
| | | "qualityInspectFileId" |
| | | ); |
| | | // ä» API è·åéä»¶å表 |
| | | getFileList(); |
| | | // 仿¬å°åå¨è·å rulesRegulationsManagementId |
| | | }); |
| | | |
| | | // è·åéä»¶å表 |
| | | const getFileList = () => { |
| | | uni.showLoading({ |
| | | title: "å è½½ä¸...", |
| | | mask: true, |
| | | }); |
| | | |
| | | qualityInspectFileListPage({ |
| | | inspectId: rulesRegulationsManagementId.value, |
| | | current: -1, |
| | | size: -1, |
| | | }) |
| | | .then(res => { |
| | | uni.hideLoading(); |
| | | if (res.code === 200) { |
| | | fileList.value = res.data.records || []; |
| | | } else { |
| | | showToast("è·åéä»¶å表失败"); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | uni.hideLoading(); |
| | | showToast("è·åéä»¶å表失败"); |
| | | }); |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "../../../styles/sales-common.scss"; |
| | | |
| | | .file-list-page { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 100rpx; |
| | | } |
| | | |
| | | .file-list-container { |
| | | padding: 20rpx; |
| | | } |
| | | |
| | | .file-list { |
| | | background: #ffffff; |
| | | border-radius: 8rpx; |
| | | overflow: hidden; |
| | | box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05); |
| | | } |
| | | |
| | | .file-item { |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 20rpx; |
| | | border-bottom: 1rpx solid #f0f0f0; |
| | | |
| | | &:last-child { |
| | | border-bottom: none; |
| | | } |
| | | } |
| | | |
| | | .file-icon { |
| | | width: 56rpx; |
| | | height: 56rpx; |
| | | border-radius: 8rpx; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | margin-right: 20rpx; |
| | | |
| | | &.blue { |
| | | background: #409eff; |
| | | } |
| | | |
| | | &.green { |
| | | background: #67c23a; |
| | | } |
| | | |
| | | &.red { |
| | | background: #f56c6c; |
| | | } |
| | | |
| | | &.orange { |
| | | background: #e6a23c; |
| | | } |
| | | |
| | | &.gray { |
| | | background: #909399; |
| | | } |
| | | |
| | | &.purple { |
| | | background: #909399; |
| | | } |
| | | |
| | | &.yellow { |
| | | background: #e6a23c; |
| | | } |
| | | } |
| | | |
| | | .file-info { |
| | | flex: 1; |
| | | min-width: 0; |
| | | } |
| | | |
| | | .file-name { |
| | | display: block; |
| | | font-size: 16px; |
| | | color: #303133; |
| | | margin-bottom: 8rpx; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | .file-meta { |
| | | display: block; |
| | | font-size: 12px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .file-actions { |
| | | display: flex; |
| | | gap: 12rpx; |
| | | } |
| | | |
| | | .empty-state { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | padding: 100rpx 0; |
| | | background: #ffffff; |
| | | border-radius: 8rpx; |
| | | box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05); |
| | | } |
| | | |
| | | .empty-text { |
| | | font-size: 14px; |
| | | color: #909399; |
| | | margin-top: 20rpx; |
| | | } |
| | | |
| | | .upload-button { |
| | | position: fixed; |
| | | bottom: 40rpx; |
| | | right: 40rpx; |
| | | width: 130rpx; |
| | | height: 130rpx; |
| | | border-radius: 50%; |
| | | background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | align-items: center; |
| | | box-shadow: 0 4rpx 16rpx rgba(102, 126, 234, 0.4); |
| | | z-index: 1000; |
| | | } |
| | | |
| | | .upload-text { |
| | | font-size: 10px; |
| | | color: #ffffff; |
| | | margin-top: 4rpx; |
| | | } |
| | | |
| | | .upload-progress { |
| | | padding: 40rpx 0; |
| | | } |
| | | |
| | | .upload-progress-text { |
| | | display: block; |
| | | text-align: center; |
| | | margin-top: 20rpx; |
| | | font-size: 14px; |
| | | color: #606266; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="material-inspection-page"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="è¿ç¨æ£éª" |
| | | @back="goBack" /> |
| | | <!-- æç´¢åºå --> |
| | | <view class="search-section"> |
| | | <view class="search-bar"> |
| | | <view class="search-input"> |
| | | <up-input class="search-text" |
| | | placeholder="请è¾å
¥å·¥åºæç´¢" |
| | | v-model="searchForm.process" |
| | | @change="getList" |
| | | clearable /> |
| | | </view> |
| | | <!-- <view class="filter-button" |
| | | @click="showDatePicker"> |
| | | <up-icon name="calendar" |
| | | size="24" |
| | | color="#999"></up-icon> |
| | | </view> --> |
| | | <view class="filter-button" |
| | | @click="getList"> |
| | | <up-icon name="search" |
| | | size="24" |
| | | color="#999"></up-icon> |
| | | </view> |
| | | </view> |
| | | <!-- æ¥æéæ© --> |
| | | <!-- <view class="date-range" |
| | | v-if="searchForm.entryDate"> |
| | | <text class="date-text">{{ searchForm.entryDate[0] }} è³ {{ searchForm.entryDate[1] }}</text> |
| | | <up-icon name="close" |
| | | size="16" |
| | | color="#999" |
| | | @click="clearDateRange"></up-icon> |
| | | </view> --> |
| | | </view> |
| | | <!-- ç»è®¡ä¿¡æ¯å¡ç --> |
| | | <!-- <view class="stats-cards"> |
| | | <view class="stat-card"> |
| | | <text class="stat-number">{{ totalCount }}</text> |
| | | <text class="stat-label">æ»æ£éª</text> |
| | | </view> |
| | | <view class="stat-card"> |
| | | <text class="stat-number">{{ submittedCount }}</text> |
| | | <text class="stat-label">å·²æäº¤</text> |
| | | </view> |
| | | <view class="stat-card"> |
| | | <text class="stat-number">{{ pendingCount }}</text> |
| | | <text class="stat-label">å¾
æäº¤</text> |
| | | </view> |
| | | <view class="stat-card"> |
| | | <text class="stat-number">{{ qualifiedCount }}</text> |
| | | <text class="stat-label">å·²åæ ¼</text> |
| | | </view> |
| | | </view> --> |
| | | <!-- æ£éªå表 --> |
| | | <view class="inspection-list" |
| | | v-if="inspectionList.length > 0"> |
| | | <view v-for="(item, index) in inspectionList" |
| | | :key="index"> |
| | | <view class="inspection-item" |
| | | @click="viewDetail(item)"> |
| | | <view class="item-header"> |
| | | <view class="item-left"> |
| | | <!-- <view class="material-icon" |
| | | :class="getStateClass(item.inspectState)"> |
| | | <up-icon :name="getStateIcon(item.inspectState)" |
| | | size="16" |
| | | color="#ffffff"></up-icon> |
| | | </view> --> |
| | | <view class="material-info"> |
| | | <text class="material-name">{{ item.productName }}</text> |
| | | <text class="material-code">{{ item.model }}</text> |
| | | </view> |
| | | </view> |
| | | <view class="status-tags"> |
| | | <u-tag :type="getTagType(item.checkResult)" |
| | | size="mini" |
| | | class="status-tag"> |
| | | {{ item.checkResult }} |
| | | </u-tag> |
| | | <u-tag :type="getStateTagType(item.inspectState)" |
| | | size="mini" |
| | | class="status-tag"> |
| | | {{ item.inspectState ? 'å·²æäº¤' : 'æªæäº¤' }} |
| | | </u-tag> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="item-details"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">æ£æµæ¥æ</text> |
| | | <text class="detail-value">{{ formatDateTime(item.checkTime) || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç产工åå·</text> |
| | | <text class="detail-value">{{ item.workOrderNo || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å·¥åº</text> |
| | | <text class="detail-value">{{ item.process || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">æ£éªå</text> |
| | | <text class="detail-value">{{ item.checkName || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">æ°é</text> |
| | | <text class="detail-value">{{ item.quantity || 0 }} {{ item.unit || '' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">æ£æµåä½</text> |
| | | <text class="detail-value">{{ item.checkCompany || '-' }}</text> |
| | | </view> |
| | | </view> |
| | | <!-- æä½æé® --> |
| | | <view class="action-buttons"> |
| | | <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.inspectState" |
| | | @click.stop="startInspection(item)"> |
| | | ç¼è¾ |
| | | </u-button> |
| | | <u-button type="info" |
| | | size="small" |
| | | class="action-btn" |
| | | @click.stop="viewDetail(item)"> |
| | | 详æ
|
| | | </u-button> |
| | | <u-button type="success" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.inspectState" |
| | | @click.stop="submitInspection(item)"> |
| | | æäº¤ |
| | | </u-button> |
| | | </view> |
| | | <view class="action-buttons"> |
| | | <u-button type="info" |
| | | size="small" |
| | | class="action-btn" |
| | | @click.stop="viewFileList(item)"> |
| | | éä»¶ |
| | | </u-button> |
| | | <u-button type="warning" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.inspectState || item.checkName !== ''" |
| | | @click.stop="assignInspector(item)"> |
| | | åé
æ£éªå |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else |
| | | class="no-data"> |
| | | <up-empty mode="data" |
| | | text="ææ æ£éªä»»å¡"></up-empty> |
| | | </view> |
| | | <!-- å页ç»ä»¶ --> |
| | | <!-- æµ®å¨æ°å¢æé® --> |
| | | <view class="fab-button" |
| | | @click="addInspection"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <up-popup v-model:show="showDate" |
| | | mode="date" |
| | | :start-year="2020" |
| | | :end-year="2030" |
| | | :range="true" |
| | | @confirm="confirmDate" /> |
| | | <!-- åé
æ£éªåå¼¹çª --> |
| | | <up-popup v-model:show="showAssignDialog" |
| | | mode="center" |
| | | round |
| | | style="width: 80%"> |
| | | <view class="assign-dialog"> |
| | | <view class="dialog-header"> |
| | | <text class="dialog-title">åé
æ£éªå</text> |
| | | <up-icon name="close" |
| | | size="20" |
| | | color="#999" |
| | | @click="showAssignDialog = false"></up-icon> |
| | | </view> |
| | | <view class="dialog-content"> |
| | | <up-form-item label="æ£éªå" |
| | | prop="checkName" |
| | | :label-width="60" |
| | | required> |
| | | <up-input v-model="assignForm.checkName" |
| | | placeholder="è¯·éæ©æ£éªå" |
| | | readonly /> |
| | | <template #right> |
| | | <up-icon @click="showInspectorSheet = true" |
| | | name="arrow-right" /> |
| | | </template> |
| | | </up-form-item> |
| | | </view> |
| | | <view class="dialog-footer"> |
| | | <u-button type="default" |
| | | class="footer-btn" |
| | | @click="showAssignDialog = false"> |
| | | åæ¶ |
| | | </u-button> |
| | | <u-button type="primary" |
| | | class="footer-btn" |
| | | @click="submitAssign"> |
| | | ç¡®å® |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </up-popup> |
| | | <!-- æ£éªåéæ© --> |
| | | <up-action-sheet :show="showInspectorSheet" |
| | | :actions="userSheetOptions" |
| | | @select="selectInspector" |
| | | title="éæ©æ£éªå" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, computed, onMounted } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import dayjs from "dayjs"; |
| | | import { |
| | | submitQualityInspect, |
| | | qualityInspectUpdate, |
| | | qualityInspectListPage, |
| | | } from "@/api/qualityManagement/materialInspection.js"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | |
| | | // æ¾ç¤ºæç¤ºä¿¡æ¯ |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | // æç´¢è¡¨å |
| | | const searchForm = ref({ |
| | | process: "", |
| | | entryDate: undefined, |
| | | entryDateStart: undefined, |
| | | entryDateEnd: undefined, |
| | | }); |
| | | |
| | | // æ¥æéæ©å¨ |
| | | const showDate = ref(false); |
| | | |
| | | // åé
æ£éªåå¼¹çª |
| | | const showAssignDialog = ref(false); |
| | | const showInspectorSheet = ref(false); |
| | | const assignForm = ref({ |
| | | checkName: "", |
| | | }); |
| | | const currentAssignRow = ref(null); |
| | | |
| | | // æ£éªåè¡¨æ°æ® |
| | | const inspectionList = ref([]); |
| | | |
| | | // åé¡µæ°æ® |
| | | const page = ref({ |
| | | current: -1, |
| | | size: -1, |
| | | total: 0, |
| | | }); |
| | | |
| | | // å è½½ç¶æ |
| | | const tableLoading = ref(false); |
| | | |
| | | // ç»è®¡æ°æ® |
| | | const totalCount = ref(0); |
| | | const submittedCount = ref(0); |
| | | const pendingCount = ref(0); |
| | | const qualifiedCount = ref(0); |
| | | |
| | | // æ£éªåå表 |
| | | const userList = ref([]); |
| | | |
| | | // ActionSheeté项 |
| | | const userSheetOptions = computed(() => { |
| | | return userList.value.map(item => ({ |
| | | name: item.nickName, |
| | | value: item.nickName, |
| | | })); |
| | | }); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // æ ¼å¼åæ¥ææ¶é´ |
| | | const formatDateTime = dateStr => { |
| | | if (!dateStr) return ""; |
| | | return dayjs(dateStr).format("YYYY-MM-DD"); |
| | | }; |
| | | |
| | | // è·åç¶ææ ·å¼ |
| | | const getStateClass = inspectState => { |
| | | return inspectState ? "state-submitted" : "state-pending"; |
| | | }; |
| | | |
| | | // è·åç¶æå¾æ |
| | | const getStateIcon = inspectState => { |
| | | return inspectState ? "checkmark-circle" : "time"; |
| | | }; |
| | | |
| | | // è·åæ ç¾ç±»å |
| | | const getTagType = checkResult => { |
| | | if (checkResult === "åæ ¼") return "success"; |
| | | if (checkResult === "ä¸åæ ¼") return "error"; |
| | | return "default"; |
| | | }; |
| | | |
| | | // è·åç¶ææ ç¾ç±»å |
| | | const getStateTagType = inspectState => { |
| | | return inspectState ? "success" : "warning"; |
| | | }; |
| | | |
| | | // æ¾ç¤ºæ¥æéæ©å¨ |
| | | const showDatePicker = () => { |
| | | showDate.value = true; |
| | | }; |
| | | |
| | | // ç¡®è®¤æ¥æéæ© |
| | | const confirmDate = e => { |
| | | searchForm.value.entryDate = e.value; |
| | | searchForm.value.entryDateStart = dayjs(e.value[0]).format("YYYY-MM-DD"); |
| | | searchForm.value.entryDateEnd = dayjs(e.value[1]).format("YYYY-MM-DD"); |
| | | getList(); |
| | | }; |
| | | const viewFileList = item => { |
| | | uni.setStorageSync("qualityInspectFileId", item.id); |
| | | uni.navigateTo({ |
| | | url: "/pages/qualityManagement/processInspection/fileList", |
| | | }); |
| | | }; |
| | | |
| | | // æ¸
餿¥æèå´ |
| | | const clearDateRange = () => { |
| | | searchForm.value.entryDate = undefined; |
| | | searchForm.value.entryDateStart = undefined; |
| | | searchForm.value.entryDateEnd = undefined; |
| | | getList(); |
| | | }; |
| | | |
| | | // è·åç¨æ·å表 |
| | | const getUserList = async () => { |
| | | try { |
| | | const userRes = await userListNoPage(); |
| | | userList.value = userRes.data || []; |
| | | } catch (e) { |
| | | console.error("å è½½æ£éªåå表失败", e); |
| | | userList.value = []; |
| | | } |
| | | }; |
| | | |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | const params = { ...searchForm.value, ...page.value }; |
| | | params.entryDate = undefined; |
| | | qualityInspectListPage({ ...params, inspectType: 1 }) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | inspectionList.value = res.data.records || []; |
| | | page.value.total = res.data.total || 0; |
| | | totalCount.value = res.data.total || 0; |
| | | submittedCount.value = inspectionList.value.filter( |
| | | item => item.inspectState |
| | | ).length; |
| | | pendingCount.value = inspectionList.value.filter( |
| | | item => !item.inspectState |
| | | ).length; |
| | | qualifiedCount.value = inspectionList.value.filter( |
| | | item => item.checkResult === "åæ ¼" |
| | | ).length; |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | console.error("è·åå表失败:", err); |
| | | showToast("è·åå表失败ï¼è¯·éè¯"); |
| | | }); |
| | | }; |
| | | |
| | | // ç¼è¾æ£éª |
| | | const startInspection = item => { |
| | | if (!item) { |
| | | showToast("åæ°é误"); |
| | | return; |
| | | } |
| | | // åå¨å®æ´çæ£éªæ°æ® |
| | | uni.setStorageSync("processInspectionEditData", item); |
| | | // 跳转å°ç¼è¾é¡µé¢ |
| | | uni.navigateTo({ |
| | | url: `/pages/qualityManagement/processInspection/add?id=${item.id}&isEdit=true`, |
| | | }); |
| | | }; |
| | | |
| | | // æ¥ç详æ
|
| | | const viewDetail = item => { |
| | | if (!item) { |
| | | showToast("åæ°é误"); |
| | | return; |
| | | } |
| | | uni.setStorageSync("processInspectionEditData", item); |
| | | // 跳转å°è¯¦æ
é¡µé¢ |
| | | uni.navigateTo({ |
| | | url: `/pages/qualityManagement/processInspection/detail?id=${item.id}`, |
| | | }); |
| | | }; |
| | | |
| | | // æ°å¢æ£éª |
| | | const addInspection = () => { |
| | | uni.navigateTo({ |
| | | url: "/pages/qualityManagement/processInspection/add", |
| | | }); |
| | | }; |
| | | |
| | | // æäº¤æ£éª |
| | | const submitInspection = async item => { |
| | | if (!item) { |
| | | showToast("åæ°é误"); |
| | | return; |
| | | } |
| | | try { |
| | | const res = await submitQualityInspect({ id: item.id }); |
| | | if (res.code === 200) { |
| | | showToast("æäº¤æå"); |
| | | setTimeout(() => { |
| | | getList(); |
| | | }, 1000); |
| | | } else { |
| | | showToast("æäº¤å¤±è´¥ï¼" + (res.msg || "æªç¥é误")); |
| | | } |
| | | } catch (error) { |
| | | console.error("æäº¤å¤±è´¥:", error); |
| | | showToast("æäº¤å¤±è´¥ï¼è¯·éè¯"); |
| | | } |
| | | }; |
| | | |
| | | // åé
æ£éªå |
| | | const assignInspector = item => { |
| | | if (!item) { |
| | | showToast("åæ°é误"); |
| | | return; |
| | | } |
| | | currentAssignRow.value = item; |
| | | getUserList(); |
| | | showAssignDialog.value = true; |
| | | }; |
| | | |
| | | // éæ©æ£éªå |
| | | const selectInspector = e => { |
| | | assignForm.value.checkName = e.value; |
| | | showInspectorSheet.value = false; |
| | | }; |
| | | |
| | | // æäº¤åé
|
| | | const submitAssign = async () => { |
| | | if (!currentAssignRow.value || !assignForm.value.checkName) { |
| | | showToast("è¯·éæ©æ£éªå"); |
| | | return; |
| | | } |
| | | try { |
| | | const data = { |
| | | ...assignForm.value, |
| | | id: currentAssignRow.value.id, |
| | | }; |
| | | const res = await qualityInspectUpdate(data); |
| | | if (res.code === 200) { |
| | | showToast("åé
æå"); |
| | | showAssignDialog.value = false; |
| | | setTimeout(() => { |
| | | getList(); |
| | | }, 1000); |
| | | } else { |
| | | showToast("åé
失败ï¼" + (res.msg || "æªç¥é误")); |
| | | } |
| | | } catch (error) { |
| | | console.error("åé
失败:", error); |
| | | showToast("åé
失败ï¼è¯·éè¯"); |
| | | } |
| | | }; |
| | | |
| | | // å¤çå页 |
| | | const handlePagination = obj => { |
| | | page.value.current = obj.current; |
| | | page.value.size = obj.size; |
| | | getList(); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | getUserList(); |
| | | }); |
| | | |
| | | onShow(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "../../../styles/sales-common.scss"; |
| | | |
| | | .material-inspection-page { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 80px; |
| | | } |
| | | |
| | | // æç´¢åºå |
| | | .search-section { |
| | | padding: 10px 15px; |
| | | background: #fff; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | } |
| | | |
| | | .search-bar { |
| | | display: flex; |
| | | align-items: center; |
| | | background: #f8f9fa; |
| | | border-radius: 20px; |
| | | padding: 0 15px; |
| | | height: 40px; |
| | | } |
| | | |
| | | .search-input { |
| | | flex: 1; |
| | | } |
| | | |
| | | .search-text { |
| | | background: transparent; |
| | | border: none; |
| | | } |
| | | |
| | | .filter-button { |
| | | margin-left: 10px; |
| | | padding: 5px; |
| | | } |
| | | |
| | | // ç»è®¡å¡ç |
| | | .stats-cards { |
| | | display: flex; |
| | | padding: 15px; |
| | | gap: 10px; |
| | | background: #fff; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .stat-card { |
| | | flex: 1; |
| | | background: #2979ff; |
| | | border-radius: 12px; |
| | | padding: 15px; |
| | | text-align: center; |
| | | color: #fff; |
| | | box-shadow: 0 2px 8px rgba(41, 121, 255, 0.2); |
| | | } |
| | | |
| | | .stat-number { |
| | | display: block; |
| | | font-size: 20px; |
| | | font-weight: 600; |
| | | margin-bottom: 5px; |
| | | } |
| | | |
| | | .stat-label { |
| | | font-size: 12px; |
| | | opacity: 0.9; |
| | | } |
| | | |
| | | // æ£éªå表 |
| | | .inspection-list { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .inspection-item { |
| | | background: #ffffff; |
| | | border-radius: 12px; |
| | | margin-bottom: 16px; |
| | | overflow: hidden; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); |
| | | padding: 0 16px; |
| | | |
| | | &:active { |
| | | transform: scale(0.98); |
| | | box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1); |
| | | } |
| | | } |
| | | |
| | | .item-header { |
| | | padding: 16px 0; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .item-left { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .material-icon { |
| | | width: 24px; |
| | | height: 24px; |
| | | background: #2979ff; |
| | | border-radius: 4px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .state-pending { |
| | | background: #ff9900; |
| | | } |
| | | |
| | | .state-submitted { |
| | | background: #52c41a; |
| | | } |
| | | |
| | | .material-info { |
| | | flex: 1; |
| | | } |
| | | |
| | | .material-name { |
| | | font-size: 14px; |
| | | color: #333; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .material-code { |
| | | font-size: 12px; |
| | | color: #999; |
| | | margin-left: 8px; |
| | | } |
| | | |
| | | .status-tags { |
| | | display: flex; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .status-tag { |
| | | margin: 0; |
| | | } |
| | | |
| | | .date-range { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | margin-top: 10px; |
| | | padding: 8px 12px; |
| | | background: #f8f9fa; |
| | | border-radius: 8px; |
| | | } |
| | | |
| | | .date-text { |
| | | font-size: 12px; |
| | | color: #666; |
| | | } |
| | | |
| | | // 详æ
è¡ |
| | | .item-details { |
| | | padding: 16px 0; |
| | | } |
| | | |
| | | .detail-row { |
| | | display: flex; |
| | | align-items: flex-end; |
| | | justify-content: space-between; |
| | | margin-bottom: 8px; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | } |
| | | |
| | | .detail-label { |
| | | font-size: 12px; |
| | | color: #777777; |
| | | min-width: 60px; |
| | | } |
| | | |
| | | .detail-value { |
| | | font-size: 12px; |
| | | color: #000000; |
| | | text-align: right; |
| | | flex: 1; |
| | | margin-left: 16px; |
| | | } |
| | | |
| | | // æä½æé® |
| | | .action-buttons { |
| | | display: flex; |
| | | gap: 12px; |
| | | padding: 0 0 16px 0; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .action-btn { |
| | | flex: 1; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | gap: 8px; |
| | | } |
| | | |
| | | // ç©ºç¶æ |
| | | .no-data { |
| | | padding: 60px 20px; |
| | | text-align: center; |
| | | } |
| | | |
| | | // æµ®å¨æé® |
| | | .fab-button { |
| | | position: fixed; |
| | | bottom: 20px; |
| | | right: 20px; |
| | | width: 56px; |
| | | height: 56px; |
| | | background: #2979ff; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | box-shadow: 0 4px 16px rgba(41, 121, 255, 0.3); |
| | | z-index: 1000; |
| | | } |
| | | |
| | | // åé
æ£éªåå¼¹çª |
| | | .assign-dialog { |
| | | padding: 24px; |
| | | background: #ffffff; |
| | | border-radius: 12px; |
| | | } |
| | | |
| | | .dialog-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 24px; |
| | | padding-bottom: 16px; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | } |
| | | |
| | | .dialog-title { |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | } |
| | | |
| | | .dialog-content { |
| | | margin-bottom: 24px; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | display: flex; |
| | | gap: 16px; |
| | | padding-top: 16px; |
| | | border-top: 1px solid #f0f0f0; |
| | | } |
| | | |
| | | .footer-btn { |
| | | flex: 1; |
| | | height: 44px; |
| | | font-size: 16px; |
| | | } |
| | | |
| | | // è¾å
¥æ¡æ ·å¼ |
| | | :deep(.up-input__inner) { |
| | | border-radius: 8px; |
| | | height: 44px; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | // 表åé¡¹æ ·å¼ |
| | | :deep(.up-form-item) { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | :deep(.up-form-item__label) { |
| | | font-size: 14px; |
| | | color: #606266; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | // æé®æ ·å¼ |
| | | :deep(.up-button--primary) { |
| | | border-radius: 8px; |
| | | } |
| | | |
| | | :deep(.up-button--default) { |
| | | border-radius: 8px; |
| | | } |
| | | |
| | | // å页ç»ä»¶ |
| | | .pagination { |
| | | padding: 20px; |
| | | background: #fff; |
| | | margin-top: 10px; |
| | | display: flex; |
| | | justify-content: center; |
| | | } |
| | | </style> |