Pārlūkot izejas kodu

新增单独报工界面和打印功能

695593266@qq.com 11 mēneši atpakaļ
vecāks
revīzija
17e9d82f3b

+ 429 - 0
src/api/produce/bom.js

@@ -0,0 +1,429 @@
+import request from '@/utils/request';
+import { MessageBox, Message } from 'element-ui';
+// 分页
+export async function getPage(params) {
+  const res = await request.get(`/main/bom/page`, { params });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 保存
+export async function bomSave(data) {
+  const res = await request.post(`/main/bom/save`, data);
+  if (res.data.code == 0) {
+    return res.data.message;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 编辑
+export async function bomUpdate(data) {
+  const res = await request.put(`main/bom/update`, data);
+  if (res.data.code == 0) {
+    return res.data.message;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 详情
+export async function getById(id) {
+  const res = await request.get(`/main/bom/getById/${id}`);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+// 删除
+export async function bomDelete(data) {
+  const res = await request.delete(`/main/bom/delete`, { data });
+  if (res.data.code == 0) {
+    return res.data.message;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+// 详情分页
+export async function detailPage(params) {
+  const res = await request.get(`/main/bom/detail/page`, { params });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+//SAP-bom同步
+export async function syncBom() {
+  const res = await request.get(`/sap/sync/syncBom`);
+  if (res.data.code == 0) {
+    return res.data.code;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 物料BOM新增- 获取版本号
+export async function getVersionCode(categoryId) {
+  const res = await request.get(`/main/bom/getVersionCode/${categoryId}`);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 工序列表  保存
+
+export async function saveBatch(data) {
+  const res = await request.post(`/main/bomtask/saveBatch`, data);
+  if (res.data.code == 0) {
+    return res.data.message;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 工序列表
+
+export async function bomTaskList(categoryId) {
+  const res = await request.get(`/main/bomtask/list/${categoryId}`);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+//  bom工序信息 删除
+export async function bomTaskDelete(data) {
+  const res = await request.delete(`/main/bomtask/delete`, { data });
+  if (res.data.code == 0) {
+    return res.data.message;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 获取工序下的产品bom信息
+
+export async function getByTaskId(categoryId, taskId) {
+  const res = await request.get(
+    `main/category/getCategoryBomByTaskId/${categoryId}/${taskId}`
+  );
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 查询BOM树
+export async function getBomTreeList(params) {
+  const res = await request.get(`/main/bomCategory/getList`, { params });
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 查询BOM树 详情
+export async function getBomGetById(id) {
+  const res = await request.get(`/main/bomCategory/getById/${id}`);
+  if (res.data.code == 0) {
+    console.log(res.data, '+++++++++++++++++++++++');
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 查询BOM 版本
+export async function versionList(params) {
+  const res = await request.get(`/main/bomCategory/versionList`, { params });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 新增BOM树节点
+export async function saveBomTreeList(data) {
+  const res = await request.post(`/main/bomCategory/save`, data);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 删除BOM树节点
+export async function deleteBomTreeList(data) {
+  const res = await request.delete(`/main/bomCategory/delete`, { data });
+  if (res.data.code == 0) {
+    return res.data.message;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 保存BOM树节点
+export async function updateBatchBOM(data) {
+  const res = await request.post(`/main/bomCategory/updateBatchBOM`, data);
+  console.log(res, 'res111111111111111');
+  if (res && res.data.code == 0) {
+    return res.data;
+  } else {
+    Message.error({
+      message: res.data.message
+    });
+    return false;
+  }
+}
+
+// 获取产品BOM列表
+export async function getBomPageList(params) {
+  const res = await request.get(`/main/bomCategory/page`, { params });
+  if (res) {
+    if (res.data.code == 0) {
+      return res.data.data;
+    }
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 获取产品BOM列表
+export async function getBomPageCategoryId(params) {
+  const res = await request.get(`/main/bomCategory/pageByCategoryId`, {
+    params
+  });
+  if (res) {
+    if (res.data.code == 0) {
+      return res.data.data;
+    }
+  }
+
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 获取BOM明细
+export async function getBom(params) {
+  const res = await request.get(`/main/bomCategory/getBom`, { params });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 修改BOM属性
+export async function bomCategoryUpdate(data) {
+  const res = await request.post(`/main/bomCategory/update`, data);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// PBom转换 MBOM
+export async function convert(data) {
+  const res = await request.post(`/main/bomCategory/convert`, data);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// PBom转换 ABOM
+export async function convertABom(data) {
+  const res = await request.post(`/main/bomCategory/convertABom`, data);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+//PBom转换为EBom
+export async function convertEBOM(data) {
+  const res = await request.post(`/main/bomCategory/convertEBOM`, data);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// EBom转换为PBom
+export async function convertEBomToPBOM(data) {
+  const res = await request.post(`/main/bomCategory/convertEBomToPBOM`, data);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 文档
+export async function getBomFilePageList(params) {
+  const res = await request.get(`/main/bomfile/page`, { params });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 启用
+export async function startAndStop(data) {
+  const res = await request.post(`/main/bomCategory/startAndStop`, data);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 发布
+
+export async function bomSubmit(data) {
+  const res = await request.post(`/bpm/bom/submit`, data);
+  if (res && res.data.code == 0) {
+    return res.data;
+  }
+}
+
+// 嘉实医药提交
+export async function jsBomSubmit(data) {
+  const res = await request.post(`/bpm/jsbom/submit`, data);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 嘉实设备提交
+
+export async function deviceBomSubmit(data) {
+  const res = await request.post(`/bpm/jsbom/deviceSubmit`, data);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 新增工序
+export async function workingProcedureSave(data) {
+  const res = await request.post(`/main/categoryparam/save`, data);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 修改工序
+export async function workingProcedureUpdate(data) {
+  const res = await request.put(`/main/categoryparam/update`, data);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 修改工步
+export async function workingStepUpdate(data) {
+  const res = await request.post(`/main/categoryparamstep/update`, data);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 修改单个工步
+export async function workingSingleUpdate(data) {
+  const res = await request.put(`/main/categoryparamstep/updateStepItem`, data);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 获取工步详情
+export async function getStepDetailById(id) {
+  const res = await request.get(`/main/categoryparamstep/getById/${id}`);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 删除工步
+export async function workingStepDelete(data) {
+  const res = await request.delete(`/main/categoryparamstep/delete`, { data });
+  if (res.data.code == 0) {
+    return res.data.message;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 工序列表
+export async function getMbomPage(params) {
+  const res = await request.get(`/main/categoryparam/mBomPage`, { params });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 通过工序获取工步列表
+export async function getStepListById(params) {
+  const res = await request.get(`/main/categoryparamstep/list`, { params });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 保存工步
+export async function workingStepSave(data) {
+  const res = await request.post(`/main/categoryparamstep/save`, data);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 供应商列表
+export async function contactList(params) {
+  const res = await request.get(`/eom/contact/page`, { params });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+// 更新供应商
+export async function saveSupplier(data) {
+  const res = await request.post(`/eom/contactproduct/saveSupplier`, data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+// 删除供应商
+export async function deleteSupplier(data) {
+  const res = await request.post(`/eom/contactproduct/deleteSupplier`, data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+// 检查bom  (里面有几个草稿)
+
+export async function hasNewVersion(data) {
+  const res = await request.post(`/main/bomCategory/hasNewVersion`, data);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+export async function sourceBomVersion(data) {
+  const res = await request.post(`/main/bomCategory/sourceBomVersion`, data);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+//明细表
+export async function getDetailList(data) {
+  const res = await request.post(`/main/bomCategory/importByBOMDetail`, data);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}

+ 1 - 1
src/config/setting.js

@@ -21,7 +21,7 @@ export const SYSTEM_NAME = 'mes';
 export const REPEATABLE_TABS = [];
 
 // 不需要登录的路由
-export const WHITE_LIST = ['/login', '/forget'];
+export const WHITE_LIST = ['/login', '/forget', '/singleLogin'];
 
 // 开启 KeepAlive 后仍然不需要缓存的路由地址
 export const KEEP_ALIVE_EXCLUDES = [];

+ 9 - 3
src/layout/components/header-tools.vue

@@ -71,7 +71,11 @@
       </el-dropdown>
     </div>
     <!-- 主题设置 -->
-    <div class="ele-admin-header-tool-item" @click="openSetting">
+    <div
+      class="ele-admin-header-tool-item"
+      @click="openSetting"
+      v-if="type != '1'"
+    >
       <i class="el-icon-_more"></i>
     </div>
     <!-- 修改密码弹窗 -->
@@ -108,13 +112,15 @@
         currentUser: {
           currentGroupId: '',
           currentRoleId: ''
-        }
+        },
+        type: ''
       };
     },
     created() {
       this.currentUser = getCurrentUser();
       this.groupId = this.currentUser.currentGroupId;
       this.roleId = this.currentUser.currentRoleId;
+      this.type = localStorage.getItem('singleUserInfo');
     },
     computed: {
       // 当前用户信息
@@ -140,7 +146,7 @@
         this.roleId = val;
         this.currentUser.currentGroupId = this.groupId;
         this.currentUser.currentRoleId = val;
-        setCurrentUser(this.currentUser)
+        setCurrentUser(this.currentUser);
         this.$store
           .dispatch('user/fetchUserInfo')
           .then(({ menus, homePath, authoritiesRouter }) => {

+ 24 - 18
src/layout/index.vue

@@ -11,7 +11,7 @@
     :show-footer="theme.showFooter"
     :head-style="theme.headStyle"
     :side-style="theme.sideStyle"
-    :layout-style="theme.layoutStyle"
+    :layout-style="type == '1' ? 'top' : 'side'"
     :side-menu-style="theme.sideMenuStyle"
     :tab-style="theme.tabStyle"
     :fixed-header="theme.fixedHeader"
@@ -53,12 +53,10 @@
     <router-layout />
     <!-- logo 图标 -->
     <template v-slot:logo>
-      
       <el-image fit="contain" src="@/assets/logo.png" alt="logo" />
     </template>
     <!-- 顶栏右侧区域 -->
     <template v-slot:right>
-      
       <header-tools :fullscreen="fullscreen" @fullscreen="onFullscreen" />
     </template>
     <!-- 全局页脚 -->
@@ -123,7 +121,7 @@
       HeaderTools
       // PageFooter
     },
-    data () {
+    data() {
       return {
         PROJECT_NAME,
         HIDE_SIDEBARS,
@@ -134,50 +132,59 @@
         LAYOUT_PATH,
         REDIRECT_PATH,
         // 是否全屏
-        fullscreen: false
+        fullscreen: false,
+        type: ''
       };
     },
     computed: {
-      isQianKun () {
+      isQianKun() {
         return window.__POWERED_BY_QIANKUN__;
       },
       // 当前语言
-      locale () {
+      locale() {
         return this.$i18n.locale;
       },
       // 菜单数据
-      menus () {
+      menus() {
         return this.$store.state.user.menus;
       },
+
+      singleUserInfo() {
+        return this.$store.state.user.singleUserInfo;
+      },
       // 主题状态
       ...mapGetters(['theme'])
     },
+
+    mounted() {
+      this.type = localStorage.getItem('singleUserInfo');
+    },
+
     methods: {
       /* 侧栏折叠切换 */
-      updateCollapse (value) {
+      updateCollapse(value) {
         // console.log('value:', this.$store.state.user.menus);
         this.$store.dispatch('theme/setCollapse', value);
       },
       /* 双侧栏一级折叠切换 */
-      updateSideNavCollapse (value) {
+      updateSideNavCollapse(value) {
         this.$store.dispatch('theme/setSideNavCollapse', value);
       },
       /* 内容区域全屏切换 */
-      updateBodyFullscreen (value) {
+      updateBodyFullscreen(value) {
         this.$store.dispatch('theme/setBodyFullscreen', value);
       },
       /* logo 点击事件 */
-      onLogoClick (isHome) {
+      onLogoClick(isHome) {
         isHome || this.$router.push(LAYOUT_PATH);
       },
       /* 监听屏幕尺寸改变 */
-      screenSizeChange () {
+      screenSizeChange() {
         this.$store.dispatch('theme/updateScreenSize');
         this.fullscreen = isFullscreen();
-
       },
       /* 全屏切换 */
-      onFullscreen () {
+      onFullscreen() {
         try {
           this.fullscreen = toggleFullscreen();
         } catch (e) {
@@ -185,7 +192,7 @@
         }
       },
       /* 页签右键菜单点击事件 */
-      onTabContextMenu ({ key, tabKey, item, active }) {
+      onTabContextMenu({ key, tabKey, item, active }) {
         switch (key) {
           case 'reload': // 刷新
             reloadPageTab({
@@ -220,7 +227,7 @@
         }
       },
       /* 菜单标题国际化 */
-      i18n (_path, key) {
+      i18n(_path, key) {
         if (!I18N_ENABLE || !key) {
           return;
         }
@@ -345,5 +352,4 @@
       }
     }
   }
-
 </style>

+ 12 - 12
src/router/index.js

@@ -6,8 +6,7 @@ import NProgress from 'nprogress';
 import VueRouter from 'vue-router';
 import { WHITE_LIST, REDIRECT_PATH, LAYOUT_PATH } from '@/config/setting';
 import store from '@/store';
-import { getToken, setToken, getCurrentUser  } from '@/utils/token-util';
-
+import { getToken, setToken, getCurrentUser } from '@/utils/token-util';
 
 import { routes, getMenuRoutes } from './routes';
 
@@ -20,7 +19,7 @@ const router = new VueRouter({
   base: window.__POWERED_BY_QIANKUN__ ? '/page-mes/' : '/mes/',
   routes,
   mode: 'history',
-  scrollBehavior () {
+  scrollBehavior() {
     return { y: 0 };
   }
 });
@@ -88,20 +87,21 @@ router.afterEach((to) => {
   }
 });
 router.roleChange = async ({ menus, homePath, authoritiesRouter }) => {
-  const currentUser = getCurrentUser()
+  const currentUser = getCurrentUser();
   if (menus && menus.length > 0) {
-    router.addRoute(
-      getMenuRoutes([...menus, ...authoritiesRouter], homePath)
-    );
+    router.addRoute(getMenuRoutes([...menus, ...authoritiesRouter], homePath));
     if (router.currentRoute.path != (menus[0].redirect || menus[0].path)) {
       await router.replace({
-        path: menus[0].redirect || menus[0].path,
-      })
+        path: menus[0].redirect || menus[0].path
+      });
     }
-    const newToken = await changeRole({ groupId: currentUser.currentGroupId, roleId: currentUser.currentRoleId })
-    setToken(newToken)
+    const newToken = await changeRole({
+      groupId: currentUser.currentGroupId,
+      roleId: currentUser.currentRoleId
+    });
+    setToken(newToken);
     setTimeout(() => {
-      window.location.reload()
+      window.location.reload();
     }, 100);
   }
 

+ 10 - 0
src/router/routes.js

@@ -17,6 +17,16 @@ export const routes = [
     path: '/forget',
     component: () => import('@/views/forget/index.vue'),
     meta: { title: '忘记密码' }
+  },
+  {
+    path: '/singleLogin',
+    component: () => import('@/views/singleLogin/index.vue'),
+    meta: { title: '登录' }
+  },
+  {
+    path: '/print',
+    component: () => import('@/views/produceOrder/print.vue'),
+    meta: { title: '工艺流程卡' }
   }
   // 404
   // {

+ 50 - 25
src/utils/page-tab-util.js

@@ -4,7 +4,7 @@
 import store from '@/store';
 import router from '@/router';
 import { Message } from 'element-ui';
-import { removeToken,removeCurrentUser } from '@/utils/token-util';
+import { removeToken, removeCurrentUser } from '@/utils/token-util';
 import { setDocumentTitle } from '@/utils/document-title-util';
 import { SYSTEM_NAME } from '@/config/setting';
 import {
@@ -19,7 +19,7 @@ const BASE_URL = process.env.BASE_URL;
 /**
  * 刷新当前路由
  */
-export function reloadPageTab (option) {
+export function reloadPageTab(option) {
   if (!option) {
     // 刷新当前路由
     const { path, fullPath, query } = router.currentRoute;
@@ -50,7 +50,7 @@ export function reloadPageTab (option) {
 /**
  * 关闭当前页签
  */
-export function finishPageTab () {
+export function finishPageTab() {
   const key = getRouteTabKey();
   removePageTab({ key, active: key });
 }
@@ -60,7 +60,7 @@ export function finishPageTab () {
  * @param key 页签的key
  * @param active 选中页签的key
  */
-export function removePageTab (option) {
+export function removePageTab(option) {
   store
     .dispatch('theme/tabRemove', option)
     .then(({ path, home }) => {
@@ -78,7 +78,7 @@ export function removePageTab (option) {
 /**
  * 关闭左侧页签
  */
-export function removeLeftPageTab (option) {
+export function removeLeftPageTab(option) {
   store
     .dispatch('theme/tabRemoveLeft', option)
     .then(({ path }) => {
@@ -94,7 +94,7 @@ export function removeLeftPageTab (option) {
 /**
  * 关闭右侧页签
  */
-export function removeRightPageTab (option) {
+export function removeRightPageTab(option) {
   store
     .dispatch('theme/tabRemoveRight', option)
     .then(({ path, home }) => {
@@ -112,7 +112,7 @@ export function removeRightPageTab (option) {
 /**
  * 关闭其它页签
  */
-export function removeOtherPageTab (option) {
+export function removeOtherPageTab(option) {
   store
     .dispatch('theme/tabRemoveOther', option)
     .then(({ path, home }) => {
@@ -131,7 +131,7 @@ export function removeOtherPageTab (option) {
  * 关闭全部页签
  * @param active 当前选中页签
  */
-export function removeAllPageTab (active) {
+export function removeAllPageTab(active) {
   store
     .dispatch('theme/tabRemoveAll', active)
     .then(({ home }) => {
@@ -147,7 +147,7 @@ export function removeAllPageTab (active) {
 /**
  * 登录成功后清空页签
  */
-export function cleanPageTabs () {
+export function cleanPageTabs() {
   store.dispatch('theme/setTabs', []);
 }
 
@@ -155,7 +155,7 @@ export function cleanPageTabs () {
  * 添加页签
  * @param data 页签数据
  */
-export function addPageTab (data) {
+export function addPageTab(data) {
   store.dispatch('theme/tabAdd', data);
 }
 
@@ -163,7 +163,7 @@ export function addPageTab (data) {
  * 修改页签
  * @param data 页签数据
  */
-export function setPageTab (data) {
+export function setPageTab(data) {
   store.dispatch('theme/tabSetItem', data);
 }
 
@@ -171,7 +171,7 @@ export function setPageTab (data) {
  * 更新页签数据
  * @param data 页签数据
  */
-export function setPageTabs (data) {
+export function setPageTabs(data) {
   store.dispatch('theme/setTabs', data);
 }
 
@@ -179,7 +179,7 @@ export function setPageTabs (data) {
  * 修改页签标题
  * @param title 标题
  */
-export function setPageTabTitle (title) {
+export function setPageTabTitle(title) {
   setPageTab({ key: getRouteTabKey(), title });
   setDocumentTitle(title);
 }
@@ -187,7 +187,7 @@ export function setPageTabTitle (title) {
 /**
  * 获取当前路由对应的页签 key
  */
-export function getRouteTabKey () {
+export function getRouteTabKey() {
   const { path, fullPath, meta } = router.currentRoute;
   const isUnique = meta.tabUnique === false || REPEATABLE_TABS.includes(path);
   return `${window.__POWERED_BY_QIANKUN__ ? '/page-' + SYSTEM_NAME : ''}${
@@ -199,7 +199,7 @@ export function getRouteTabKey () {
  * 设置主页的组件名称
  * @param components 组件名称
  */
-export function setHomeComponents (components) {
+export function setHomeComponents(components) {
   store.dispatch('theme/setHomeComponents', components);
 }
 
@@ -207,7 +207,7 @@ export function setHomeComponents (components) {
  * 设置路由刷新信息
  * @param option 路由刷新参数
  */
-export function setRouteReload (option) {
+export function setRouteReload(option) {
   return store.dispatch('theme/setRouteReload', option);
 }
 
@@ -215,7 +215,7 @@ export function setRouteReload (option) {
  * 判断路由是否是主页
  * @param route 路由信息
  */
-export function isHomeRoute (route) {
+export function isHomeRoute(route) {
   const { path, matched } = route;
   if (HOME_ROUTE === path) {
     return true;
@@ -231,7 +231,7 @@ export function isHomeRoute (route) {
  * 登录成功后跳转首页
  * @param from 登录前的地址
  */
-export function goHomeRoute (from) {
+export function goHomeRoute(from) {
   router.replace(from || HOME_ROUTE);
 }
 
@@ -240,16 +240,41 @@ export function goHomeRoute (from) {
  * @param from 是否使用路由跳转
  * @param from 登录后跳转的地址
  */
-export function logout (route, from) {
+export function logout(route, from) {
   removeToken();
   removeCurrentUser();
+
   if (route) {
-    router.push({
-      path: '/login',
-      query: from ? { from } : void 0
-    });
+    if (localStorage.getItem('singleUserInfo') == '1') {
+      router.push({
+        path: '/singleLogin',
+        query: from ? { from } : void 0
+      });
+    } else {
+      router.push({
+        path: '/login',
+        query: from ? { from } : void 0
+      });
+    }
   } else {
-    // 这样跳转避免再次登录重复注册动态路由
-    location.replace(BASE_URL + 'login' + (from ? '?from=' + from : ''));
+    if (localStorage.getItem('singleUserInfo') == '1') {
+      location.replace(
+        BASE_URL + 'singleLogin' + (from ? '?from=' + from : '')
+      );
+    } else {
+      location.replace(BASE_URL + 'login' + (from ? '?from=' + from : ''));
+    }
   }
+
+  localStorage.removeItem('singleUserInfo');
+
+  // if (route) {
+  //   router.push({
+  //     path: '/login',
+  //     query: from ? { from } : void 0
+  //   });
+  // } else {
+  // 这样跳转避免再次登录重复注册动态路由
+  //   location.replace(BASE_URL + 'login' + (from ? '?from=' + from : ''));
+  // }
 }

+ 7 - 0
src/views/produce/components/bom/index.vue

@@ -0,0 +1,7 @@
+<template> </template>
+
+<script>
+  export default {};
+</script>
+
+<style></style>

+ 0 - 2
src/views/produce/components/jobBooking/components/jobBom.vue

@@ -144,8 +144,6 @@
           </div>
         </div>
 
-        {{ clientEnvironmentId }} -{{}}
-
         <div
           class="btn-margin"
           v-if="

+ 1 - 1
src/views/produce/components/jobBooking/details.vue

@@ -206,7 +206,7 @@
           >
             <detailsIndex
               :code="objData.code"
-              :taskId="objData.currentTaskDiagram.taskId"
+              :taskId="objData.currentTaskDiagram.sourceTaskId"
             >
             </detailsIndex>
           </div>

+ 9 - 0
src/views/produceOrder/index.vue

@@ -2,6 +2,7 @@
   <div class="ele-body">
     <el-card shadow="never" v-loading="loading">
       <seek-page :seekList="seekList" @search="search"></seek-page>
+      <!-- <button @click="btnPrint">打印</button> -->
 
       <!-- <produceOrder-search @search="reload" ref="searchRef" :statusOpt="statusOpt" :planType="planType"
         :activeName="activeName">
@@ -773,6 +774,14 @@
         return obj && obj.label;
       },
 
+      btnPrint() {
+        const url = this.$router.resolve({ path: '/print' }).href; // 获取目标URL路径的完整URL字符串
+        window.open(url, '_blank');
+        // this.$router.push({
+        //   path: '/print'
+        // });
+      },
+
       routing(row) {
         this.id = row.id;
 

+ 226 - 0
src/views/produceOrder/print.vue

@@ -0,0 +1,226 @@
+<template>
+  <div class="print-root">
+    <div class="card-title">工艺流程卡</div>
+    <table class="info-table">
+      <tr>
+        <td rowspan="3" class="qr-cell">
+          <img :src="card.qrLeft" alt="二维码" />
+        </td>
+        <td>单号</td>
+        <td>{{ card.orderNo }}</td>
+        <td>单据日期</td>
+        <td>{{ card.date }}</td>
+        <td rowspan="3" class="qr-cell">
+          <img :src="card.qrRight" alt="二维码" />
+        </td>
+      </tr>
+      <tr>
+        <td>编号</td>
+        <td>{{ card.code }}</td>
+        <td>存货名称</td>
+        <td>{{ card.name }}</td>
+      </tr>
+      <tr>
+        <td>图号</td>
+        <td>{{ card.drawingNo }}</td>
+        <td colspan="2"></td>
+      </tr>
+    </table>
+
+    <table class="process-table">
+      <thead>
+        <tr>
+          <th rowspan="2">工序</th>
+          <th colspan="4">数量</th>
+          <th rowspan="2">品质验收</th>
+          <th rowspan="2">交接签字</th>
+          <th rowspan="2">备注</th>
+        </tr>
+        <tr>
+          <th>加工</th>
+          <th>发料</th>
+          <th>合格</th>
+          <th>报废</th>
+        </tr>
+      </thead>
+      <tbody>
+        <tr v-for="(row, idx) in card.process" :key="idx">
+          <td>{{ row.name }}</td>
+          <td>{{ row.make }}</td>
+          <td>{{ row.send }}</td>
+          <td>{{ row.pass }}</td>
+          <td>{{ row.scrap }}</td>
+          <td>{{ row.qc }}</td>
+          <td>{{ row.sign }}</td>
+          <td>{{ row.remark }}</td>
+        </tr>
+      </tbody>
+    </table>
+
+    <div class="footer-info">
+      <div>制单人:{{ card.creator }}</div>
+      <div>审核人:{{ card.auditor }}</div>
+      <!-- <div style="flex: 1; text-align: right">
+          第{{ card.page }}页 共{{ card.totalPages }}页
+        </div> -->
+    </div>
+
+    <!-- 打印按钮 -->
+    <!-- <div class="no-print" style="margin-top: 10px">
+      <button @click="doPrint">打印</button>
+    </div> -->
+  </div>
+</template>
+
+<script>
+  export default {
+    name: 'print-dialog',
+
+    data() {
+      return {
+        card: {
+          qrLeft:
+            'https://api.qrserver.com/v1/create-qr-code/?size=80x80&data=左二维码',
+          qrRight:
+            'https://api.qrserver.com/v1/create-qr-code/?size=80x80&data=右二维码',
+          orderNo: 'ZHD2025076835',
+          date: '2025/07/21',
+          code: '13650042',
+          name: '射灯安装座 HZS120GT.3',
+          drawingNo: '516',
+          process: [
+            {
+              name: '抛丸',
+              make: 30,
+              send: '',
+              pass: '',
+              scrap: '',
+              qc: '',
+              sign: '',
+              remark: ''
+            },
+            {
+              name: '三维光割',
+              make: 30,
+              send: '',
+              pass: 30,
+              scrap: '',
+              qc: '',
+              sign: '',
+              remark: ''
+            },
+            {
+              name: '喷粉',
+              make: 30,
+              send: '',
+              pass: '',
+              scrap: '',
+              qc: '',
+              sign: '签名',
+              remark: '深灰色(RAL7011)'
+            }
+          ],
+          creator: '李敦',
+          auditor: '李敦',
+          page: 6,
+          totalPages: 14
+        }
+      };
+    },
+
+    mounted() {
+      this.doPrint();
+    },
+
+    methods: {
+      doPrint() {
+        this.$nextTick(() => {
+          window.print();
+        });
+      }
+    }
+  };
+</script>
+
+<style scoped>
+  .print-root {
+    font-family: 'Microsoft Yahei', Arial, sans-serif;
+    font-size: 12px;
+    background: #fff;
+    padding: 10px;
+    margin: 40px;
+  }
+
+  .card-title {
+    text-align: center;
+    font-size: 16px;
+    font-weight: bold;
+    margin: 5px 0;
+  }
+
+  .info-table {
+    width: 100%;
+    border-collapse: collapse;
+    margin-bottom: 6px;
+  }
+
+  .info-table td {
+    border: 1px solid #000;
+    padding: 3px 5px;
+    vertical-align: middle;
+  }
+
+  .qr-cell {
+    text-align: center;
+    width: 90px;
+    height: 120px;
+  }
+  .qr-cell img {
+    width: 80px;
+    height: 80px;
+  }
+
+  .process-table {
+    width: 100%;
+    border-collapse: collapse;
+    margin-bottom: 8px;
+  }
+  .process-table th,
+  .process-table td {
+    border: 1px solid #000;
+    padding: 3px;
+    text-align: center;
+  }
+  .process-table thead th {
+    font-weight: bold;
+  }
+
+  .footer-info {
+    display: flex;
+    justify-content: space-between;
+    font-size: 12px;
+  }
+
+  .no-print {
+    display: block;
+  }
+
+  /* 打印优化 */
+  @page {
+    size: A4;
+    margin: 12mm;
+  }
+
+  @media print {
+    .no-print {
+      display: none !important;
+    }
+    * {
+      -webkit-print-color-adjust: exact;
+      print-color-adjust: exact;
+    }
+    .print-root {
+      padding: 0;
+    }
+  }
+</style>

+ 407 - 0
src/views/singleLogin/index.vue

@@ -0,0 +1,407 @@
+<template>
+  <div
+    :class="[
+      'login-wrapper',
+      ['', 'login-form-right', 'login-form-left'][direction]
+    ]"
+  >
+    <el-form
+      ref="form"
+      size="large"
+      :model="form"
+      :rules="rules"
+      class="login-form ele-bg-white"
+      @keyup.enter.native="submit"
+    >
+      <h4>{{ $t('login.title') }}</h4>
+      <el-form-item prop="loginName">
+        <el-input
+          clearable
+          v-model="form.loginName"
+          prefix-icon="el-icon-user"
+          :placeholder="$t('login.loginName')"
+          @blur="getUserData"
+        />
+      </el-form-item>
+      <el-form-item prop="loginPwd">
+        <el-input
+          show-password
+          v-model="form.loginPwd"
+          prefix-icon="el-icon-lock"
+          :placeholder="$t('login.loginPwd')"
+        />
+      </el-form-item>
+
+      <el-form-item prop="loginPwd">
+        <el-input
+          show-password
+          v-model="form.factory"
+          disabled
+          placeholder="所属工厂"
+        />
+      </el-form-item>
+
+      <el-form-item prop="loginPwd">
+        <el-input
+          show-password
+          v-model="form.workCenter"
+          disabled
+          placeholder="所属工作中心"
+        />
+      </el-form-item>
+      <el-form-item prop="loginPwd">
+        <el-input
+          show-password
+          v-model="form.team"
+          disabled
+          placeholder="所属班组"
+        />
+      </el-form-item>
+      <el-form-item prop="loginPwd">
+        <el-input
+          show-password
+          v-model="form.desk"
+          disabled
+          placeholder="工位"
+        />
+      </el-form-item>
+
+      <el-form-item prop="loginPwd">
+        <el-input
+          show-password
+          v-model="form.device"
+          disabled
+          placeholder="设备"
+        />
+      </el-form-item>
+
+      <div class="el-form-item">
+        <el-checkbox v-model="form.remember">
+          {{ $t('login.remember') }}
+        </el-checkbox>
+        <el-link
+          type="primary"
+          :underline="false"
+          class="ele-pull-right"
+          @click="$router.push('/forget')"
+        >
+          忘记密码
+        </el-link>
+      </div>
+      <div class="el-form-item">
+        <el-button
+          size="large"
+          type="primary"
+          class="login-btn"
+          :loading="loading"
+          @click="submit"
+        >
+          {{ loading ? $t('login.loading') : $t('login.login') }}
+        </el-button>
+      </div>
+      <div class="ele-text-center" style="margin-bottom: 10px">
+        <i class="login-oauth-icon el-icon-_qq" style="background: #3492ed"></i>
+        <i
+          class="login-oauth-icon el-icon-_wechat"
+          style="background: #4daf29"
+        ></i>
+        <i
+          class="login-oauth-icon el-icon-_weibo"
+          style="background: #cf1900"
+        ></i>
+      </div>
+    </el-form>
+    <div class="login-copyright">
+      copyright © 2022 eleadmin.com all rights reserved.
+    </div>
+    <!-- 多语言切换 -->
+    <div style="position: absolute; right: 30px; top: 20px">
+      <i18n-icon
+        :icon-style="{ fontSize: '22px', color: '#fff', cursor: 'pointer' }"
+      />
+    </div>
+    <!-- 实际项目去掉这段 -->
+    <!-- <div
+      class="hidden-xs-only"
+      style="position: absolute; right: 30px; bottom: 20px; z-index: 9"
+    >
+      <el-radio-group v-model="direction" size="mini">
+        <el-radio-button label="2">居左</el-radio-button>
+        <el-radio-button label="0">居中</el-radio-button>
+        <el-radio-button label="1">居右</el-radio-button>
+      </el-radio-group>
+    </div> -->
+  </div>
+</template>
+
+<script>
+  import I18nIcon from '@/layout/components/i18n-icon.vue';
+  import { getToken } from '@/utils/token-util';
+  import { login, getCaptcha, getLoginUser } from '@/api/login';
+  import { setCurrentUser } from '@/utils/token-util';
+  import { getUser } from '@/api/system/user';
+
+  export default {
+    // eslint-disable-next-line vue/multi-word-component-names
+    name: 'Login',
+    components: { I18nIcon },
+    data() {
+      return {
+        // 登录框方向, 0居中, 1居右, 2居左
+        direction: 1,
+        // 加载状态
+        loading: false,
+        // 表单数据
+        form: {
+          loginName: 'mes111',
+          loginPwd: '123456',
+          remember: true,
+          factory: '',
+          device: '',
+          team: '',
+          workCenter: '',
+          desk: ''
+        },
+        // 验证码base64数据
+        captcha: '',
+        // 验证码内容, 实际项目去掉
+        text: ''
+      };
+    },
+    computed: {
+      // 表单验证规则
+      rules() {
+        return {
+          loginName: [
+            {
+              required: true,
+              message: this.$t('login.loginName'),
+              type: 'string',
+              trigger: 'blur'
+            }
+          ],
+          loginPwd: [
+            {
+              required: true,
+              message: this.$t('login.loginPwd'),
+              type: 'string',
+              trigger: 'blur'
+            }
+          ]
+        };
+      }
+    },
+    created() {
+      if (getToken()) {
+        this.goHome();
+      } else {
+        // 重置菜单权限
+        this.$store.commit('user/setMenus', null);
+      }
+    },
+    methods: {
+      getUserData() {
+        console.log(111111111111);
+      },
+
+      /* 提交 */
+      submit() {
+        this.$refs.form.validate((valid) => {
+          if (!valid) {
+            return false;
+          }
+          this.loading = true;
+          login(this.form)
+            .then((res) => {
+              localStorage.setItem('userId', res.data.userId);
+              // 用户信息
+              if (res.data?.loginChangeGroupVOList.length > 0) {
+                setCurrentUser(
+                  {
+                    currentGroupId: res.data.loginChangeGroupVOList[0].groupId,
+                    currentRoleId:
+                      res.data.loginChangeGroupVOList[0]
+                        .loginChangeRoleVOList[0].roleId
+                  },
+                  this.form.remember
+                );
+              }
+              this.$store.commit('user/setUserInfo', res.data);
+              this.loading = false;
+              this.$message.success(res.message);
+              this.$store.dispatch('user/getCurrentUserAuthorityDept');
+              this.goHome();
+            })
+            .catch((e) => {
+              this.loading = false;
+              // this.$message.error(e.message);
+            });
+        });
+      },
+      /* 跳转到首页 */
+      goHome() {
+        // this.$store.commit('user/singleUserInfo', "1");
+        localStorage.setItem('singleUserInfo', '1');
+        this.$router.push(this.$route?.query?.from ?? '/').catch(() => {});
+      },
+      /* 更换图形验证码 */
+      changeCaptcha() {
+        // 这里演示的验证码是后端返回base64格式的形式, 如果后端地址直接是图片请参考忘记密码页面
+        getCaptcha()
+          .then((data) => {
+            this.captcha = data.base64;
+            // 实际项目后端一般会返回验证码的key而不是直接返回验证码的内容, 登录用key去验证, 可以根据自己后端接口修改
+            this.text = data.text;
+            // 自动回填验证码, 实际项目去掉这个
+            this.form.code = this.text;
+            this.$refs?.form?.clearValidate();
+          })
+          .catch((e) => {
+            // this.$message.error(e.message);
+          });
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  /* 背景 */
+  .login-wrapper {
+    padding: 50px 20px;
+    position: relative;
+    box-sizing: border-box;
+    background-image: url('@/assets/bg-login.jpg');
+    background-repeat: no-repeat;
+    background-size: cover;
+    min-height: 100vh;
+
+    &:before {
+      content: '';
+      background-color: rgba(0, 0, 0, 0.2);
+      position: absolute;
+      top: 0;
+      left: 0;
+      right: 0;
+      bottom: 0;
+    }
+  }
+
+  /* 卡片 */
+  .login-form {
+    margin: 0 auto;
+    width: 360px;
+    max-width: 100%;
+    padding: 25px 30px;
+    position: relative;
+    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15);
+    box-sizing: border-box;
+    border-radius: 4px;
+    z-index: 2;
+
+    h4 {
+      text-align: center;
+      margin: 0 0 25px 0;
+    }
+
+    & > .el-form-item {
+      margin-bottom: 25px;
+    }
+  }
+
+  .login-form-right .login-form {
+    margin: 0 15% 0 auto;
+  }
+
+  .login-form-left .login-form {
+    margin: 0 auto 0 15%;
+  }
+
+  /* 验证码 */
+  .login-input-group {
+    display: flex;
+    align-items: center;
+
+    :deep(.el-input) {
+      flex: 1;
+    }
+  }
+
+  .login-captcha {
+    height: 38px;
+    width: 102px;
+    margin-left: 10px;
+    border-radius: 4px;
+    border: 1px solid #dcdfe6;
+    text-align: center;
+    cursor: pointer;
+
+    &:hover {
+      opacity: 0.75;
+    }
+  }
+
+  .login-btn {
+    display: block;
+    width: 100%;
+  }
+
+  /* 第三方登录图标 */
+  .login-oauth-icon {
+    color: #fff;
+    padding: 5px;
+    margin: 0 10px;
+    font-size: 18px;
+    border-radius: 50%;
+    cursor: pointer;
+  }
+
+  /* 底部版权 */
+  .login-copyright {
+    color: #eee;
+    padding-top: 20px;
+    text-align: center;
+    position: relative;
+    z-index: 1;
+  }
+
+  /* 响应式 */
+  @media screen and (min-height: 550px) {
+    .login-form {
+      position: absolute;
+      top: 30%;
+      left: 50%;
+      transform: translateX(-50%);
+      margin-top: -220px;
+    }
+
+    .login-form-right .login-form,
+    .login-form-left .login-form {
+      left: auto;
+      right: 15%;
+      transform: translateX(0);
+      margin: -220px auto auto auto;
+    }
+
+    .login-form-left .login-form {
+      right: auto;
+      left: 15%;
+    }
+
+    .login-copyright {
+      position: absolute;
+      bottom: 20px;
+      right: 0;
+      left: 0;
+    }
+  }
+
+  @media screen and (max-width: 768px) {
+    .login-form-right .login-form,
+    .login-form-left .login-form {
+      left: 50%;
+      right: auto;
+      transform: translateX(-50%);
+      margin-right: auto;
+    }
+  }
+</style>