const api = require('../../utils/api') const locationGuard = require('../../utils/locationGuard') const decodeRepeated = value => { let text = String(value || '').trim() for (let index = 0; index < 3; index += 1) { try { const decoded = decodeURIComponent(text) if (decoded === text) { break } text = decoded } catch (error) { break } } return text } const itemKey = item => `${item.attendancePointName || ''}||${item.moldName || item.productName || item.name}||${item.processName || ''}` Page({ data: { items: [], attendancePointName: '', equipmentOptions: [], equipmentLabels: [], filling: false, submitting: false, deviceModalVisible: false, activeDeviceIndex: -1, deviceSelectOptions: [], pendingDeviceNos: [], currentLocation: null, }, onLoad(options) { const user = api.getCurrentUser() if (!user || user.role !== 'worker') { wx.showToast({ title: '请先用冲压工人登录', icon: 'none' }) setTimeout(() => { wx.reLaunch({ url: '/pages/index/index' }) }, 800) return } const attendancePointName = decodeRepeated(options.attendancePointName || '') this.setData({ attendancePointName }) this.loadCleaningEquipment(attendancePointName) this.addResolvedItem({ attendancePointName, moldName: decodeRepeated(options.moldName || ''), processName: decodeRepeated(options.processName || ''), stampingMethod: decodeRepeated(options.stampingMethod || ''), isCleaning: options.isCleaning === '1', displayName: decodeRepeated(options.displayName || ''), }) }, addResolvedItem(raw) { const item = { attendancePointName: String(raw.attendancePointName || this.data.attendancePointName || '').trim(), moldName: String(raw.moldName || raw.name || '').trim(), processName: String(raw.processName || '').trim(), stampingMethod: String(raw.stampingMethod || '').trim(), isCleaning: !!raw.isCleaning || String(raw.stampingMethod || '').trim() === '清洗', displayName: raw.displayName || api.moldDisplayName(raw.moldName || raw.name, raw.processName, raw.stampingMethod), deviceNo: '', deviceNos: [], quantity: '', } if (!item.moldName) { wx.showToast({ title: '未识别清洗产品', icon: 'none' }) return } if (!item.processName) { wx.showToast({ title: '未识别工序', icon: 'none' }) return } if (!item.isCleaning) { wx.showToast({ title: '只能添加冲压方式为清洗的二维码', icon: 'none' }) return } if (this.data.attendancePointName && item.attendancePointName !== this.data.attendancePointName) { wx.showToast({ title: '只能添加同一考勤点的清洗产品', icon: 'none' }) return } const exists = this.data.items.some(existing => itemKey(existing) === itemKey(item)) if (exists) { wx.showToast({ title: '该清洗产品已添加', icon: 'none' }) return } this.setData({ items: this.data.items.concat(item), }) }, async loadCleaningEquipment(attendancePointName = this.data.attendancePointName) { try { const result = await api.listEquipment({ attendancePointName, deviceType: '清洗设备', page: 1, pageSize: 100, }) const equipmentOptions = result.rows || [] this.setData({ equipmentOptions, equipmentLabels: equipmentOptions.map(item => item.displayName || item.deviceNo), }) } catch (error) { wx.showToast({ title: error.message || '加载清洗设备失败', icon: 'none' }) } }, extractScene(scanResult) { const raw = decodeRepeated(scanResult) if (!raw) { return '' } const patterns = [ /(?:^|[?&])scene=([^&]+)/i, /(?:^|[?&])mold=([^&]+)/i, ] for (let index = 0; index < patterns.length; index += 1) { const matched = raw.match(patterns[index]) if (matched && matched[1]) { const value = decodeRepeated(matched[1]) return value.startsWith('mold=') ? value : `mold=${value}` } } return raw.startsWith('mold=') ? raw : '' }, async addByScanResult(scanResult) { const scene = this.extractScene(scanResult) if (!scene) { wx.showToast({ title: '未识别清洗二维码', icon: 'none' }) return } try { const resolved = await api.resolveMoldScene(scene) await locationGuard.ensureFactoryLocation(resolved.attendancePointName) this.addResolvedItem(resolved) } catch (error) { wx.showToast({ title: error.message || '二维码解析失败', icon: 'none' }) } }, startFill() { if (!this.data.items.length) { wx.showToast({ title: '请先添加清洗产品', icon: 'none' }) return } this.setData({ filling: true }) }, async continueAdd() { try { await locationGuard.ensureFactoryLocation(this.data.attendancePointName) } catch (error) { wx.showModal({ title: '无法继续扫码', content: error.message || '当前位置不在允许范围内', showCancel: false, }) return } wx.scanCode({ onlyFromCamera: false, success: res => { const candidates = [res.path, res.result, res.rawData] const raw = candidates.find(item => item) || '' this.addByScanResult(raw) }, }) }, abandon() { wx.showModal({ title: '放弃报工', content: '确认放弃本次清洗报工?', confirmText: '放弃', confirmColor: '#d92d20', success: res => { if (res.confirm) { wx.reLaunch({ url: '/pages/index/index' }) } }, }) }, onQuantityInput(e) { const index = e.currentTarget.dataset.index this.setData({ [`items[${index}].quantity`]: e.detail.value, }) }, noop() {}, openDeviceSelector(e) { const index = Number(e.currentTarget.dataset.index) const item = this.data.items[index] if (!item) { return } if (!this.data.equipmentOptions.length) { wx.showToast({ title: '暂无清洗设备', icon: 'none' }) return } const selected = new Set(item.deviceNos && item.deviceNos.length ? item.deviceNos : (item.deviceNo ? String(item.deviceNo).split('、') : [])) const deviceSelectOptions = this.data.equipmentOptions.map(equipment => ({ ...equipment, checked: selected.has(equipment.deviceNo), })) this.setData({ activeDeviceIndex: index, pendingDeviceNos: Array.from(selected).filter(Boolean), deviceSelectOptions, deviceModalVisible: true, }) }, closeDeviceSelector() { this.setData({ deviceModalVisible: false, activeDeviceIndex: -1, deviceSelectOptions: [], pendingDeviceNos: [], }) }, onDeviceSelectionChange(e) { const pendingDeviceNos = e.detail.value || [] const selected = new Set(pendingDeviceNos) this.setData({ pendingDeviceNos, deviceSelectOptions: this.data.deviceSelectOptions.map(item => ({ ...item, checked: selected.has(item.deviceNo), })), }) }, confirmDeviceSelection() { const index = Number(this.data.activeDeviceIndex) if (index < 0 || !this.data.items[index]) { this.closeDeviceSelector() return } if (!this.data.pendingDeviceNos.length) { wx.showToast({ title: '请至少选择一台清洗设备', icon: 'none' }) return } const deviceNos = this.data.pendingDeviceNos this.setData({ [`items[${index}].deviceNos`]: deviceNos, [`items[${index}].deviceNo`]: deviceNos.join('、'), deviceModalVisible: false, activeDeviceIndex: -1, deviceSelectOptions: [], pendingDeviceNos: [], }) }, async submit() { if (this.data.submitting) { return } const missingDevice = this.data.items.find(item => !item.deviceNo) if (missingDevice) { wx.showToast({ title: `${missingDevice.moldName}请选择清洗设备号`, icon: 'none' }) return } const invalid = this.data.items.find(item => Number(item.quantity || 0) <= 0) if (invalid) { wx.showToast({ title: `${invalid.moldName}请填写清洗数量`, icon: 'none' }) return } this.setData({ submitting: true }) wx.showLoading({ title: '提交中' }) try { const locationResult = await locationGuard.ensureFactoryLocation(this.data.attendancePointName) const report = await api.submitCleaningReport(this.data.items, locationResult.current) wx.reLaunch({ url: `/pages/reportResult/reportResult?reportId=${report.id}`, }) } catch (error) { wx.showToast({ title: error.message || '提交失败', icon: 'none' }) } finally { wx.hideLoading() this.setData({ submitting: false }) } }, })