feat: 完成产线MES系统全流程功能迭代与优化

本提交完成了多个核心模块的功能完善与业务对齐:
1. 工位终端:固定工位配置、移除自选工位逻辑、适配配置化工位号
2. MES核心:重构工位组合逻辑、新增工单/流程状态管理、补全报工/追溯逻辑
3. WMS客户端:新增修改密码功能、优化帮助弹窗逻辑
4. 文档与权限:补充完整操作手册、统一菜单名称与权限描述
5. 修复多业务校验:排产数量校验、工单状态校验、工位绑定规则
This commit is contained in:
SunYF
2026-08-31 12:58:28 +08:00
parent a3145a8bd6
commit ae4c292487
53 changed files with 1475 additions and 912 deletions
+1 -1
View File
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>北京动力 · 工位终端</title>
<title>工位终端</title>
</head>
<body>
<div id="app"></div>
@@ -27,16 +27,7 @@
</div>
<div class="field">
<span class="lab">工位</span>
<el-select
v-if="!fixedStation"
v-model="stationNo"
size="large"
class="station-el"
placeholder="请选择工位"
>
<el-option v-for="n in 12" :key="n" :label="'工位 ' + n" :value="n" />
</el-select>
<span v-else class="station-fixed">工位 {{ fixedStation }}</span>
<span class="station-fixed">{{ fixedStation ? '工位 ' + fixedStation : '工位加载中…' }}</span>
</div>
<el-button class="btn-login" type="primary" size="large" :loading="loading" @click="submit">
@@ -55,22 +46,20 @@ import { ElMessage } from 'element-plus'
import { getConfig, login } from '../api'
import { setAuth } from '../utils/request'
const STATION_KEY = 'ws_station_no'
const router = useRouter()
const username = ref('')
const password = ref('')
const stationNo = ref(null)
const fixedStation = ref(0)
const loading = ref(false)
// 工位由服务端配置文件固定(1~12),一个工位一个终端,终端不允许修改工位
onMounted(async () => {
try {
const cfg = await getConfig()
if (cfg?.stationNo > 0) fixedStation.value = cfg.stationNo
} catch {
// 网络异常时忽略,工位仍可自选
// 网络异常时保留 0,登录会提示配置未加载
}
stationNo.value = fixedStation.value || Number(localStorage.getItem(STATION_KEY)) || null
})
async function submit() {
@@ -78,9 +67,8 @@ async function submit() {
ElMessage.warning('请输入账号和密码')
return
}
const sn = fixedStation.value || stationNo.value
if (!sn) {
ElMessage.warning('请选择工位')
if (!fixedStation.value) {
ElMessage.warning('工位配置未加载,请检查服务端配置文件后重启')
return
}
loading.value = true
@@ -88,10 +76,9 @@ async function submit() {
const data = await login({
username: username.value,
password: password.value,
stationNo: sn
stationNo: fixedStation.value
})
setAuth(data.accessToken, data.user)
localStorage.setItem(STATION_KEY, String(sn))
ElMessage.success('登录成功')
router.push('/main')
} catch (e) {
@@ -4,15 +4,10 @@
<header class="top-bar">
<div class="brand">工位终端</div>
<div v-if="!fixedStation" class="dock-select">
<!-- 工位固定由服务端配置文件加载1~12终端不允许修改 -->
<div class="dock-select">
<span class="dock-lab">工位</span>
<el-select v-model="stationNo" size="large" class="dock-el">
<el-option v-for="n in 12" :key="n" :label="'工位 ' + n" :value="n" />
</el-select>
</div>
<div v-else class="dock-select">
<span class="dock-lab">工位</span>
<span class="dock-fixed">{{ fixedStation }}</span>
<span class="dock-fixed">{{ stationNo ? '工位 ' + stationNo : '…' }}</span>
</div>
<div class="spacer"></div>
@@ -169,9 +164,15 @@
<!-- 操作说明帮助 -->
<PageHelp :data="helpWorkstation" />
<!-- 我的工作量弹窗块6 -->
<el-dialog v-model="workload.show" title="我的工作量" width="720px" top="8vh">
<!-- 我的工作量弹窗块6当前登录人所有工位的工作默认当前工位可按工位/时间筛选 -->
<el-dialog v-model="workload.show" title="我的工作量" width="760px" top="8vh">
<el-form inline>
<el-form-item label="工位">
<el-select v-model="workload.stationNo" size="large" style="width:160px">
<el-option label="全部工位" :value="0" />
<el-option v-for="n in 12" :key="n" :label="'工位 ' + n" :value="n" />
</el-select>
</el-form-item>
<el-form-item label="日期范围">
<el-date-picker
v-model="workload.range"
@@ -192,6 +193,7 @@
<el-col :span="6"><el-card shadow="never" class="wl-stat"><div class="wl-label">总合格率</div><div class="wl-value">{{ workload.summary.rate }}</div></el-card></el-col>
</el-row>
<el-table :data="workload.rows" border size="small" max-height="360">
<el-table-column prop="stationNo" label="工位" width="90" align="center" />
<el-table-column prop="date" label="日期" width="110" />
<el-table-column prop="processCode" label="工序" width="80" align="center" />
<el-table-column prop="processName" label="工序名" min-width="130" show-overflow-tooltip />
@@ -209,7 +211,7 @@
</template>
<script setup>
import { computed, onBeforeUnmount, onMounted, reactive, ref, watch } from 'vue'
import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import PageHelp from '../components/PageHelp.vue'
@@ -227,30 +229,23 @@ import {
} from '../api'
import { clearAuth, getUser } from '../utils/request'
const STATION_KEY = 'ws_station_no'
const router = useRouter()
const user = getUser()
// ---------- 工位配置(固定工位号锁定,否则 1~12 自选,存 localStorage ----------
const fixedStation = ref(0)
const stationNo = ref(Number(localStorage.getItem(STATION_KEY)) || 1)
// ---------- 工位配置(固定工位号:由服务端 yaml 配置在启动时加载,终端不允许修改 ----------
const stationNo = ref(0)
const screwCount = ref(0)
async function loadConfig() {
try {
const cfg = await getConfig()
if (cfg?.stationNo > 0) fixedStation.value = cfg.stationNo
if (cfg?.stationNo > 0) stationNo.value = cfg.stationNo
if (cfg?.screwCount > 0) screwCount.value = cfg.screwCount
} catch {
/* 配置加载失败静默 */
}
}
watch(stationNo, (v) => {
localStorage.setItem(STATION_KEY, String(v))
refreshAll()
})
// ---------- 当前任务(MES ----------
const task = ref(null)
const flowName = computed(() => task.value?.flow?.name || '-')
@@ -534,15 +529,17 @@ async function manualFlush() {
}
}
// ---------- 我的工作量(块6 ----------
// ---------- 我的工作量(块6:当前登录人所有工位的工作,可筛工位(默认当前工位)/时间 ----------
const workload = reactive({
show: false,
stationNo: 0, // 0=全部工位;默认打开时设为当前工位
range: null,
rows: [],
summary: { doneCount: 0, okCount: 0, ngCount: 0, rate: '-' }
})
function openWorkload() {
if (!workload.stationNo) workload.stationNo = stationNo.value // 默认当前工位
workload.show = true
loadWorkload()
}
@@ -551,6 +548,7 @@ async function loadWorkload() {
const [from, to] = workload.range || []
const params = {
operator: user.name || user.username || '',
stationNo: workload.stationNo || 0, // 0=全部工位
from: from || '',
to: to || ''
}
@@ -591,7 +589,6 @@ function logout() {
onMounted(async () => {
await loadConfig()
if (fixedStation.value) stationNo.value = fixedStation.value
refreshAll()
focusScan()
window.addEventListener('focus', focusScan)