Browse Source

Merge remote-tracking branch 'origin/xf_dev' into xf_dev

# Conflicts:
#	src/views/system/user/index.vue
lupeng 10 tháng trước cách đây
mục cha
commit
497a1ee4d3
33 tập tin đã thay đổi với 642 bổ sung183 xóa
  1. 0 4
      .env.development
  2. 1 0
      package.json
  3. BIN
      src/assets/images/screen_bg_capacity.png
  4. BIN
      src/assets/images/screen_bg_quality.png
  5. BIN
      src/assets/images/screen_bg_task.png
  6. BIN
      src/assets/images/screen_header1.png
  7. 3 0
      src/common/configs/buttonPermission.ts
  8. 1 4
      src/directive/permission/index.ts
  9. 4 0
      src/plugins/icons.ts
  10. 17 0
      src/router/index.ts
  11. 3 0
      src/styles/index.scss
  12. 2 0
      src/styles/variables.scss
  13. 13 4
      src/views/base/craftManagement/route/index.vue
  14. 15 2
      src/views/device/allocate/index.vue
  15. 10 1
      src/views/device/instance/index.vue
  16. 1 0
      src/views/device/maintenance/index.vue
  17. 1 0
      src/views/device/metering/index.vue
  18. 1 1
      src/views/pro/traceability/components/checkCom.vue
  19. 1 1
      src/views/pro/traceability/components/equitCom.vue
  20. 1 1
      src/views/pro/traceability/components/faultCom.vue
  21. 1 1
      src/views/pro/traceability/components/materialsCom.vue
  22. 1 1
      src/views/pro/traceability/components/mediaCom.vue
  23. 1 1
      src/views/pro/traceability/components/recordCom.vue
  24. 1 1
      src/views/quality/faultHandle/components/fault-page.vue
  25. 107 0
      src/views/quality/reverseTraceability/index.vue
  26. 27 0
      src/views/report/statistics/screens/capacity/index.vue
  27. 29 0
      src/views/report/statistics/screens/common-header.vue
  28. 31 0
      src/views/report/statistics/screens/quality/index.vue
  29. 128 0
      src/views/report/statistics/screens/tasks/index.vue
  30. 91 0
      src/views/report/statistics/screens/titleHeader.vue
  31. 87 83
      src/views/system/menu/index.vue
  32. 1 0
      src/views/system/user/components/dept-tree.vue
  33. 63 78
      src/views/system/user/index.vue

+ 0 - 4
.env.development

@@ -10,10 +10,6 @@ VITE_APP_BASE_API = '/dev-api'
 # 上传文件接口地址
 VITE_APP_UPLOAD_URL = 'http://192.168.101.4:9000'
 # 开发接口地址
-# VITE_APP_API_URL = 'http://192.168.101.4:8078'
 VITE_APP_API_URL = 'http://192.168.101.4:8078'
-#  VITE_APP_API_URL = 'http://121.41.179.41:8078'  #lup
-#VITE_APP_API_URL = 'http://192.168.101.64:8078'  #hetao
-
 # 是否启用 Mock 服务
 VITE_MOCK_DEV_SERVER = false

+ 1 - 0
package.json

