diff --git a/src/api/mes/moldget.js b/src/api/mes/moldget.js
index 44fdb21..c1d333a 100644
--- a/src/api/mes/moldget.js
+++ b/src/api/mes/moldget.js
@@ -61,3 +61,12 @@ export function getSimpleUserList() {
method: 'get'
})
}
+
+// 仓库库区列表(根据仓库ID获取)
+export function getWarehouseAreaSimpleList(warehouseId) {
+ return request({
+ url: '/admin-api/erp/warehouse-area/simple-list',
+ method: 'get',
+ params: { warehouseId }
+ })
+}
diff --git a/src/api/mes/sparepart.js b/src/api/mes/sparepart.js
new file mode 100644
index 0000000..1afc49a
--- /dev/null
+++ b/src/api/mes/sparepart.js
@@ -0,0 +1,22 @@
+import request from '@/utils/request'
+
+// 备件列表(分页查询全部产品,前端按 categoryType=5 过滤备件)
+export function getSparepartSimpleList(pageNo = 1) {
+ return request({
+ url: '/admin-api/erp/product/page',
+ method: 'get',
+ params: {
+ pageNo,
+ pageSize: 100
+ }
+ })
+}
+
+// 备件详情(含供应商、图片等完整信息)
+export function getSparepartDetail(id) {
+ return request({
+ url: '/admin-api/erp/product/get',
+ method: 'get',
+ params: { id }
+ })
+}
diff --git a/src/api/mes/sparepartInbound.js b/src/api/mes/sparepartInbound.js
new file mode 100644
index 0000000..c4ff7a8
--- /dev/null
+++ b/src/api/mes/sparepartInbound.js
@@ -0,0 +1,36 @@
+import request from '@/utils/request'
+
+// 备件入库单创建
+export function createSparepartInbound(data) {
+ return request({
+ url: '/admin-api/erp/stock-in/create',
+ method: 'post',
+ data: { ...data, inType: '备件入库' }
+ })
+}
+// 备件入库单分页查询(待入库/待审核)
+export function getSparepartInboundPage(params = {}) {
+ return request({
+ url: '/admin-api/erp/stock-in/page',
+ method: 'get',
+ params: { ...params, inType: '备件入库' }
+ })
+}
+
+// 备件入库单审核(status: 20=通过, 1=驳回)
+export function auditSparepartInbound(data) {
+ return request({
+ url: '/admin-api/erp/stock-in/audit',
+ method: 'put',
+ data
+ })
+}
+
+// 备件入库单删除
+export function deleteSparepartInbound(id) {
+ return request({
+ url: '/admin-api/erp/stock-in/delete',
+ method: 'delete',
+ params: { ids: String(id) }
+ })
+}
diff --git a/src/api/mes/sparepartOutbound.js b/src/api/mes/sparepartOutbound.js
new file mode 100644
index 0000000..5325f84
--- /dev/null
+++ b/src/api/mes/sparepartOutbound.js
@@ -0,0 +1,28 @@
+import request from '@/utils/request'
+
+// 备件出库单分页查询
+export function getSparepartOutboundPage(params = {}) {
+ return request({
+ url: '/admin-api/erp/stock-out/page',
+ method: 'get',
+ params: { ...params, outType: '备件出库' }
+ })
+}
+
+// 备件出库单审核(status: 20=通过, 1=驳回)
+export function auditSparepartOutbound(data) {
+ return request({
+ url: '/admin-api/erp/stock-out/audit',
+ method: 'put',
+ data
+ })
+}
+
+// 备件出库单删除
+export function deleteSparepartOutbound(id) {
+ return request({
+ url: '/admin-api/erp/stock-out/delete',
+ method: 'delete',
+ params: { ids: String(id) }
+ })
+}
diff --git a/src/api/system/user.js b/src/api/system/user.js
index 2641a5b..94acd63 100644
--- a/src/api/system/user.js
+++ b/src/api/system/user.js
@@ -22,10 +22,11 @@ export function getUserProfile() {
})
}
-export function getSimpleUserList() {
+export function getSimpleUserList(params) {
return request({
url: '/admin-api/system/user/simple-list',
- method: 'get'
+ method: 'get',
+ params
})
}
diff --git a/src/components/common/PermissionMenuPage.vue b/src/components/common/PermissionMenuPage.vue
index 8e1b115..314a4e5 100644
--- a/src/components/common/PermissionMenuPage.vue
+++ b/src/components/common/PermissionMenuPage.vue
@@ -37,7 +37,7 @@
- {{ translateLiteral(module.name) }}
+ {{ getDisplayName(module) }}
@@ -60,9 +60,9 @@
size="24"
:color="getModuleColor(moduleIndex)"
>
- {{ getMenuSymbol(entry.name, entryIndex) }}
+ {{ getMenuSymbol(getDisplayName(entry), entryIndex) }}
- {{ translateLiteral(entry.name) }}
+ {{ getDisplayName(entry) }}
@@ -77,10 +77,10 @@
diff --git a/src/pages_function/pages/moldoperate/deviceSelect.vue b/src/pages_function/pages/moldoperate/deviceSelect.vue
index 4bbf07c..cac770e 100644
--- a/src/pages_function/pages/moldoperate/deviceSelect.vue
+++ b/src/pages_function/pages/moldoperate/deviceSelect.vue
@@ -69,6 +69,7 @@ import { useI18n } from 'vue-i18n'
import NavBar from '@/components/common/NavBar.vue'
import { getDeviceLedgerList } from '@/api/mes/moldoperate'
import { getDeviceLineTree } from '@/api/mes/deviceLine'
+import { getMoldBrandPage } from '@/api/mes/mold'
const { t } = useI18n()
@@ -105,65 +106,39 @@ function getStatusLabel(device) {
return map[status] || textValue(device.deviceStatus) || '-'
}
-// 当前在机模具 - 优先从持久化存储读取(实时),否则 fallback 设备台账字段
-function getCurrentMold(device) {
- const deviceId = device?.id
- const deviceCode = device?.deviceCode
+// 设备名 → 在机模具名 映射表
+const deviceMoldMap = ref(new Map())
- // 1. 优先读新版 _mountedMoldInfoMap(按 deviceId 索引,再用 deviceCode fallback)
+async function loadDeviceMolds() {
try {
- const map = uni.getStorageSync('_mountedMoldInfoMap') || {}
- // 先按 id 匹配
- const key = String(deviceId)
- let info = deviceId != null ? map[key] : null
- // 再按 deviceCode 匹配(兼容 id 可能不一致的情况)
- if (!info && deviceCode) {
- const found = Object.values(map).find((item) => item?.deviceCode === deviceCode)
- if (found) info = found
- }
-
- // 调试日志:只在首次加载时输出一次
- if (!getCurrentMold._logged) {
- getCurrentMold._logged = true
- console.log('[deviceSelect] === 调试信息 ===')
- console.log('[deviceSelect] storage map keys:', Object.keys(map))
- console.log('[deviceSelect] storage map values:', map)
- console.log('[deviceSelect] 当前设备 deviceId:', deviceId, 'type:', typeof deviceId, 'key:', key)
- console.log('[deviceSelect] 当前设备 deviceCode:', deviceCode)
- console.log('[deviceSelect] id匹配结果:', info ? '命中' : '未命中')
- if (!info) {
- console.log('[deviceSelect] 尝试 deviceCode fallback...')
- for (const [k, v] of Object.entries(map)) {
- console.log('[deviceSelect] storage[', k, '].deviceCode =', v?.deviceCode, 'vs 设备 code =', deviceCode, '匹配:', v?.deviceCode === deviceCode)
- }
+ const res = await getMoldBrandPage({ pageSize: 100 })
+ const root = res && res.data !== undefined ? res.data : res
+ const pageData = root?.pageResult || root
+ const list = Array.isArray(pageData) ? pageData : (Array.isArray(pageData?.list) ? pageData.list : [])
+ const map = new Map()
+ for (const mold of list) {
+ const deviceName = mold.deviceName
+ if (deviceName) {
+ if (!map.has(deviceName)) map.set(deviceName, [])
+ map.get(deviceName).push(mold.name || '')
}
- // fallback 检查
- const saved = uni.getStorageSync('_mountedMoldInfo') || null
- console.log('[deviceSelect] 旧版 _mountedMoldInfo:', saved)
- console.log('[deviceSelect] 设备台账字段 currentMold:', device?.currentMold, 'moldName:', device?.moldName, 'moldId:', device?.moldId)
- }
-
- if (info?.mold) {
- return info.mold.name || info.mold.moldName || '-'
}
+ deviceMoldMap.value = map
} catch (e) {
- console.warn('[deviceSelect] read _mountedMoldInfoMap error', e)
+ console.error('loadDeviceMolds error', e)
}
+}
- // 2. 兼容旧版 _mountedMoldInfo
- let saved = null
- try { saved = uni.getStorageSync('_mountedMoldInfo') || null } catch {}
- if (saved) {
- const idMatch = deviceId != null && String(saved.deviceId) === String(deviceId)
- const codeMatch = deviceCode && saved.deviceCode === deviceCode
- if (idMatch || codeMatch) {
- return saved.mold?.name || saved.mold?.moldName || '-'
- }
+// 当前在机模具 - 从模具型号接口获取
+function getCurrentMold(device) {
+ if (!device) return t('moldOperate.noMoldOnDevice')
+ const deviceName = device.deviceName
+ if (deviceName && deviceMoldMap.value.has(deviceName)) {
+ const names = deviceMoldMap.value.get(deviceName) || []
+ return names.join(',')
}
-
- // 3. fallback 设备台账静态字段
- const staticMold = textValue(device.currentMold || device.moldName || device.moldId)
- return staticMold === '-' ? t('moldOperate.noMoldOnDevice') : staticMold
+ // fallback 设备台账静态字段
+ return textValue(device.currentMold || device.moldName) || t('moldOperate.noMoldOnDevice')
}
function flattenLineTree(nodes, parentId) {
@@ -269,7 +244,7 @@ function handleConfirm() {
}
onShow(async () => {
- await Promise.allSettled([loadDevices(), loadLineTree()])
+ await Promise.allSettled([loadDevices(), loadLineTree(), loadDeviceMolds()])
})
diff --git a/src/pages_function/pages/moldoperate/dismount.vue b/src/pages_function/pages/moldoperate/dismount.vue
index ada878e..ceffcd5 100644
--- a/src/pages_function/pages/moldoperate/dismount.vue
+++ b/src/pages_function/pages/moldoperate/dismount.vue
@@ -4,24 +4,24 @@
-
- {{ t('moldPressureNet.history') }}
+
-
-
-
-
- {{ t('moldOperate.scanDevice') }}
+
+
-
-
-
{{ t('moldOperate.selectDevice') }}
@@ -80,16 +80,6 @@
{{ t('moldOperate.product') }}
{{ textValue(selectedMold.productName) }}
-
- {{ t('moldOperate.mountTime') }}
- {{ textValue(selectedMold.mountTime) }}
-
-
-
-
- {{ t('moldOperate.useCount') }}
- {{ formatUseCount(selectedMold.useCount) }}
-
@@ -117,40 +107,15 @@
{{ t('moldOperate.operator') + ' & ' + t('moldOperate.remark') }}
-
-
-
- *{{ t('moldOperate.operator') }}
-
-
-
- {{ selectedOperator ? selectedOperator.label : t('moldOperate.placeholderOperator') }}
-
-
-
-
-
-
- {{ item.label }}
-
-
- 暂无数据
-
+
+
+
+ *{{ t('moldOperate.operator') }}
+
+ {{ currentUserName }}
-
{{ t('moldOperate.remark') }}
@@ -202,11 +167,17 @@ import { computed, reactive, ref } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import { useI18n } from 'vue-i18n'
import NavBar from '@/components/common/NavBar.vue'
-import { getLowerMoldList, getDeviceLedgerList, createMoldOperate } from '@/api/mes/moldoperate'
+import { getDeviceLedgerList, createMoldOperate } from '@/api/mes/moldoperate'
+import { getMoldBrandPage } from '@/api/mes/mold'
+import useUserStore from '@/store/modules/user'
import { getDeviceLineTree } from '@/api/mes/deviceLine'
-import { getSimpleUserList } from '@/api/system/user'
const { t } = useI18n()
+const userStore = useUserStore()
+
+// 当前登录用户
+const currentUserName = computed(() => userStore.name || '未知用户')
+const currentUserId = computed(() => userStore.userId)
const lineInfoMap = ref(new Map()) // deviceLine id → { name, parentId, parentChain }
@@ -282,10 +253,8 @@ const tempSelectedMoldId = ref(null)
// ---- 操作人与备注 ----
const remarkText = ref('')
-const operatorOptions = ref([])
const selectedOperator = ref(null)
-const operatorIndex = ref(-1)
-const showOperatorDropdown = ref(false)
+const scanCodeInput = ref('')
// ---- 工具函数 ----
function textValue(v) {
@@ -295,12 +264,7 @@ function textValue(v) {
return s || '-'
}
-function formatUseCount(count) {
- if (count == null) return '-'
- const num = Number(count)
- if (isNaN(num)) return String(count)
- return num.toLocaleString() + ' ' + t('moldOperate.countUnit')
-}
+
function formatTime(time) {
if (!time) return '-'
@@ -374,45 +338,20 @@ function findArr(obj, d = 0) {
return []
}
-async function loadLowerMolds(deviceId) {
+async function loadLowerMolds(deviceName) {
lowerMoldLoading.value = true
try {
- // ====== 策略1:优先从持久化存储读取(按设备ID索引,不会互覆盖)======
- let map = {}
- try { map = uni.getStorageSync('_mountedMoldInfoMap') || {} } catch {}
- const savedInfo = map[String(deviceId)] || null
-
- console.log('[下模] 持久化在机模具信息 =', savedInfo ? JSON.stringify(savedInfo) : 'null', 'deviceId=', deviceId)
-
- if (savedInfo && savedInfo.mold) {
- console.log('[下模] 命中持久化数据, deviceId=', deviceId)
- const m = savedInfo.mold
- lowerMoldOptions.value = [{
- id: m.id,
- moldId: m.id,
- moldName: m.name || m.moldName || '-',
- moldCode: m.code || m.moldCode || '-',
- productName: m.productName || '-',
- mountTime: formatTime(savedInfo.mountTime),
- useCount: '-'
- }]
- console.log('[下模] 使用持久化数据 =', JSON.stringify(lowerMoldOptions.value[0]))
- return
- }
- console.log('[下模] 未命中持久化数据,进入接口查询')
-
- // ====== 策略2:fallback - 调用在机模具接口 ======
- let list = []
- try {
- const res = await getLowerMoldList(deviceId)
- const root = (res && res.data !== undefined) ? res.data : res
- list = findArr(root)
- } catch (apiErr) {
- console.warn('[下模] getLowerMoldList 接口异常', apiErr)
- }
-
- lowerMoldOptions.value = list
- console.log('[下模] loadLowerMolds 返回 list.length =', list.length)
+ const res = await getMoldBrandPage({ deviceName, pageSize: 100 })
+ const root = (res && res.data !== undefined) ? res.data : res
+ const pageData = root?.pageResult || root
+ const list = Array.isArray(pageData) ? pageData : (Array.isArray(pageData?.list) ? pageData.list : [])
+ lowerMoldOptions.value = list.map(m => ({
+ id: m.id,
+ moldId: m.id,
+ moldName: m.name || '-',
+ moldCode: m.code || '-',
+ productName: m.productName || '-'
+ }))
} catch (e) {
console.error('loadLowerMolds error', e)
} finally {
@@ -420,17 +359,39 @@ async function loadLowerMolds(deviceId) {
}
}
-// ---- 扫描设备码 ----
+// ---- 扫描/输入设备码 ----
+function matchDeviceByCode(code) {
+ if (!code) return null
+ let matched = null
+ if (code.toUpperCase().startsWith('EQUIPMENT-')) {
+ const idFromQr = code.replace(/EQUIPMENT-/i, '')
+ matched = deviceOptions.value.find((d) => String(d.raw.id) === idFromQr)
+ }
+ if (!matched) {
+ matched = deviceOptions.value.find((d) =>
+ Object.values(d.raw).some((v) =>
+ typeof v === 'string' && v.trim().toUpperCase() === code.toUpperCase()
+ ) || d.label.toUpperCase().includes(code.toUpperCase())
+ )
+ }
+ if (!matched) {
+ const idMatch = code.match(/(\d+)$/)
+ if (idMatch) {
+ matched = deviceOptions.value.find((d) => String(d.raw.id) === idMatch[1])
+ }
+ }
+ return matched
+}
+
function handleScan() {
uni.scanCode({
onlyFromCamera: false,
scanType: ['qrCode', 'barCode'],
success(res) {
- const code = res.result?.trim()
+ const code = (res.result || '').trim()
if (!code) return
- const matched = deviceOptions.value.find((d) =>
- d.raw.deviceCode === code || String(d.raw.code) === code || d.label.includes(code)
- )
+ scanCodeInput.value = code
+ const matched = matchDeviceByCode(code)
if (matched) {
selectDevice(matched.raw)
} else {
@@ -445,13 +406,24 @@ function handleScan() {
})
}
+function onScanInputConfirm() {
+ const code = scanCodeInput.value.trim()
+ if (!code) return
+ const matched = matchDeviceByCode(code)
+ if (matched) {
+ selectDevice(matched.raw)
+ } else {
+ uni.showToast({ title: t('moldOperate.deviceNotFound'), icon: 'none' })
+ }
+}
+
// ---- 设备选择 ----
function selectDevice(device) {
selectedDevice.value = device || {}
moldsLoaded.value = false
selectedMold.value = {}
- if (device?.id) {
- loadLowerMolds(device.id).then(() => {
+ if (device?.deviceName) {
+ loadLowerMolds(device.deviceName).then(() => {
moldsLoaded.value = true
if (lowerMoldOptions.value.length > 0) {
const first = lowerMoldOptions.value[0]
@@ -459,9 +431,7 @@ function selectDevice(device) {
id: first.id || first.moldId,
moldName: first.moldName || first.name,
moldCode: first.moldCode || first.code,
- productName: first.productName || '-',
- mountTime: first.mountTime || '-',
- useCount: first.useCount ?? '-'
+ productName: first.productName || '-'
}
}
})
@@ -475,12 +445,12 @@ function openDevicePicker() {
// ---- 在机模具选择(更换下模对象)----
function openLowerMoldPicker() {
- if (!selectedDevice.value?.id) {
+ if (!selectedDevice.value?.deviceName) {
uni.showToast({ title: t('moldOperate.validatorDeviceRequired'), icon: 'none' })
return
}
tempSelectedMoldId.value = selectedMold.value ? String(selectedMold.value.id || selectedMold.value.moldId) : null
- loadLowerMolds(selectedDevice.value.id).then(() => {
+ loadLowerMolds(selectedDevice.value.deviceName).then(() => {
lowerMoldPickerRef.value?.open()
})
}
@@ -494,9 +464,7 @@ function confirmLowerMoldSelection() {
id: mold.id || mold.moldId,
moldName: mold.moldName || mold.name,
moldCode: mold.moldCode || mold.code,
- productName: mold.productName || '-',
- mountTime: mold.mountTime || '-',
- useCount: mold.useCount ?? '-'
+ productName: mold.productName || '-'
}
}
lowerMoldPickerRef.value?.close()
@@ -504,34 +472,16 @@ 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 autoSetOperator() {
+ if (currentUserId.value && currentUserName.value) {
+ selectedOperator.value = {
+ value: currentUserId.value,
+ label: currentUserName.value
+ }
}
}
-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' })
}
@@ -578,21 +528,11 @@ async function handleConfirm() {
console.log('[下模] 提交参数 =', JSON.stringify(payload))
await createMoldOperate(payload)
uni.showToast({ title: t('functionCommon.createSuccess'), icon: 'success' })
- // 下模成功后清除该设备的持久化数据
- if (selectedDevice.value?.id) {
- try {
- const map = uni.getStorageSync('_mountedMoldInfoMap') || {}
- delete map[String(selectedDevice.value.id)]
- uni.setStorageSync('_mountedMoldInfoMap', map)
- } catch {}
- }
// 重置表单
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) || '系统异常'
@@ -608,7 +548,8 @@ function handleCancel() {
}
onShow(async () => {
- await Promise.allSettled([loadDevices(), loadLineTree(), loadOperators()])
+ autoSetOperator()
+ await Promise.allSettled([loadDevices(), loadLineTree()])
// 从 globalData 读取设备选择页回传的设备
const device = getApp().globalData._deviceSelectResult
if (device) {
@@ -621,21 +562,16 @@ onShow(async () => {
diff --git a/src/pages_function/pages/sparepartInbound/index.vue b/src/pages_function/pages/sparepartInbound/index.vue
new file mode 100644
index 0000000..bdc7497
--- /dev/null
+++ b/src/pages_function/pages/sparepartInbound/index.vue
@@ -0,0 +1,594 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ currentStatusLabel }}
+
+
+
+ {{ t('functionCommon.reset') }}
+
+
+
+
+
+
+
+
+
+ {{ t('sparepartInbound.sparepartInfo') }}
+ {{ textValue(item.productNames) }}
+
+
+ {{ t('sparepartInbound.inboundTime') }}
+ {{ formatDateTime(item.inTime || item.createTime) }}
+
+
+ {{ t('sparepartInbound.creator') }}
+ {{ textValue(item.creatorName || item.creator) }}
+
+
+ {{ t('sparepartInbound.quantity') }}
+ {{ textValue(item.totalCount) }}
+
+
+ {{ t('sparepartInbound.reviewer') }}
+ {{ textValue(item.auditUserName) }}
+
+
+
+
+ {{ t('sparepartInbound.approve') }}
+ {{ t('sparepartInbound.reject') }}
+
+
+
+ {{ t('functionCommon.loading') }}
+ {{ t('sparepartInbound.empty') }}
+ {{ t('functionCommon.loadingMore') }}
+ {{ t('functionCommon.noMoreData') }}
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
diff --git a/src/pages_function/pages/sparepartInbound/sparepartSelect.vue b/src/pages_function/pages/sparepartInbound/sparepartSelect.vue
new file mode 100644
index 0000000..7730636
--- /dev/null
+++ b/src/pages_function/pages/sparepartInbound/sparepartSelect.vue
@@ -0,0 +1,295 @@
+
+
+
+
+
+
+
+
+
+ ✕
+
+
+
+
+
+
+
+
+
+ {{ t('sparepartInbound.sparepartCode') }}
+ {{ textValue(item.barCode) }}
+
+
+ {{ t('sparepartInbound.spec') }}
+ {{ textValue(item.standard || item.deviceSpec) }}
+
+
+ {{ t('sparepartInbound.category') }}
+ {{ textValue(item.categoryName) }}
+
+
+ {{ t('sparepartInbound.unit') }}
+ {{ textValue(item.unitName) }}
+
+
+ {{ t('sparepartInbound.purchaseUnit') }}
+ {{ textValue(item.purchaseUnitName) }}
+
+
+ {{ t('sparepartInbound.convertRatio') }}
+ 1{{ textValue(item.purchaseUnitName) }}={{ textValue(item.purchaseUnitConvertQuantity) }}{{ textValue(item.unitName) }}
+
+
+
+
+
+
+
+ {{ t('functionCommon.loading') }}
+ {{ t('sparepartInbound.noSparepartData') }}
+
+
+
+
+
+ {{ t('functionCommon.confirm') }}
+
+
+
+
+
+
+
+
diff --git a/src/pages_function/pages/sparepartInbound/userSelect.vue b/src/pages_function/pages/sparepartInbound/userSelect.vue
new file mode 100644
index 0000000..e69de29
diff --git a/src/pages_function/pages/sparepartOutbound/create.vue b/src/pages_function/pages/sparepartOutbound/create.vue
new file mode 100644
index 0000000..005d667
--- /dev/null
+++ b/src/pages_function/pages/sparepartOutbound/create.vue
@@ -0,0 +1,711 @@
+
+
+
+
+
+
+
+
+
+
+ 扫备件码
+
+
+
+
+
+ 选择备件
+
+
+
+
+
+
+
+ 已选备件
+
+
+
+
+
+
+ 📦
+
+
+
+
+ 备件名称:
+ {{ textValue(selectedSparepart.name) }}
+
+
+ 规格:
+ {{ textValue(selectedSparepart.standard || selectedSparepart.deviceSpec) }}
+
+
+ 当前库存:
+ {{ textValue(selectedSparepart.stock) }}{{ textUnit(selectedSparepart.minStockUnitName) }}
+
+
+
+
+
+
+ 采购单位:
+ {{ textValue(selectedSparepart.purchaseUnitName) }}
+
+
+ 库存单位:
+ {{ textValue(selectedSparepart.unitName || selectedSparepart.minStockUnitName) }}
+
+
+
+ 换算关系:
+ 1{{ textValue(selectedSparepart.purchaseUnitName) }}={{ textValue(selectedSparepart.purchaseUnitConvertQuantity) }}{{ stockUnitLabel(selectedSparepart) }}
+
+
+
+
+
+
+
+ 出库用途
+
+
+
+
+ 维修领用
+
+
+
+ 保养领用
+
+
+
+
+
+
+ 关联信息
+
+
+
+
+ 关联设备
+
+
+ {{ selectedDevice ? selectedDevice.label : '请选择' }}
+ ▼
+
+
+
+
+ {{ item.label }}
+ ✓
+
+ 暂无设备数据
+
+
+
+
+
+ {{ selectedPurpose === 'repair' ? '维修单号' : '保养单号' }}
+
+
+ {{ currentOrder ? currentOrder.label : '请选择' }}
+ ▼
+
+
+
+
+ {{ item.label }}
+ ✓
+
+ {{ selectedPurpose === 'repair' ? '暂无维修单' : '暂无保养单' }}
+
+
+
+
+
+
+
+
+
+
+
+ 出库数量
+
+
+
+ 出库数量
+
+ 单位:{{ textValue(selectedSparepart.purchaseUnitName) }}
+
+
+ 折算后库存数量:
+ {{ calculatedStock }}
+ {{ stockUnitLabel(selectedSparepart) }}
+
+
+ {{ outboundQty || 0 }}{{ textValue(selectedSparepart.purchaseUnitName) }} × {{ textValue(selectedSparepart.purchaseUnitConvertQuantity) }}{{ stockUnitLabel(selectedSparepart) }} = {{ calculatedStock }}{{ stockUnitLabel(selectedSparepart) }}
+
+
+
+
+
+
+ 经办人
+
+
+
+
+ {{ selectedOperator ? selectedOperator.label : '请选择经办人' }}
+
+ ▼
+
+
+
+
+ {{ item.label }}
+ ✓
+
+ 暂无数据
+
+
+
+
+
+
+
+
+ 请扫码或选择备件
+
+
+
+
+ 取消
+ 确认出库
+
+
+
+
+
+
+
diff --git a/src/pages_function/pages/sparepartOutbound/index.vue b/src/pages_function/pages/sparepartOutbound/index.vue
new file mode 100644
index 0000000..985b2a6
--- /dev/null
+++ b/src/pages_function/pages/sparepartOutbound/index.vue
@@ -0,0 +1,594 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ currentStatusLabel }}
+
+
+
+ {{ t('functionCommon.reset') }}
+
+
+
+
+
+
+
+
+
+ {{ t('sparepartOutbound.sparepartInfo') }}
+ {{ textValue(item.productNames) }}
+
+
+ {{ t('sparepartOutbound.outboundTime') }}
+ {{ formatDateTime(item.outTime || item.createTime) }}
+
+
+ {{ t('sparepartOutbound.creator') }}
+ {{ textValue(item.creatorName || item.creator) }}
+
+
+ {{ t('sparepartOutbound.quantity') }}
+ {{ textValue(item.totalCount) }}
+
+
+ {{ t('sparepartOutbound.reviewer') }}
+ {{ textValue(item.auditUserName) }}
+
+
+
+
+ {{ t('sparepartOutbound.approve') }}
+ {{ t('sparepartOutbound.reject') }}
+
+
+
+ {{ t('functionCommon.loading') }}
+ {{ t('sparepartOutbound.empty') }}
+ {{ t('functionCommon.loadingMore') }}
+ {{ t('functionCommon.noMoreData') }}
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
diff --git a/src/pages_mine/pages/setting/index.vue b/src/pages_mine/pages/setting/index.vue
index e749f95..503daab 100644
--- a/src/pages_mine/pages/setting/index.vue
+++ b/src/pages_mine/pages/setting/index.vue
@@ -178,7 +178,7 @@ function dialogClose() {
.server-address-text {
max-width: 400rpx;
- text-align: right;
+ // text-align: right;
word-break: break-all;
}
diff --git a/src/utils/permissionMenu.js b/src/utils/permissionMenu.js
index f61f7e5..885dbe5 100644
--- a/src/utils/permissionMenu.js
+++ b/src/utils/permissionMenu.js
@@ -1,3 +1,4 @@
+import { getCurrentLocale } from '@/locales'
const DIRECT_ROUTE_PREFIXES = ['pages/', 'page_', 'pages_']
@@ -87,6 +88,12 @@ const MENU_ROUTE_MAP = {
mold: '/pages_function/pages/mold/index',
equipment: '/pages_function/pages/equipment/index',
spare: '/pages_function/pages/spare/index',
+ sparepartInbound: '/pages_function/pages/sparepartInbound/index',
+ sparepartoutbound: '/pages_function/pages/sparepartOutbound/index',
+ '备件出库': '/pages_function/pages/sparepartOutbound/index',
+ sparepartinbound: '/pages_function/pages/sparepartInbound/index',
+ sparepartIn: '/pages_function/pages/sparepartInbound/index',
+ '备件入库': '/pages_function/pages/sparepartInbound/index',
keypart: '/pages_function/pages/keypart/index',
product: '/pages_function/pages/product/index'
}
@@ -185,7 +192,7 @@ export function getConfigurableNavMenus(menus) {
export function buildNavMenuViewModels(menus) {
return getConfigurableNavMenus(menus).map((menu, index) => {
- const displayName = String(menu.name || menu.enName || '').trim() || `菜单${index + 1}`
+ const displayName = getLocalizedMenuName(menu, `菜单${index + 1}`)
return {
...menu,
displayName,
@@ -305,7 +312,8 @@ export function resolveMenuUrl(menu) {
return directRoute
}
- const keys = [menu?.component, menu?.path, menu?.enName, menu?.name]
+ // 优先用 menu.name(中文,最不容易冲突),再用 component/path
+ const keys = [menu?.name, menu?.enName, menu?.component, menu?.path]
for (const key of keys) {
const normalizedKey = normalizeMenuKey(key)
if (normalizedKey && MENU_ROUTE_MAP[normalizedKey]) {
@@ -328,13 +336,22 @@ export function getMenuSymbol(name, index) {
return MENU_SYMBOLS[index % MENU_SYMBOLS.length]
}
+export function getLocalizedMenuName(menu, fallback = '') {
+ const name = String(menu?.name || '').trim()
+ const enName = String(menu?.enName || '').trim()
+ if (getCurrentLocale() === 'en-US') {
+ return enName || name || fallback
+ }
+ return name || enName || fallback
+}
+
export function syncTabBarMenus(menus, options = {}) {
const reportMenu = findTabMenuByPage(menus, 'pages/report')
const workMenu = findTabMenuByPage(menus, 'pages/work')
return [
options.homeText || '首页',
- reportMenu?.name || options.reportFallback || '报表',
- workMenu?.name || reportMenu?.name || options.workFallback || '管理',
+ getLocalizedMenuName(reportMenu, options.reportFallback || '报表'),
+ getLocalizedMenuName(workMenu, getLocalizedMenuName(reportMenu, options.workFallback || '管理')),
options.mineText || '我的'
]
}