From 36d41897b36fc174b0269442caf7e504e98905de Mon Sep 17 00:00:00 2001
From: zhongwenkai <3478244299@qq.com>
Date: Thu, 11 Jun 2026 17:19:54 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E4=B8=8A=E4=B8=8B=E6=A8=A1=E9=A1=B5?=
=?UTF-8?q?=E9=9D=A2=E6=96=B0=E5=A2=9E=E6=93=8D=E4=BD=9C=E4=BA=BA=E9=80=89?=
=?UTF-8?q?=E6=8B=A9=E4=B8=8E=E5=A4=87=E6=B3=A8=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/locales/en-US.js | 3 +
src/locales/zh-CN.js | 3 +
.../pages/moldoperate/dismount.vue | 231 ++++++++++++++++-
.../pages/moldoperate/index.vue | 234 +++++++++++++++++-
4 files changed, 467 insertions(+), 4 deletions(-)
diff --git a/src/locales/en-US.js b/src/locales/en-US.js
index 362ec8e..5c80b77 100644
--- a/src/locales/en-US.js
+++ b/src/locales/en-US.js
@@ -338,6 +338,7 @@ export default {
validatorOperateTypeRequired: 'Operation type is required',
validatorDeviceRequired: 'Device is required',
validatorMoldRequired: 'Select at least one mold for mounting',
+ validatorOperatorRequired: 'Please select operator',
validatorLowerMoldRequired: 'Select at least one mold for dismounting',
loadEditFailed: 'Failed to load edit data',
confirmDelete: 'Confirm delete this mold operate record?',
@@ -372,6 +373,8 @@ export default {
historySuffix: ' History',
historyTitle: 'Mold Operate History',
searchPlaceholder: 'Search device/mold name',
+ operator: 'Operator',
+ placeholderOperator: 'Select operator',
filterAll: 'All',
filterToday: 'Today',
filterWeek: 'This Week',
diff --git a/src/locales/zh-CN.js b/src/locales/zh-CN.js
index 01e0b99..ea2ae7f 100644
--- a/src/locales/zh-CN.js
+++ b/src/locales/zh-CN.js
@@ -338,6 +338,7 @@ export default {
validatorOperateTypeRequired: '操作类型不能为空',
validatorDeviceRequired: '设备不能为空',
validatorMoldRequired: '请至少选择一个上模模具',
+ validatorOperatorRequired: '请选择操作人',
validatorLowerMoldRequired: '请至少选择一个下模模具',
loadEditFailed: '加载编辑数据失败',
confirmDelete: '确认删除该上下模记录吗?',
@@ -372,6 +373,8 @@ export default {
historySuffix: '历史',
historyTitle: '上下模历史',
searchPlaceholder: '搜索设备/模具名称',
+ operator: '操作人',
+ placeholderOperator: '请选择操作人',
filterAll: '全部',
filterToday: '今天',
filterWeek: '本周',
diff --git a/src/pages_function/pages/moldoperate/dismount.vue b/src/pages_function/pages/moldoperate/dismount.vue
index 3ca9a14..7a320c0 100644
--- a/src/pages_function/pages/moldoperate/dismount.vue
+++ b/src/pages_function/pages/moldoperate/dismount.vue
@@ -113,6 +113,60 @@
+
+
+
+
+ {{ t('moldOperate.operator') + ' & ' + t('moldOperate.remark') }}
+
+
+
+
+ *{{ t('moldOperate.operator') }}
+
+
+
+ {{ selectedOperator ? selectedOperator.label : t('moldOperate.placeholderOperator') }}
+
+
+
+
+
+
+ {{ item.label }}
+
+
+ 暂无数据
+
+
+
+
+
+
+
+ {{ t('moldOperate.remark') }}
+
+
+
+
+
+
{{ t('moldOperate.confirmDismount') }}
@@ -150,6 +204,7 @@ import { onShow } from '@dcloudio/uni-app'
import { useI18n } from 'vue-i18n'
import { getLowerMoldList, getDeviceLedgerList, createMoldOperate } from '@/api/mes/moldoperate'
import { getDeviceLineTree } from '@/api/mes/deviceLine'
+import { getSimpleUserList } from '@/api/system/user'
const { t } = useI18n()
@@ -225,6 +280,13 @@ const lowerMoldLoading = ref(false)
const moldsLoaded = ref(false)
const tempSelectedMoldId = ref(null)
+// ---- 操作人与备注 ----
+const remarkText = ref('')
+const operatorOptions = ref([])
+const selectedOperator = ref(null)
+const operatorIndex = ref(-1)
+const showOperatorDropdown = ref(false)
+
// ---- 工具函数 ----
function textValue(v) {
if (v === 0) return '0'
@@ -442,6 +504,34 @@ function confirmLowerMoldSelection() {
function closeLowerMoldPicker() { lowerMoldPickerRef.value?.close() }
+// ---- 操作人列表加载 ----
+async function loadOperators() {
+ try {
+ const res = await getSimpleUserList()
+ const data = Array.isArray(res) ? res : (Array.isArray(res?.data) ? res.data : [])
+ operatorOptions.value = data.map((u) => ({
+ value: u.id || u.userId,
+ label: u.nickname || u.userName || u.name || String(u.id || '')
+ }))
+ } catch (e) {
+ console.error('loadOperators error', e)
+ }
+}
+
+function toggleOperatorDropdown() {
+ showOperatorDropdown.value = !showOperatorDropdown.value
+}
+
+function closeOperatorDropdown() {
+ showOperatorDropdown.value = false
+}
+
+function handleSelectOperator(item, idx) {
+ selectedOperator.value = item
+ operatorIndex.value = idx
+ closeOperatorDropdown()
+}
+
function goToHistory() {
uni.navigateTo({ url: '/pages_function/pages/moldoperate/history?type=down' })
}
@@ -460,6 +550,10 @@ function validForm() {
uni.showToast({ title: t('moldOperate.validatorLowerMoldRequired'), icon: 'none' })
return false
}
+ if (!selectedOperator.value) {
+ uni.showToast({ title: t('moldOperate.validatorOperatorRequired'), icon: 'none' })
+ return false
+ }
return true
}
@@ -474,6 +568,13 @@ async function handleConfirm() {
lineId: device.deviceLine != null ? String(device.deviceLine) : undefined,
lineName: device.deviceLine != null ? getTopLineName(device.deviceLine) : (device.lineName || undefined)
}
+ // 添加操作人和备注
+ if (selectedOperator.value) {
+ payload.operatorId = selectedOperator.value.value
+ }
+ if (remarkText.value.trim()) {
+ payload.remark = remarkText.value.trim()
+ }
console.log('[下模] 提交参数 =', JSON.stringify(payload))
await createMoldOperate(payload)
uni.showToast({ title: t('functionCommon.createSuccess'), icon: 'success' })
@@ -489,6 +590,9 @@ async function handleConfirm() {
selectedDevice.value = {}
selectedMold.value = {}
lowerMoldOptions.value = []
+ remarkText.value = ''
+ selectedOperator.value = null
+ operatorIndex.value = -1
} catch (e) {
console.error('[下模] 保存失败 =', e)
const errMsg = e?.msg || (typeof e === 'string' ? e : e?.message) || '系统异常'
@@ -497,7 +601,7 @@ async function handleConfirm() {
}
onShow(async () => {
- await Promise.allSettled([loadDevices(), loadLineTree()])
+ await Promise.allSettled([loadDevices(), loadLineTree(), loadOperators()])
// 从 globalData 读取设备选择页回传的设备
const device = getApp().globalData._deviceSelectResult
if (device) {
@@ -606,7 +710,6 @@ onShow(async () => {
margin: 16rpx 24rpx;
background: #ffffff;
border-radius: 14rpx;
- overflow: hidden;
}
.section-title-bar {
@@ -735,6 +838,130 @@ onShow(async () => {
}
}
+/* ====== 表单行(操作人/备注) ====== */
+.form-row {
+ margin-top: 18rpx;
+
+ &:first-child {
+ margin-top: 0;
+ }
+}
+
+.form-cell {
+ width: 100%;
+
+ .form-label {
+ display: block;
+ font-size: 24rpx;
+ color: #999;
+ margin-bottom: 8rpx;
+
+ .required {
+ color: #dc2626;
+ margin-right: 4rpx;
+ }
+ }
+}
+
+/* ====== 下拉选择器(操作人) ====== */
+.select-dropdown {
+ position: relative;
+ width: 100%;
+}
+
+.dropdown-input {
+ display: flex;
+ align-items: center;
+ height: 72rpx;
+ padding: 0 20rpx;
+ border: 1rpx solid #e0e0e0;
+ border-radius: 10rpx;
+ font-size: 27rpx;
+ color: #333;
+ background: #f9fafb;
+}
+
+.dropdown-value {
+ flex: 1;
+
+ &.placeholder {
+ color: #bbb;
+ }
+}
+
+.dropdown-arrow {
+ position: absolute;
+ right: 16rpx;
+ top: 50%;
+ transform: translateY(-50%);
+ pointer-events: none;
+}
+
+/* ====== 下拉面板(在输入框下方展开) ====== */
+.dropdown-panel {
+ position: absolute;
+ top: 76rpx;
+ left: 0;
+ right: 0;
+ z-index: 99;
+ background: #ffffff;
+ border: 1rpx solid #e0e0e0;
+ border-radius: 12rpx;
+ box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.1);
+ overflow: hidden;
+}
+
+.dropdown-scroll {
+ max-height: 400rpx;
+}
+
+.dropdown-item {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 22rpx 28rpx;
+ font-size: 27rpx;
+ color: #333;
+ border-bottom: 1rpx solid #f5f5f5;
+
+ &:last-child {
+ border-bottom: none;
+ }
+
+ &:active {
+ background: #f5f7fa;
+ }
+
+ &.active {
+ color: #1f7cff;
+ background: #f0f7ff;
+ }
+}
+
+.dropdown-item-text {
+ flex: 1;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.dropdown-empty {
+ padding: 32rpx;
+ text-align: center;
+ font-size: 26rpx;
+ color: #999;
+}
+
+.form-input {
+ height: 72rpx;
+ padding: 0 20rpx;
+ border: 1rpx solid #e0e0e0;
+ border-radius: 10rpx;
+ font-size: 27rpx;
+ color: #333;
+ background: #f9fafb;
+}
+
/* ====== 空提示 ====== */
.empty-mold-hint {
padding: 40rpx 24rpx;
diff --git a/src/pages_function/pages/moldoperate/index.vue b/src/pages_function/pages/moldoperate/index.vue
index 682000c..2b0346f 100644
--- a/src/pages_function/pages/moldoperate/index.vue
+++ b/src/pages_function/pages/moldoperate/index.vue
@@ -107,6 +107,62 @@
+
+
+
+
+ {{ t('moldOperate.operator') + ' & ' + t('moldOperate.remark') }}
+
+
+
+
+ *{{ t('moldOperate.operator') }}
+
+
+
+
+ {{ selectedOperator ? selectedOperator.label : t('moldOperate.placeholderOperator') }}
+
+
+
+
+
+
+
+ {{ item.label }}
+
+
+ 暂无数据
+
+
+
+
+
+
+
+ {{ t('moldOperate.remark') }}
+
+
+
+
+
+
{{ t('functionCommon.cancel') }}
@@ -121,6 +177,7 @@ import { computed, ref } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import { useI18n } from 'vue-i18n'
import { getDeviceLedgerList, createMoldOperate } from '@/api/mes/moldoperate'
+import { getSimpleUserList } from '@/api/system/user'
const { t } = useI18n()
@@ -160,6 +217,10 @@ const selectedDevice = ref({})
const selectedMountMolds = ref([])
const tempSelectedDeviceId = ref(null)
+const remarkText = ref('')
+const operatorOptions = ref([])
+const selectedOperator = ref(null)
+const operatorIndex = ref(-1)
// 设备状态 - 上模
const deviceStatusClass = computed(() => {
@@ -241,6 +302,36 @@ const currentMoldDisplay = computed(() => {
return textValue(selectedDevice.value.currentMold)
})
+// ---- 操作人列表加载 ----
+async function loadOperators() {
+ try {
+ const res = await getSimpleUserList()
+ const data = Array.isArray(res) ? res : (Array.isArray(res?.data) ? res.data : [])
+ operatorOptions.value = data.map((u) => ({
+ value: u.id || u.userId,
+ label: u.nickname || u.userName || u.name || String(u.id || '')
+ }))
+ } catch (e) {
+ console.error('loadOperators error', e)
+ }
+}
+
+const showOperatorDropdown = ref(false)
+
+function toggleOperatorDropdown() {
+ showOperatorDropdown.value = !showOperatorDropdown.value
+}
+
+function closeOperatorDropdown() {
+ showOperatorDropdown.value = false
+}
+
+function handleSelectOperator(item, idx) {
+ selectedOperator.value = item
+ operatorIndex.value = idx
+ closeOperatorDropdown()
+}
+
function selectDevice(device) {
selectedDevice.value = device || {}
tempSelectedDeviceId.value = device ? device.id : null
@@ -272,6 +363,10 @@ function validFormMount() {
uni.showToast({ title: t('moldOperate.validatorMoldRequired'), icon: 'none' })
return false
}
+ if (!selectedOperator.value) {
+ uni.showToast({ title: t('moldOperate.validatorOperatorRequired'), icon: 'none' })
+ return false
+ }
return true
}
@@ -286,6 +381,13 @@ async function handleConfirmMount() {
lineName: selectedDevice.value.workshopName || '',
lineId: selectedDevice.value.deviceLine || ''
}
+ // 添加操作人和备注
+ if (selectedOperator.value) {
+ payload.operatorId = selectedOperator.value.value
+ }
+ if (remarkText.value.trim()) {
+ payload.remark = remarkText.value.trim()
+ }
console.log('=== 上模提交参数 ===', JSON.stringify(payload))
console.log('=== deviceId type:', typeof payload.deviceId, 'value:', payload.deviceId)
console.log('=== moldId type:', typeof payload.moldId, 'value:', payload.moldId)
@@ -347,6 +449,9 @@ function handleScan() {
function handleCancel() {
selectedDevice.value = {}
selectedMountMolds.value = []
+ remarkText.value = ''
+ selectedOperator.value = null
+ operatorIndex.value = -1
}
function goBack() {
@@ -358,7 +463,7 @@ function goToHistory() {
}
onShow(async () => {
- await Promise.allSettled([loadDevices()])
+ await Promise.allSettled([loadDevices(), loadOperators()])
// 从 globalData 读取设备选择页回传的设备
const device = getApp().globalData._deviceSelectResult
if (device) {
@@ -473,7 +578,6 @@ onShow(async () => {
margin: 16rpx 24rpx;
background: #ffffff;
border-radius: 14rpx;
- overflow: hidden;
}
.section-title-bar {
@@ -592,6 +696,132 @@ onShow(async () => {
.change-text { font-size: 26rpx; color: #666; }
}
+/* ====== 表单行(操作人/备注) ====== */
+.form-row {
+ margin-top: 18rpx;
+
+ &:first-child {
+ margin-top: 0;
+ }
+}
+
+.form-cell {
+ width: 100%;
+
+ .form-label {
+ display: block;
+ font-size: 24rpx;
+ color: #999;
+ margin-bottom: 8rpx;
+
+ .required {
+ color: #dc2626;
+ margin-right: 4rpx;
+ }
+ }
+}
+
+
+
+/* ====== 下拉选择器(操作人) ====== */
+.select-dropdown {
+ position: relative;
+ width: 100%;
+}
+
+.dropdown-input {
+ display: flex;
+ align-items: center;
+ height: 72rpx;
+ padding: 0 20rpx;
+ border: 1rpx solid #e0e0e0;
+ border-radius: 10rpx;
+ font-size: 27rpx;
+ color: #333;
+ background: #f9fafb;
+}
+
+.dropdown-value {
+ flex: 1;
+
+ &.placeholder {
+ color: #bbb;
+ }
+}
+
+.dropdown-arrow {
+ position: absolute;
+ right: 16rpx;
+ top: 50%;
+ transform: translateY(-50%);
+ pointer-events: none;
+}
+
+/* ====== 下拉面板(在输入框下方展开) ====== */
+.dropdown-panel {
+ position: absolute;
+ top: 76rpx;
+ left: 0;
+ right: 0;
+ z-index: 99;
+ background: #ffffff;
+ border: 1rpx solid #e0e0e0;
+ border-radius: 12rpx;
+ box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.1);
+ overflow: hidden;
+}
+
+.dropdown-scroll {
+ max-height: 400rpx;
+}
+
+.dropdown-item {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 22rpx 28rpx;
+ font-size: 27rpx;
+ color: #333;
+ border-bottom: 1rpx solid #f5f5f5;
+
+ &:last-child {
+ border-bottom: none;
+ }
+
+ &:active {
+ background: #f5f7fa;
+ }
+
+ &.active {
+ color: #1f7cff;
+ background: #f0f7ff;
+ }
+}
+
+.dropdown-item-text {
+ flex: 1;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.dropdown-empty {
+ padding: 32rpx;
+ text-align: center;
+ font-size: 26rpx;
+ color: #999;
+}
+
+.form-input {
+ height: 72rpx;
+ padding: 0 20rpx;
+ border: 1rpx solid #e0e0e0;
+ border-radius: 10rpx;
+ font-size: 27rpx;
+ color: #333;
+ background: #f9fafb;
+}
+
/* ====== 空提示 ====== */
.empty-mold-hint {
padding: 40rpx 24rpx;