@@ -41,6 +41,7 @@
   },
   "dependencies": {
     "@element-plus/icons-vue": "^2.3.1",
+    "@kjgl77/datav-vue3": "^1.7.3",
     "@smallwei/avue": "^3.3.3",
     "@types/smallwei__avue": "^3.0.5",
     "@vueup/vue-quill": "1.0.0-alpha.40",

BIN
src/assets/images/screen_bg_capacity.png


BIN
src/assets/images/screen_bg_quality.png


BIN
src/assets/images/screen_bg_task.png


BIN
src/assets/images/screen_header1.png


+ 3 - 0
src/common/configs/buttonPermission.ts

@@ -68,6 +68,9 @@ const ButtonPermKeys = {
       maintenance: "device:maintenance",
     },
     BTNS: {
+      instance_add: "device:instance:add",
+      instance_del: "device:instance:del",
+      instance_edit: "device:instance:edit",
       maintenance_add: "device:maintenance:add",
       maintenance_handle: "device:maintenance:handle",
       maintenance_edit: "device:maintenance:edit",

+ 1 - 4
src/directive/permission/index.ts

@@ -37,10 +37,7 @@ export function checkPerm(str: string) {
   if (roles.includes("ROOT")) {
     return true;
   }
-  const hasPerm = perms?.some((perm) => {
-    return str.includes(perm);
-  });
-  return hasPerm;
+  return perms.includes(str)
 }
 
 /**

+ 4 - 0
src/plugins/icons.ts

@@ -1,8 +1,12 @@
 import type { App } from "vue";
 import * as ElementPlusIconsVue from "@element-plus/icons-vue";
 
+import DataVVue3 from "@kjgl77/datav-vue3";
+
 // 注册所有图标
 export function setupElIcons(app: App<Element>) {
+  app.use(DataVVue3);
+
   for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
     app.component(key, component);
   }

+ 17 - 0
src/router/index.ts

@@ -43,6 +43,23 @@ export const constantRoutes: RouteRecordRaw[] = [
     meta: { hidden: true },
     component: () => import("@/views/error-page/404.vue"),
   },
+  // ===============大屏
+  {
+    path: "/taskScreen",
+    component: () =>
+      import("@/views/report/statistics/screens/tasks/index.vue"),
+  },
+  {
+    path: "/capacityScreen",
+    component: () =>
+      import("@/views/report/statistics/screens/capacity/index.vue"),
+  },
+  {
+    path: "/qualityScreen",
+    component: () =>
+      import("@/views/report/statistics/screens/quality/index.vue"),
+  },
+
   // 外部链接
   // {
   //   path: "/external-link",

+ 3 - 0
src/styles/index.scss

@@ -3,6 +3,7 @@
 .app-container {
   padding: 10px;
 }
+
 .search-container {
   padding: 18px 0 0 10px;
   margin-bottom: 10px;
@@ -35,3 +36,5 @@
   background-color: white;
   border-radius: 10px;
 }
+
+

+ 2 - 0
src/styles/variables.scss

@@ -27,3 +27,5 @@ $sidebar-width: 210px; // 侧边栏宽度
 $sidebar-width-collapsed: 54px; // 侧边栏收缩宽度
 $navbar-height: 50px; // 导航栏高度
 $tags-view-height: 34px; // TagsView 高度
+
+$screen-header-height: 80px;

+ 13 - 4
src/views/base/craftManagement/route/index.vue

@@ -9,7 +9,6 @@
       v-model:page="page"
       @row-save="createRow"
       @row-update="updateRow"
-      @row-del="deleteRow"
       @search-change="searchChange"
       @search-reset="resetChange"
       @size-change="dataList"
@@ -44,11 +43,19 @@
           link
           type="primary"
           icon="el-icon-edit"
-          :disabled="false"
+          v-if="row.usable === 0"
           @click="doEdit(row, index)"
           >编辑</el-button
         >
         <el-button
+            link
+            type="danger"
+            icon="el-icon-edit"
+            v-if="row.usable === 0"
+            @click="deleteRow(row, index)"
+        >删除</el-button
+        >
+        <el-button
           link
           type="primary"
           icon="el-icon-copy-document"
@@ -212,9 +219,11 @@ const bindProcess = (row) => {
 // 设置表格列或者其他自定义的option
 option.value = Object.assign(option.value, {
   selection: true,
-  labelWidth: 110,
+  labelWidth: 100,
   editBtn: false,
-  searchLabelWidth: 110,
+  delBtn: false,
+  menuWidth: 250,
+  searchLabelWidth: 100,
   column: [
     {
       label: "工艺路线编号",

+ 15 - 2
src/views/device/allocate/index.vue

@@ -124,10 +124,23 @@
               :rules="rules"
             >
               <el-form-item label="审批人员" prop="auditUser">
-                <el-input
+<!--                <el-input
                   :disabled="maintenanceInfo.state !== 0"
                   v-model="maintenanceInfo.auditUser"
-                />
+                />-->
+                <el-select
+                    v-model="maintenanceInfo.auditUser"
+                    placeholder="审批人员"
+                    size="large"
+                    filterable
+                    style="width: 240px">
+                  <el-option
+                      v-for="item in userList"
+                      :key="item.userName"
+                      :label="item.userName"
+                      :value="item.userName"
+                  />
+                </el-select>
               </el-form-item>
               <el-form-item label="审批结果">
                 <el-radio-group

+ 10 - 1
src/views/device/instance/index.vue

@@ -10,6 +10,7 @@
       @row-save="createRow"
       @row-update="updateRow"
       @row-del="deleteRow"
+      :permission="permission"
       @search-change="searchChange"
       @search-reset="resetChange"
       @size-change="dataList"
@@ -31,7 +32,7 @@
       </template>-->
       <template #menu="{ size, row, index }">
         <el-button
-          v-hasPerm="[buttonPermission.DEVICE.BTNS.maintenance_edit]"
+          v-hasPerm="[buttonPermission.DEVICE.BTNS.instance_edit]"
           type="primary"
           link
           size="small"
@@ -48,6 +49,7 @@
           type="danger"
           icon="el-icon-delete"
           :size="size"
+          v-hasPerm="[buttonPermission.DEVICE.BTNS.instance_del]"
           @click="multipleDelete"
           >删除</el-button
         >
@@ -152,6 +154,7 @@ import { useCommonStoreHook } from "@/store";
 import ChoiceWorkshopPage from "../../plan/workOrder/components/choice-workshop-page.vue";
 import ChoiceStationPage from "./components/choice-station-page.vue";
 import dictDataUtil from "@/common/configs/dictDataUtil";
+import { checkPerm } from "@/directive/permission";
 const { isShowTable, tableType } = toRefs(useCommonStoreHook());
 const test = () => {
   isShowTable.value = true;
@@ -166,6 +169,12 @@ const addItem = () => {
     type: 1,
   });
 };
+const permission = reactive({
+  delBtn: checkPerm(buttonPermission.DEVICE.BTNS.instance_del),
+  addBtn: checkPerm(buttonPermission.DEVICE.BTNS.instance_add),
+  editBtn: checkPerm(buttonPermission.DEVICE.BTNS.instance_edit),
+  menu: true,
+});
 const minusItem = (row) => {
   pageData.value = pageData.value.filter(
     (item) => item.fieldCode !== row.fieldCode

+ 1 - 0
src/views/device/maintenance/index.vue

@@ -84,6 +84,7 @@
                     v-model="maintenanceInfo.userName"
                     placeholder="维护人员"
                     size="large"
+                    filterable
                     style="width: 240px">
                   <el-option
                       v-for="item in userList"

+ 1 - 0
src/views/device/metering/index.vue

@@ -76,6 +76,7 @@
                     v-model="maintenanceInfo.userName"
                     placeholder="计量人员"
                     size="large"
+                    filterable
                     style="width: 240px">
                   <el-option
                       v-for="item in userList"

+ 1 - 1
src/views/pro/traceability/components/checkCom.vue

@@ -51,7 +51,7 @@ const { checkBtnPerm, downloadTemplate, exportData } = Utils; //按钮权限等
 const crudRef = ref(null); //crudRef.value 获取avue-crud对象
 
 const refreshTra = (row) => {
-  commonConfig.value.params = { seqNo: row.seqNo };
+  commonConfig.value.params = { seqNo: row.seqNo,workOrderCode: row.workOrderCode };
   dataList();
 };
 defineExpose({ refreshTra });

+ 1 - 1
src/views/pro/traceability/components/equitCom.vue

@@ -51,7 +51,7 @@ const { checkBtnPerm, downloadTemplate, exportData } = Utils; //按钮权限等
 const crudRef = ref(null); //crudRef.value 获取avue-crud对象
 
 const refreshTra = (row) => {
-  commonConfig.value.params = { seqNo: row.seqNo };
+  commonConfig.value.params = { seqNo: row.seqNo,workOrderCode: row.workOrderCode };
   dataList();
 };
 defineExpose({ refreshTra });

+ 1 - 1
src/views/pro/traceability/components/faultCom.vue

@@ -51,7 +51,7 @@ const { checkBtnPerm, downloadTemplate, exportData } = Utils; //按钮权限等
 const crudRef = ref(null); //crudRef.value 获取avue-crud对象
 
 const refreshTra = (row) => {
-  commonConfig.value.params = { seqNo: row.seqNo };
+  commonConfig.value.params = { seqNo: row.seqNo,workOrderCode: row.workOrderCode };
   dataList();
 };
 defineExpose({ refreshTra });

+ 1 - 1
src/views/pro/traceability/components/materialsCom.vue

@@ -51,7 +51,7 @@ const { checkBtnPerm, downloadTemplate, exportData } = Utils; //按钮权限等
 const crudRef = ref(null); //crudRef.value 获取avue-crud对象
 
 const refreshTra = (row) => {
-  commonConfig.value.params = { seqNo: row.seqNo };
+  commonConfig.value.params = { seqNo: row.seqNo,workOrderCode: row.workOrderCode };
   dataList();
 };
 defineExpose({ refreshTra });

+ 1 - 1
src/views/pro/traceability/components/mediaCom.vue

@@ -65,7 +65,7 @@ const openDialog = (row) =>{
   url.value =  import.meta.env.VITE_APP_UPLOAD_URL + row.filePath
 }
 const refreshTra = (row) => {
-  commonConfig.value.params = { seqNo: row.seqNo };
+  commonConfig.value.params = { seqNo: row.seqNo,workOrderCode: row.workOrderCode };
   dataList();
 };
 defineExpose({ refreshTra });

+ 1 - 1
src/views/pro/traceability/components/recordCom.vue

@@ -51,7 +51,7 @@ const { checkBtnPerm, downloadTemplate, exportData } = Utils; //按钮权限等
 const crudRef = ref(null); //crudRef.value 获取avue-crud对象
 
 const refreshTra = (row) => {
-  commonConfig.value.params = { seqNo: row.seqNo };
+  commonConfig.value.params = { seqNo: row.seqNo,workOrderCode: row.workOrderCode };
   dataList();
 };
 defineExpose({ refreshTra });

+ 1 - 1
src/views/quality/faultHandle/components/fault-page.vue

@@ -265,7 +265,7 @@ const faultHandle=ref({});
     }else{
       row.enabled = true
     }
-    row.reworkProcessId = undefined
+    //row.reworkProcessId = undefined
   }
   const option2=ref(null);
   const value=ref([]);

+ 107 - 0
src/views/quality/reverseTraceability/index.vue

@@ -0,0 +1,107 @@
+<template>
+  <div class="mainContentBox">
+    <avue-crud
+      ref="crudRef"
+      v-model:search="search"
+      v-model="form"
+      :data="data"
+      :option="option"
+      v-model:page="page"
+      @row-save="createRow"
+      @row-update="updateRow"
+      @row-del="deleteRow"
+      @search-change="searchChange"
+      @search-reset="resetChange"
+      @size-change="dataList"
+      @current-change="dataList"
+      @selection-change="selectionChange"
+    />
+  </div>
+</template>
+<script setup>
+import { useCrud } from "@/hooks/userCrud";
+import { useCommonStoreHook, useDictionaryStore } from "@/store";
+
+// 数据字典相关
+const { dicts } = useDictionaryStore();
+
+// 传入一个url,后面不带/
+const { form, data, option, search, page, toDeleteIds, Methords, Utils } =
+  useCrud({
+    src: "/api/v1/process/itemRecord/itemInfo",
+  });
+const { dataList, createRow, updateRow, deleteRow, searchChange, resetChange } =
+  Methords; //增删改查
+const { selectionChange, multipleDelete } = Methords; //选中和批量删除事件
+const { checkBtnPerm, downloadTemplate, exportData } = Utils; //按钮权限等工具
+
+const crudRef = ref(null); //crudRef.value 获取avue-crud对象
+
+onMounted(() => {
+  dataList();
+});
+
+// 设置表格列或者其他自定义的option
+option.value = Object.assign(option.value, {
+  selection: false,
+  addBtn: false,
+  delBtn: false,
+  editBtn: false,
+  viewBtn: true,
+  column: [
+    {
+      label: "物料编码",
+      prop: "itemCode",
+      search: true,
+    },
+    {
+      label: "物料型号",
+      prop: "itemModel",
+      search: true,
+    },
+    {
+      label: "物料名称",
+      prop: "itemName",
+    },
+    {
+      label: "序列号",
+      prop: "itemSeq",
+    },
+    {
+      label: "序列号",
+      prop: "itemSeq",
+      hide: true,
+      search: true,
+    },
+    {
+      label: "采集工单",
+      prop: "workOrderCode",
+    },
+    {
+      label: "采集产品",
+      prop: "seqNo",
+    },
+    {
+      label: "工作台名称",
+      prop: "stationName",
+    },
+    {
+      label: "录入数量",
+      prop: "num",
+    },
+    {
+      label: "追溯类型",
+      prop: "trackType",
+      hide: true,
+    },
+    {
+      label: "采集时间",
+      prop: "trackWhen",
+    },
+    {
+      label: "修改时间",
+      prop: "updated",
+    },
+  ],
+});
+</script>

+ 27 - 0
src/views/report/statistics/screens/capacity/index.vue

@@ -0,0 +1,27 @@
+<template>
+  <div class="screen-container">
+    <common-header title="工位任务分布" />
+    <div class="screen-content"></div>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import CommonHeader from "@/views/report/statistics/screens/common-header.vue";
+</script>
+
+<style lang="scss" scoped>
+.screen-container {
+  width: 100vw;
+  height: 100vh;
+  background-image: url("@/assets/images/screen_bg_task.png");
+  background-size: cover;
+  background-position: center;
+}
+
+.screen-content {
+  width: 100vw;
+  height: calc(100vh - 96px - 18px);
+  margin-top: 18px;
+  border: 2px solid red;
+}
+</style>

+ 29 - 0
src/views/report/statistics/screens/common-header.vue

@@ -0,0 +1,29 @@
+<template>
+  <div class="screen-header">{{ title }}</div>
+</template>
+
+<script lang="ts" setup>
+defineProps({
+  title: {
+    type: String,
+    default: "",
+  },
+});
+</script>
+
+<style lang="scss" scoped>
+.screen-header {
+  display: flex;
+  justify-content: center;
+  align-items: end;
+  height: $screen-header-height;
+  padding-bottom: 15px;
+  font-weight: 500;
+  font-size: 49px;
+  color: #ffffff;
+  line-height: 58px;
+  background-image: url("@/assets/images/screen_header1.png");
+  background-size: 100% 100%;
+  background-position: center;
+}
+</style>

+ 31 - 0
src/views/report/statistics/screens/quality/index.vue

@@ -0,0 +1,31 @@
+<template>
+  <div class="screen-container">
+    <common-header title="质量统计" />
+    <div class="screen-content">
+      <TitleHeader :title="aaa" />
+    </div>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import CommonHeader from "@/views/report/statistics/screens/common-header.vue";
+import TitleHeader from "../titleHeader.vue";
+const aaa = ref("你在构建什打无无大武当");
+</script>
+
+<style lang="scss" scoped>
+.screen-container {
+  width: 100vw;
+  height: 100vh;
+  background-image: url("@/assets/images/screen_bg_task.png");
+  background-size: cover;
+  background-position: center;
+}
+
+.screen-content {
+  width: 100vw;
+  height: calc(100vh - 96px - 18px);
+  margin-top: 18px;
+  border: 2px solid red;
+}
+</style>

+ 128 - 0
src/views/report/statistics/screens/tasks/index.vue

@@ -0,0 +1,128 @@
+<template>
+  <dv-full-screen-container>
+    <div class="screen-container">
+      <common-header title="工位任务分布" />
+      <div class="screen-content">
+        <div v-for="(item, index) in data" :key="index" class="grid-item">
+          <title-header title="入库检料" />
+          <div class="grid-bottom">
+            <div class="left-info">
+              <div class="box">
+                <div class="title">工位名称</div>
+                <div class="code">工位代码</div>
+              </div>
+              <div class="box">
+                <div>
+                  <span class="com-num">完成数量/</span>
+                  <span class="plan-num">计划数量</span>
+                </div>
+                <div class="desc">任务描述</div>
+              </div>
+            </div>
+            <div class="right-chart">dd</div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </dv-full-screen-container>
+</template>
+
+<script lang="ts" setup>
+import CommonHeader from "@/views/report/statistics/screens/common-header.vue";
+import TitleHeader from "@/views/report/statistics/screens/titleHeader.vue";
+
+const data = ref([{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}]);
+</script>
+
+<style lang="scss" scoped>
+.screen-container {
+  width: 100vw;
+  height: 100vh;
+  background-image: url("@/assets/images/screen_bg_task.png");
+  background-size: cover;
+  background-position: center;
+}
+
+.screen-content {
+  width: 100vw;
+  height: calc(100vh - $screen-header-height - 18px);
+  margin-top: 18px;
+  padding: 0 32px;
+
+  display: grid;
+  grid-template-columns: repeat(3, 1fr);
+  gap: 25px;
+
+  overflow-y: auto;
+
+  border: 2px solid red;
+
+  .grid-item {
+    height: 300px;
+    background: rgba(0, 0, 0, 0.5);
+    border-radius: 8px 8px 8px 8px;
+    padding: 16px;
+
+    .grid-bottom {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      height: 100%;
+
+      .left-info {
+        display: flex;
+        flex-direction: column;
+        justify-content: space-between;
+        align-items: start;
+        padding: 0px 18px;
+        border: 2px solid white;
+
+        .box {
+          height: 50%;
+          border: 2px solid red;
+        }
+
+        .title {
+          font-weight: 500;
+          font-size: 24px;
+          color: #ffffff;
+          line-height: 20px;
+        }
+
+        .code {
+          font-weight: 400;
+          font-size: 17px;
+          color: #fff8;
+          line-height: 17px;
+        }
+
+        .com-num {
+          font-weight: 500;
+          font-size: 48px;
+          color: #55d1aa;
+        }
+
+        .plan-num {
+          font-weight: 500;
+          font-size: 48px;
+          color: #fff;
+        }
+
+        .desc {
+          font-weight: 400;
+          font-size: 17px;
+          color: #ffffff;
+          line-height: 17px;
+        }
+      }
+
+      .right-chart {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        padding-right: 28px;
+      }
+    }
+  }
+}
+</style>

+ 91 - 0
src/views/report/statistics/screens/titleHeader.vue

@@ -0,0 +1,91 @@
+<template>
+  <div class="body">
+    <div class="info">
+      <div class="round">
+        <div class="colorRound" :style="{ backgroundColor: color }"></div>
+      </div>
+      <div class="text">{{ title }}</div>
+    </div>
+    <div class="line">
+      <div class="lines"></div>
+    </div>
+    <div class="dian">
+      <div class="lines"></div>
+    </div>
+  </div>
+</template>
+
+<script lang="ts" setup>
+defineProps({
+  title: {
+    type: String,
+    default: "",
+  },
+  color: {
+    type: String,
+    default: "#5fe3ff",
+  },
+});
+</script>
+
+<style lang="scss" scoped>
+.body {
+  height: 3vh;
+  display: flex;
+  text-align: center;
+  width: 100%;
+  justify-content: space-between;
+  .info {
+    display: flex;
+    align-items: center;
+    .text {
+      color: white;
+      font-size: 2.5vh;
+    }
+    .round {
+      height: 2.4vh;
+      width: 2.4vh;
+      border-radius: 1.2vh;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      margin-right: 0.8vw;
+      border: 1px solid rgba(255, 255, 255, 0.3);
+      .colorRound {
+        height: 1.18vh;
+        width: 1.18vh;
+        border-radius: 0.59vh;
+      }
+    }
+  }
+  .line {
+    flex: 1;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    padding-left: 0.8vw;
+    .lines {
+      width: 100%;
+      border: 1px solid rgba(255, 255, 255, 0.2);
+      height: 0vh;
+      border-top: 0;
+      border-right: 0;
+      border-left: 0;
+    }
+  }
+  .dian {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 0.5vw;
+    .lines {
+      width: 0.5vw;
+      border: 1px solid rgba(255, 255, 255, 1);
+      height: 0vh;
+      border-top: 0;
+      border-right: 0;
+      border-left: 0;
+    }
+  }
+}
+</style>

+ 87 - 83
src/views/system/menu/index.vue

@@ -1,95 +1,96 @@
 <template>
   <div class="app-container">
     <div class="search-container">
-      <el-form ref="queryFormRef" :model="queryParams" :inline="true">
+      <el-form ref="queryFormRef" :inline="true" :model="queryParams">
         <el-form-item label="关键字" prop="keywords">
           <el-input
             v-model="queryParams.keywords"
-            placeholder="菜单名称"
             clearable
+            placeholder="菜单名称"
             @keyup.enter="handleQuery"
           />
         </el-form-item>
         <el-form-item>
-          <el-button type="primary" @click="handleQuery"
-            ><template #icon><i-ep-search /></template>搜索</el-button
-          >
+          <el-button type="primary" @click="handleQuery">
+            <template #icon>
+              <i-ep-search />
+            </template>
+            搜索
+          </el-button>
           <el-button @click="resetQuery">
-            <template #icon><i-ep-refresh /></template>
-            重置</el-button
-          >
+            <template #icon>
+              <i-ep-refresh />
+            </template>
+            重置
+          </el-button>
         </el-form-item>
       </el-form>
     </div>
 
-    <el-card shadow="never" class="table-container">
+    <el-card class="table-container" shadow="never">
       <template #header>
         <el-button
           v-hasPerm="[ButtonPermKeys.SYSTEM.BTNS.menu_add]"
           type="primary"
           @click="openDialog('0')"
         >
-          <template #icon><i-ep-plus /></template>
-          新增</el-button
-        >
+          <template #icon>
+            <i-ep-plus />
+          </template>
+          新增
+        </el-button>
       </template>
 
       <el-table
         v-loading="loading"
         :data="menuList"
-        highlight-current-row
-        row-key="id"
         :expand-row-keys="['1']"
-        @row-click="onRowClick"
         :tree-props="{
           children: 'childs',
           hasChildren: 'hasChildren',
         }"
+        highlight-current-row
+        row-key="id"
+        @row-click="onRowClick"
       >
-        <el-table-column label="菜单名称"  >
+        <el-table-column label="菜单名称">
           <template #default="scope">
             <svg-icon :icon-class="scope.row.icon" />
             {{ scope.row.menuName }}
           </template>
         </el-table-column>
 
-        <el-table-column label="类型" align="center">
+        <el-table-column align="center" label="类型">
           <template #default="scope">
             <el-tag
               v-if="scope.row.type === MenuTypeEnum.CATALOG"
               type="warning"
-              >目录</el-tag
-            >
+              >目录
+            </el-tag>
             <el-tag v-if="scope.row.type === MenuTypeEnum.MENU" type="success"
-              >菜单</el-tag
-            >
-            <el-tag v-if="scope.row.type === MenuTypeEnum.BUTTON" type="danger"
-              >按钮</el-tag
-            >
-            <el-tag v-if="scope.row.isFrame" type="info">外链</el-tag>
+              >菜单
+            </el-tag>
+            <el-tag v-if="scope.row.type === MenuTypeEnum.BUTTON" type="info"
+              >按钮
+            </el-tag>
+            <el-tag v-if="scope.row.type === MenuTypeEnum.EXTLINK" type="danger"
+              >外链
+            </el-tag>
           </template>
         </el-table-column>
 
-        <el-table-column
-          label="路由路径"
-          align="left"
-          prop="path"
-        />
+        <el-table-column align="left" label="路由路径" prop="path" />
 
-        <el-table-column
-          label="组件路径"
-          align="left"
-          prop="component"
-        />
+        <el-table-column align="left" label="组件路径" prop="component" />
 
         <el-table-column
-          label="权限标识"
           align="center"
-          width="200"
+          label="权限标识"
           prop="perms"
+          width="200"
         />
 
-        <el-table-column label="状态" align="center" width="80">
+        <el-table-column align="center" label="状态" width="80">
           <template #default="scope">
             <el-tag v-if="scope.row.visible === 0" type="success">显示</el-tag>
             <el-tag v-else type="info">隐藏</el-tag>
@@ -97,41 +98,44 @@
         </el-table-column>
 
         <el-table-column
-          label="排序"
           align="center"
-          width="80"
+          label="排序"
           prop="orderNum"
+          width="80"
         />
 
-        <el-table-column fixed="right" align="center" label="操作" width="220">
+        <el-table-column align="center" fixed="right" label="操作" width="220">
           <template #default="scope">
             <el-button
-              v-hasPerm="[ButtonPermKeys.SYSTEM.BTNS.menu_add]"
               v-if="scope.row.type == 0 || scope.row.type == 1"
-              type="primary"
+              v-hasPerm="[ButtonPermKeys.SYSTEM.BTNS.menu_add]"
               link
               size="small"
+              type="primary"
               @click.stop="openDialog(scope.row.id)"
             >
-              <i-ep-plus />新增
+              <i-ep-plus />
+              新增
             </el-button>
 
             <el-button
               v-hasPerm="[ButtonPermKeys.SYSTEM.BTNS.menu_edit]"
-              type="primary"
               link
               size="small"
+              type="primary"
               @click.stop="openDialog(undefined, scope.row.id)"
             >
-              <i-ep-edit />编辑
+              <i-ep-edit />
+              编辑
             </el-button>
             <el-button
               v-hasPerm="[ButtonPermKeys.SYSTEM.BTNS.menu_del]"
-              type="primary"
               link
               size="small"
+              type="primary"
               @click.stop="handleDelete(scope.row.id)"
-              ><i-ep-delete />
+            >
+              <i-ep-delete />
               删除
             </el-button>
           </template>
@@ -142,11 +146,11 @@
     <el-dialog
       v-model="dialog.visible"
       :header="dialog.title"
-      destroy-on-close
       append-to-body
+      destroy-on-close
+      top="5vh"
       width="1000px"
       @close="closeDialog"
-      top="5vh"
     >
       <el-form
         ref="menuFormRef"
@@ -157,13 +161,13 @@
         <el-form-item label="父级菜单" prop="parentId">
           <el-tree-select
             v-model="formData.parentId"
-            placeholder="选择上级菜单"
             :data="menuOptions"
-            filterable
-            check-strictly
-            :render-after-expand="false"
             :props="defaultProps"
+            :render-after-expand="false"
+            check-strictly
+            filterable
             node-key="id"
+            placeholder="选择上级菜单"
           />
         </el-form-item>
 
@@ -172,8 +176,8 @@
         </el-form-item>
 
         <el-row>
-          <el-col :span="12"
-            ><el-form-item label="菜单类型" prop="type">
+          <el-col :span="12">
+            <el-form-item label="菜单类型" prop="type">
               <el-radio-group
                 v-model="formData.type"
                 @change="onMenuTypeChange"
@@ -181,26 +185,26 @@
                 <el-radio :value="0">目录</el-radio>
                 <el-radio :value="1">菜单</el-radio>
                 <el-radio :value="2">按钮</el-radio>
-                <!-- <el-radio label="EXTLINK">外链</el-radio> -->
+                <el-radio :value="3">外链</el-radio>
               </el-radio-group>
             </el-form-item>
           </el-col>
-          <el-col :span="12"
-            ><el-form-item
+          <el-col :span="12">
+            <el-form-item
               v-if="formData.type !== MenuTypeEnum.BUTTON"
-              prop="visible"
               label="显示状态"
+              prop="visible"
             >
               <el-radio-group v-model="formData.visible">
                 <el-radio :value="0">显示</el-radio>
                 <el-radio :value="1">隐藏</el-radio>
               </el-radio-group>
-            </el-form-item></el-col
-          >
+            </el-form-item>
+          </el-col>
         </el-row>
 
         <el-form-item
-          v-if="formData.isFrame === 1"
+          v-if="formData.type == MenuTypeEnum.EXTLINK"
           label="外链地址"
           prop="path"
         >
@@ -208,7 +212,7 @@
         </el-form-item>
 
         <el-form-item
-          v-if="
+          v-else-if="
             formData.type == MenuTypeEnum.CATALOG ||
             formData.type == MenuTypeEnum.MENU
           "
@@ -233,11 +237,11 @@
             style="width: 95%"
           >
             <template v-if="formData.type == MenuTypeEnum.MENU" #prepend
-              >src/views/</template
-            >
+              >src/views/
+            </template>
             <template v-if="formData.type == MenuTypeEnum.MENU" #append
-              >.vue</template
-            >
+              >.vue
+            </template>
           </el-input>
         </el-form-item>
 
@@ -269,20 +273,20 @@
             <el-form-item label="排序" prop="orderNum">
               <el-input-number
                 v-model="formData.orderNum"
-                style="width: 100px"
-                controls-position="right"
                 :min="0"
+                controls-position="right"
+                style="width: 100px"
               />
             </el-form-item>
           </el-col>
-          <el-col :span="12"
-            ><el-form-item label="是否为外链">
-              <el-radio-group v-model="formData.isFrame">
-                <el-radio :value="1">是</el-radio>
-                <el-radio :value="0">否</el-radio>
-              </el-radio-group>
-            </el-form-item></el-col
-          >
+          <!--          <el-col :span="12">-->
+          <!--            <el-form-item label="是否为外链">-->
+          <!--              <el-radio-group v-model="formData.isFrame">-->
+          <!--                <el-radio :value="1">是</el-radio>-->
+          <!--                <el-radio :value="0">否</el-radio>-->
+          <!--              </el-radio-group>-->
+          <!--            </el-form-item>-->
+          <!--          </el-col>-->
         </el-row>
 
         <el-row>
@@ -292,8 +296,8 @@
                 <el-radio :value="0">启用</el-radio>
                 <el-radio :value="1">禁用</el-radio>
               </el-radio-group>
-            </el-form-item></el-col
-          >
+            </el-form-item>
+          </el-col>
           <el-col :span="12">
             <el-form-item
               v-if="formData.type === MenuTypeEnum.MENU"
@@ -347,7 +351,7 @@
   </div>
 </template>
 
-<script setup lang="ts">
+<script lang="ts" setup>
 defineOptions({
   // eslint-disable-next-line vue/no-reserved-component-names
   name: "Menu",
@@ -386,9 +390,9 @@ const formData = reactive<MenuForm>({
   visible: 0,
   orderNum: 1,
   type: MenuTypeEnum.MENU,
-  alwaysShow: 0,
+  alwaysShow: 1,
   keepAlive: 0,
-  isFrame: 0,
+  isFrame: 0, //用type来判断是否为外链
   state: 0,
 });
 

+ 1 - 0
src/views/system/user/components/dept-tree.vue

@@ -14,6 +14,7 @@
       :props="{ children: 'children', label: 'deptName', disabled: '' }"
       :expand-on-click-node="false"
       :filter-node-method="handleFilter"
+      highlight-current
       default-expand-all
       @node-click="handleNodeClick"
     />

+ 63 - 78
src/views/system/user/index.vue

@@ -28,8 +28,8 @@
                 clearable
                 class="!w-[100px]"
               >
-                <el-option label="启用" value="0" />
-                <el-option label="禁用" value="1" />
+                <el-option label="启用" value=0 />
+                <el-option label="禁用" value=1 />
               </el-select>
             </el-form-item>
             <el-form-item>
@@ -96,22 +96,27 @@
               prop="userName"
             />
             <el-table-column
-              label="姓名"
-              width="120"
-              align="center"
-              prop="nickName"
+                label="姓名"
+                width="120"
+                align="center"
+                prop="nickName"
             />
             <el-table-column
-              key="employeeCode"
-              label="员工编号"
-              align="center"
-              prop="employeeCode"
+                key="employeeCode"
+                label="员工编号"
+                align="center"
+                prop="employeeCode"
             />
-            <el-table-column label="性别" width="100" align="center" prop="sex">
+            <el-table-column
+              label="性别"
+              width="100"
+              align="center"
+              prop="sex"
+            >
               <template #default="scope">
                 <el-tag :type="scope.row.sex == 0 ? 'info' : 'success'">{{
-                  scope.row.sex == 0 ? "未知" : scope.row.sex == 1 ? "男" : "女"
-                }}</el-tag>
+                    scope.row.sex == 0 ? "未知" : scope.row.sex == 1 ? "男" : "女"
+                  }}</el-tag>
               </template>
             </el-table-column>
 
@@ -206,18 +211,15 @@
           <el-col :span="11">
             <el-form-item label="用户名" prop="userName">
               <el-input
-                v-model="formData.userName"
-                :disabled="!!formData.id"
-                placeholder="请输入用户名"
+                  v-model="formData.userName"
+                  :disabled="!!formData.id"
+                  placeholder="请输入用户名"
               />
             </el-form-item>
           </el-col>
-          <el-col :span="11">
+            <el-col :span="11">
             <el-form-item label="用户昵称" prop="nickName">
-              <el-input
-                v-model="formData.nickName"
-                placeholder="请输入用户昵称"
-              />
+              <el-input v-model="formData.nickName" placeholder="请输入用户昵称" />
             </el-form-item>
           </el-col>
         </el-row>
@@ -226,17 +228,17 @@
           <el-col :span="11">
             <el-form-item label="员工编号" prop="employeeCode">
               <el-input
-                v-model="formData.employeeCode"
-                placeholder="请输入员工编号"
+                  v-model="formData.employeeCode"
+                  placeholder="请输入员工编号"
               />
             </el-form-item>
           </el-col>
           <el-col :span="11">
             <el-form-item label="性别" prop="sex">
               <el-radio-group v-model="formData.sex">
-                <el-radio :value="0">未知</el-radio>
-                <el-radio :value="1">男</el-radio>
-                <el-radio :value="2">女</el-radio>
+                <el-radio :value=0>未知</el-radio>
+                <el-radio :value=1>男</el-radio>
+                <el-radio :value=2>女</el-radio>
               </el-radio-group>
             </el-form-item>
           </el-col>
@@ -245,22 +247,17 @@
           <el-col :span="22">
             <el-form-item label="所属部门" prop="deptIds">
               <el-tree-select
-                v-model="formData.deptIds"
-                placeholder="请选择所属部门"
-                :data="deptList"
-                :multiple="true"
-                filterable
-                show-checkbox
-                load-key="deptName"
-                value-key="id"
-                :props="{
-                  children: 'children',
-                  label: 'deptName',
-                  value: 'id',
-                  disabled: '',
-                }"
-                check-strictly
-                :render-after-expand="false"
+                  v-model="formData.deptIds"
+                  placeholder="请选择所属部门"
+                  :data="deptList"
+                  :multiple="true"
+                  filterable
+                  show-checkbox
+                  load-key="deptName"
+                  value-key="id"
+                  :props="{ children: 'children', label: 'deptName',value: 'id', disabled: '' }"
+                  check-strictly
+                  :render-after-expand="false"
               />
             </el-form-item>
           </el-col>
@@ -269,16 +266,12 @@
         <el-row :gutter="22">
           <el-col :span="22">
             <el-form-item label="角色" prop="roleIds">
-              <el-select
-                v-model="formData.roleIds"
-                multiple
-                placeholder="请选择"
-              >
+              <el-select v-model="formData.roleIds" multiple placeholder="请选择">
                 <el-option
-                  v-for="item in roleList"
-                  :key="item.id"
-                  :label="item.roleName"
-                  :value="item.id"
+                    v-for="item in roleList"
+                    :key="item.id"
+                    :label="item.roleName"
+                    :value="item.id"
                 />
               </el-select>
             </el-form-item>
@@ -288,16 +281,12 @@
         <el-row :gutter="22">
           <el-col :span="22">
             <el-form-item label="岗位" prop="postIds">
-              <el-select
-                v-model="formData.postIds"
-                multiple
-                placeholder="请选择"
-              >
+              <el-select v-model="formData.postIds" multiple placeholder="请选择">
                 <el-option
-                  v-for="item in postList"
-                  :key="item.id"
-                  :label="item.postName"
-                  :value="item.id"
+                    v-for="item in postList"
+                    :key="item.id"
+                    :label="item.postName"
+                    :value="item.id"
                 />
               </el-select>
             </el-form-item>
@@ -307,18 +296,18 @@
           <el-col :span="11">
             <el-form-item label="手机号码" prop="phone">
               <el-input
-                v-model="formData.phone"
-                placeholder="请输入手机号码"
-                maxlength="11"
+                  v-model="formData.phone"
+                  placeholder="请输入手机号码"
+                  maxlength="11"
               />
             </el-form-item>
           </el-col>
           <el-col :span="11">
             <el-form-item label="邮箱" prop="email">
               <el-input
-                v-model="formData.email"
-                placeholder="请输入邮箱"
-                maxlength="50"
+                  v-model="formData.email"
+                  placeholder="请输入邮箱"
+                  maxlength="50"
               />
             </el-form-item>
           </el-col>
@@ -326,8 +315,8 @@
 
         <el-form-item label="状态" prop="state">
           <el-radio-group v-model="formData.state">
-            <el-radio :value="0">正常</el-radio>
-            <el-radio :value="1">禁用</el-radio>
+            <el-radio :value=0>正常</el-radio>
+            <el-radio :value=1>禁用</el-radio>
           </el-radio-group>
         </el-form-item>
       </el-form>
@@ -345,12 +334,7 @@
             :data="deptList"
             load-key="deptName"
             value-key="id"
-            :props="{
-              children: 'children',
-              label: 'deptName',
-              value: 'id',
-              disabled: '',
-            }"
+            :props="{ children: 'children', label: 'deptName',value: 'id', disabled: '' }"
             filterable
             check-strictly
           />
@@ -431,6 +415,7 @@ const deptList = ref(); // 部门下拉数据源
 const roleList = ref(); // 角色下拉数据源
 const postList = ref(); // 岗位下拉数据源
 
+
 // 弹窗对象
 const dialog = reactive({
   visible: false,
@@ -443,7 +428,7 @@ const dialog = reactive({
 const formData = reactive({
   state: 0,
   sex: 0,
-  email: "",
+  email: '',
 });
 
 // 用户导入数据
@@ -457,9 +442,7 @@ const importData = reactive({
 const rules = reactive({
   userName: [{ required: true, message: "用户名不能为空", trigger: "blur" }],
   nickName: [{ required: true, message: "用户昵称不能为空", trigger: "blur" }],
-  employeeCode: [
-    { required: true, message: "员工编号不能为空", trigger: "blur" },
-  ],
+  employeeCode: [{ required: true, message: "员工编号不能为空", trigger: "blur" }],
   deptIds: [{ required: true, message: "所属部门不能为空", trigger: "blur" }],
   roleIds: [{ required: true, message: "用户角色不能为空", trigger: "blur" }],
   postIds: [{ required: true, message: "用户岗位不能为空", trigger: "blur" }],
@@ -482,6 +465,7 @@ const rules = reactive({
 /** 查询 */
 function handleQuery() {
   loading.value = true;
+  queryParams.deptQuery = queryParams.deptId
   getUserPage(queryParams)
     .then(({ data }) => {
       pageData.value = data.records;
@@ -633,6 +617,7 @@ const handleSubmit = useThrottleFn(() => {
 
 /** 删除用户 */
 function handleDelete(id) {
+
   ElMessageBox.confirm("确认删除用户?", "警告", {
     confirmButtonText: "确定",
     cancelButtonText: "取消",