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
@@ -56,7 +56,7 @@
</template>
<script setup>
import { ref } from 'vue'
import { ref, onMounted, onBeforeUnmount } from 'vue'
defineProps({
data: { type: Object, default: () => ({ title: '操作说明', overview: '', fields: [] }) }
@@ -64,6 +64,10 @@ defineProps({
const show = ref(false)
function open() { show.value = true }
// 右上角「帮助」按钮(MainLayout)通过 wms:open-page-help 事件触发当前页帮助抽屉
onMounted(() => window.addEventListener('wms:open-page-help', open))
onBeforeUnmount(() => window.removeEventListener('wms:open-page-help', open))
</script>
<style scoped>
@@ -12,6 +12,7 @@ const route = useRoute()
const router = useRouter()
const user = getUser()
const userName = computed(() => user?.realName || user?.username || '未登录')
const pageTitle = computed(() => route.meta?.title || '')
const menus = [
@@ -27,6 +28,19 @@ const menus = [
{ path: '/base-data', title: '基础数据', icon: EditPen }
]
// 打开当前页面帮助(各页面 PageHelp 监听 wms:open-page-help 事件弹出抽屉)
function openHelp() {
window.dispatchEvent(new CustomEvent('wms:open-page-help'))
}
function onUserCmd(cmd) {
if (cmd === 'password') {
router.push('/change-password')
} else if (cmd === 'logout') {
onLogout()
}
}
function onLogout() {
logout()
ElMessage.success('已退出登录')
@@ -57,8 +71,16 @@ function onLogout() {
<el-button text type="primary" @click="router.push('/display')">
<el-icon style="margin-right:4px"><Monitor /></el-icon>免登录大屏
</el-button>
<el-tag effect="plain">{{ user?.realName || user?.username || '未登录' }}</el-tag>
<el-button text type="danger" @click="onLogout">退出登录</el-button>
<el-button class="help-btn" text @click="openHelp">帮助</el-button>
<el-dropdown trigger="click" @command="onUserCmd">
<span class="user-name">{{ userName }} <span class="caret"></span></span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="password">修改密码</el-dropdown-item>
<el-dropdown-item divided command="logout">退出登录</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-header>
<el-main class="main">
<router-view />
@@ -83,5 +105,12 @@ function onLogout() {
}
.title { font-size: 16px; font-weight: 600; }
.spacer { flex: 1; }
.help-btn { font-size: 13px; color: #606266; }
.user-name {
display: inline-flex; align-items: center; gap: 4px; cursor: pointer;
font-size: 14px; color: #303133; outline: none; padding: 4px 6px; border-radius: 4px;
}
.user-name:hover { color: #1668dc; background: #f2f6fc; }
.caret { font-size: 10px; color: #909399; }
.main { background: #f0f2f5; padding: 14px; overflow: auto; }
</style>
@@ -0,0 +1,63 @@
<template>
<el-card style="max-width:480px;margin-top:20px">
<template #header><b>修改我的密码</b></template>
<el-alert type="warning" :closable="false" style="margin-bottom:16px"
title="密码修改成功后需重新登录" />
<el-form :model="form" label-width="100px" @submit.prevent>
<el-form-item label="旧密码">
<el-input v-model="form.oldPassword" type="password" show-password
placeholder="请输入当前密码" />
</el-form-item>
<el-form-item label="新密码">
<el-input v-model="form.newPassword" type="password" show-password
placeholder="至少 6 位" />
</el-form-item>
<el-form-item label="确认新密码">
<el-input v-model="form.confirmPassword" type="password" show-password
placeholder="请再次输入新密码" />
</el-form-item>
<el-form-item>
<el-button type="primary" :loading="loading" @click="submit">保存</el-button>
<el-button @click="reset">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</template>
<script setup>
import { reactive, ref } from 'vue'
import { ElMessage } from 'element-plus'
import { useRouter } from 'vue-router'
import { logout } from '../utils/auth'
import request from '../utils/request'
const router = useRouter()
const loading = ref(false)
const form = reactive({ oldPassword: '', newPassword: '', confirmPassword: '' })
async function submit() {
if (!form.oldPassword || !form.newPassword) return ElMessage.warning('请填写旧密码和新密码')
if (form.newPassword !== form.confirmPassword) return ElMessage.warning('两次输入的新密码不一致')
if (form.newPassword.length < 6) return ElMessage.warning('新密码长度至少 6 位')
loading.value = true
try {
await request.post('/user/change-password', {
oldPassword: form.oldPassword,
newPassword: form.newPassword
})
ElMessage.success('密码修改成功,请重新登录')
logout()
router.replace('/login')
} catch (e) {
/* 错误已由请求拦截器提示 */
} finally {
loading.value = false
}
}
function reset() {
form.oldPassword = ''
form.newPassword = ''
form.confirmPassword = ''
}
</script>
@@ -18,7 +18,8 @@ const routes = [
{ path: 'semi', name: 'Semi', component: () => import('../pages/Semi.vue'), meta: { title: '半成品/成品' } },
{ path: 'package', name: 'Package', component: () => import('../pages/Package.vue'), meta: { title: '包装绑定' } },
{ path: 'ledger', name: 'Ledger', component: () => import('../pages/Ledger.vue'), meta: { title: '备料台账' } },
{ path: 'base-data', name: 'BaseData', component: () => import('../pages/BaseData.vue'), meta: { title: '基础数据' } }
{ path: 'base-data', name: 'BaseData', component: () => import('../pages/BaseData.vue'), meta: { title: '基础数据' } },
{ path: 'change-password', name: 'ChangePassword', component: () => import('../pages/ChangePassword.vue'), meta: { title: '修改密码' } }
]
},
{ path: '/:pathMatch(.*)*', redirect: '/' }