Răsfoiți Sursa

菜单组件配置

quwangxin 3 ani în urmă
părinte
comite
39481fda5f

+ 23 - 21
package-lock.json

@@ -2028,6 +2028,29 @@
         "webpack-merge": "^5.7.3",
         "webpack-virtual-modules": "^0.4.2",
         "whatwg-fetch": "^3.6.2"
+      },
+      "dependencies": {
+        "@vue/vue-loader-v15": {
+          "version": "npm:vue-loader@15.10.1",
+          "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.10.1.tgz",
+          "integrity": "sha512-SaPHK1A01VrNthlix6h1hq4uJu7S/z0kdLUb6klubo738NeQoLbS6V9/d8Pv19tU0XdQKju3D1HSKuI8wJ5wMA==",
+          "dev": true,
+          "requires": {
+            "@vue/component-compiler-utils": "^3.1.0",
+            "hash-sum": "^1.0.2",
+            "loader-utils": "^1.1.0",
+            "vue-hot-reload-api": "^2.3.0",
+            "vue-style-loader": "^4.1.0"
+          },
+          "dependencies": {
+            "hash-sum": {
+              "version": "1.0.2",
+              "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz",
+              "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==",
+              "dev": true
+            }
+          }
+        }
       }
     },
     "@vue/cli-shared-utils": {
@@ -2177,27 +2200,6 @@
         }
       }
     },
-    "@vue/vue-loader-v15": {
-      "version": "npm:vue-loader@15.10.1",
-      "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.10.1.tgz",
-      "integrity": "sha512-SaPHK1A01VrNthlix6h1hq4uJu7S/z0kdLUb6klubo738NeQoLbS6V9/d8Pv19tU0XdQKju3D1HSKuI8wJ5wMA==",
-      "dev": true,
-      "requires": {
-        "@vue/component-compiler-utils": "^3.1.0",
-        "hash-sum": "^1.0.2",
-        "loader-utils": "^1.1.0",
-        "vue-hot-reload-api": "^2.3.0",
-        "vue-style-loader": "^4.1.0"
-      },
-      "dependencies": {
-        "hash-sum": {
-          "version": "1.0.2",
-          "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz",
-          "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==",
-          "dev": true
-        }
-      }
-    },
     "@vue/web-component-wrapper": {
       "version": "1.3.0",
       "resolved": "https://registry.npmmirror.com/@vue/web-component-wrapper/-/web-component-wrapper-1.3.0.tgz",

+ 8 - 0
src/api/classifyManage/index.js

@@ -25,6 +25,14 @@ export async function getTreeByPid (parentId) {
   }
   return Promise.reject(new Error(res.data.message));
 }
+// 根据类型查分类树
+export async function getTreeByType (type) {
+  const res = await request.get(`/main/categoryLevel/getTreeByType/${type}`);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
 
 // 删除分类
 export async function deleteCategory (id) {

+ 155 - 0
src/components/AssetTree/index.vue

@@ -0,0 +1,155 @@
+<template>
+  <div class="tree-wrapper">
+    <el-tree
+      :data="treeList"
+      :props="defaultProps"
+      :default-expand-all="defaultExpandAll"
+      :default-expanded-keys="defaultExpandedKeys"
+      v-loading="treeLoading"
+      node-key="id"
+      ref="tree"
+      :expand-on-click-node="expandOnClickNode"
+      :highlight-current="true"
+      @node-click="handleNodeClick"
+      v-bind="$attrs"
+    >
+    </el-tree>
+  </div>
+</template>
+
+<script>
+  import { getTreeByType } from '@/api/classifyManage';
+  // let originId = '';
+  // let originType = '';
+  export default {
+    props: {
+      defaultProps: {
+        type: Object,
+        default: function () {
+          return {
+            children: 'children',
+            value: 'code',
+            label: 'name'
+          };
+        }
+      },
+      defaultExpandAll: {
+        type: Boolean,
+        default: true
+      },
+      init: {
+        type: Boolean,
+        default: false
+      },
+      defaultExpandedKeys: {
+        type: Array,
+        default: function () {
+          return [];
+        }
+      },
+      expandOnClickNode: {
+        type: Boolean,
+        default: false
+      },
+      type: {
+        type: String,
+        default: ''
+      },
+      // appendRoot: {
+      //   type: Boolean,
+      //   default: false
+      // },
+      treeFormate: {
+        type: Function,
+        default: null
+      }
+    },
+    data () {
+      return {
+        treeList: [],
+        treeLoading: false,
+        parentName: '',
+        parentId: '',
+        currentKey: ''
+      };
+    },
+    mounted () {
+      if (this.init) {
+        this.getTreeData();
+      }
+    },
+    methods: {
+      getInstance () {
+        return this.$refs.tree;
+      },
+      // 获取树结构数据
+      async getTreeData () {
+        try {
+          this.treeLoading = true;
+          const res = await getTreeByType(type);
+          this.treeLoading = false;
+          if (res.success) {
+            this.treeList = res.data;
+
+            if (this.treeFormate) {
+              this.treeList = this.treeFormate(this.treeList);
+            }
+            this.$nextTick(() => {
+              // 默认高亮第一级树节点
+              if (this.treeList[0]) {
+                this.setCurrentKey(this.treeList[0].id);
+                this.handleNodeClick(
+                  this.treeList[0],
+                  this.$refs.tree.getCurrentNode()
+                );
+              }
+            });
+            return this.treeList;
+          }
+        } catch (error) {}
+        this.treeLoading = false;
+      },
+      // 递归 - 往树children里面添加parentName
+      // _setParentName (tree) {
+      //   let data = tree;
+      //   for (let i = 0; i < data.length; i++) {
+      //     if (data[i].parentId === '0') {
+      //       this.parentName = data[i].name;
+      //       originId = data[i].id;
+      //       originType = data[i].type;
+      //     }
+
+      //     data[i]['originId'] = originId;
+      //     data[i]['originType'] = originType;
+      //     data[i]['parentId'] = data[i]['parentId'];
+      //     if (data[i].children && data[i].children.length > 0) {
+      //       this._setParentName(data[i].children);
+      //     }
+      //   }
+      //   return data;
+      // },
+
+      handleNodeClick (data, node) {
+        this.$emit('handleNodeClick', data, node);
+      },
+      // 设置默认高亮行
+      setCurrentKey (id) {
+        this.currentKey = id;
+        this.$refs.tree.setCurrentKey(this.currentKey);
+      },
+
+      // 获取树的选中状态
+      getSelectList () {
+        const selectList = this.$refs.tree.getCurrentNode();
+        return selectList;
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .tree-wrapper {
+    width: 100%;
+    overflow: auto;
+  }
+</style>

+ 5 - 5
src/components/Dict/DictSelection.vue

@@ -41,27 +41,27 @@
         default: 'dictCode'
       }
     },
-    data() {
+    data () {
       return {};
     },
     computed: {
       ...mapGetters(['dict', 'getDict']),
-      dictList() {
+      dictList () {
         return this.dict[dictEnum[this.dictName]] || [];
       },
       selectVal: {
-        set(val) {
+        set (val) {
           this.$emit('updateVal', val);
           // change获取选中项所有数据
 
           this.$emit('itemChange', this.getDict(this.dictName, val));
         },
-        get() {
+        get () {
           return this.value;
         }
       }
     },
-    created() {
+    created () {
       if (this.dictName) {
         this.requestDict(this.dictName);
       }

+ 1 - 1
src/utils/request.js

@@ -44,7 +44,7 @@ service.interceptors.request.use(
 service.interceptors.response.use(
   (res) => {
     // token 自动续期
-    if (res.data.code == '-1' && res.config.showErrorToast !== false) {
+    if (res.data.code == '-1' && res.config?.showErrorToast !== false) {
       Message.error(res.data.message);
     }
     const token = res.headers[TOKEN_HEADER_NAME.toLowerCase()];

+ 0 - 1
src/views/classifyManage/details.vue

@@ -201,7 +201,6 @@
       this.requestDict('分隔符');
       this.getTree().then(() => {
         this.$nextTick(() => {
-          console.log(this.treeData[0]?.id);
           this.getDetail(this.treeData[0]?.id);
         });
       });

+ 1 - 1
src/views/classifyManage/index.vue

@@ -103,7 +103,7 @@
         return getSubPage({
           ...where,
           parentId: 0,
-          current: page,
+          pageNum: page,
           size: limit
         });
       },

+ 208 - 0
src/views/classifyManage/itemInformation/components/item-list.vue

@@ -0,0 +1,208 @@
+<template>
+  <div>
+    <!-- 数据表格 -->
+    <ele-pro-table
+      ref="table"
+      :columns="columns"
+      :datasource="datasource"
+      height="calc(100vh - 265px)"
+      full-height="calc(100vh - 116px)"
+      tool-class="ele-toolbar-form"
+      cache-key="systemOrgUserTable"
+    >
+      <!-- 表头工具栏 -->
+      <template v-slot:toolbar>
+        <item-search @search="reload"> </item-search>
+      </template>
+      <!-- 操作列 -->
+      <template v-slot:action="{ row }">
+        <el-link
+          type="primary"
+          :underline="false"
+          icon="el-icon-edit"
+          @click="openEdit(row)"
+        >
+          编辑
+        </el-link>
+        <el-link
+          v-if="row.loginName"
+          type="primary"
+          :underline="false"
+          icon="el-icon-unlock"
+          @click="toUnBind(row)"
+        >
+          克隆
+        </el-link>
+        <el-popconfirm
+          class="ele-action"
+          title="确定要删除此用户吗?"
+          @confirm="remove(row)"
+        >
+          <template v-slot:reference>
+            <el-link type="danger" :underline="false" icon="el-icon-delete">
+              删除
+            </el-link>
+          </template>
+        </el-popconfirm>
+      </template>
+    </ele-pro-table>
+  </div>
+</template>
+
+<script>
+  import ItemSearch from './item-search.vue';
+  import {
+    getUserPage,
+    removePersonnel,
+    unbindLoginName
+  } from '@/api/system/organization';
+  import { handlers } from 'mdast-util-to-hast/lib/handlers';
+
+  export default {
+    components: { ItemSearch },
+    props: {
+      // 机构id
+      organizationId: [Number, String],
+      // 全部机构
+      organizationList: Array,
+      current: {
+        type: Object,
+        default: () => ({})
+      }
+    },
+    data () {
+      return {};
+    },
+    computed: {
+      // 表格列配置
+      columns () {
+        const privateColumn = [];
+
+        return [
+          {
+            columnKey: 'index',
+            type: 'index',
+            width: 45,
+            align: 'center',
+            showOverflowTooltip: true,
+            fixed: 'left'
+          },
+          {
+            prop: 'name',
+            label: '物品编码',
+            sortable: 'custom',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            prop: 'jobNumber',
+            label: '物品名称',
+            sortable: 'custom',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            prop: 'loginName',
+            label: '物品类型',
+            sortable: 'custom',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          ...privateColumn,
+          {
+            prop: 'measuringUnit',
+            label: '计量单位',
+            sortable: 'custom',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'packingUnit',
+            label: '包装单位',
+            align: 'center'
+          },
+          {
+            prop: 'classificationUrl',
+            label: '分类',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            columnKey: 'action',
+            label: '操作',
+            width: 200,
+            align: 'left',
+            resizable: false,
+            slot: 'action',
+            showOverflowTooltip: true
+          }
+        ];
+      }
+    },
+    methods: {
+      /* 表格数据源 */
+      datasource ({ page, limit, where, order }) {
+        return Promise.resolve([]);
+      },
+      /* 刷新表格 */
+      reload (where) {
+        this.$refs.table.reload({ pageNum: 1, where: where });
+      },
+      /* 显示编辑 */
+      openEdit (row) {},
+
+      // 解除绑定
+      toUnBind (row) {
+        const loading = this.$loading({ lock: true });
+        unbindLoginName(row.id)
+          .then((res) => {
+            loading.close();
+            this.$message.success('解绑成功');
+            this.reload();
+          })
+          .catch((e) => {
+            loading.close();
+            this.$message.error(e.message);
+          });
+      },
+      /* 删除 */
+      remove (row) {
+        const loading = this.$loading({ lock: true });
+        removePersonnel([row.id])
+          .then((msg) => {
+            loading.close();
+            this.$message.success(msg);
+            this.reload();
+          })
+          .catch((e) => {
+            loading.close();
+            this.$message.error(e.message);
+          });
+      },
+      /* 更改状态 */
+      editStatus (row) {
+        const loading = this.$loading({ lock: true });
+        updateUserStatus(row.userId, row.status)
+          .then((msg) => {
+            loading.close();
+            this.$message.success(msg);
+          })
+          .catch((e) => {
+            loading.close();
+            row.status = !row.status ? 1 : 0;
+            this.$message.error(e.message);
+          });
+      }
+    },
+    watch: {
+      // 监听机构id变化
+      current: {
+        handler () {
+          console.log(this.current);
+          this.reload();
+        }
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped></style>

+ 75 - 0
src/views/classifyManage/itemInformation/components/item-search.vue

@@ -0,0 +1,75 @@
+<!-- 搜索表单 -->
+<template>
+  <el-form
+    label-width="100px"
+    class="ele-form-search"
+    @keyup.enter.native="search"
+    @submit.native.prevent
+  >
+    <el-row :gutter="15">
+      <el-col v-bind="styleResponsive ? { lg: 6, md: 12 } : { span: 6 }">
+        <el-form-item label="物品编码:">
+          <el-input
+            clearable
+            placeholder="请输入"
+            v-model.trim="params.code"
+          ></el-input>
+        </el-form-item>
+      </el-col>
+      <el-col v-bind="styleResponsive ? { lg: 6, md: 12 } : { span: 6 }">
+        <el-form-item label="物品名称:">
+          <el-input
+            clearable
+            v-model="params.name"
+            placeholder="请输入"
+          ></el-input>
+        </el-form-item>
+      </el-col>
+      <el-col v-bind="styleResponsive ? { lg: 6, md: 12 } : { span: 6 }">
+        <div class="ele-form-actions">
+          <el-button
+            type="primary"
+            icon="el-icon-search"
+            class="ele-btn-icon"
+            @click="search"
+          >
+            查询
+          </el-button>
+          <el-button @click="reset">重置</el-button>
+        </div>
+      </el-col>
+    </el-row>
+  </el-form>
+</template>
+<script>
+  export default {
+    data () {
+      // 默认表单数据
+      const defaultParams = {
+        name: '',
+        code: ''
+      };
+      return {
+        // 表单数据
+        params: { ...defaultParams }
+      };
+    },
+    computed: {
+      // 是否开启响应式布局
+      styleResponsive () {
+        return this.$store.state.theme.styleResponsive;
+      }
+    },
+    methods: {
+      /* 搜索 */
+      search () {
+        this.$emit('search', this.params);
+      },
+      /*  重置 */
+      reset () {
+        this.params = { ...this.defaultParams };
+        this.search();
+      }
+    }
+  };
+</script>

+ 94 - 0
src/views/classifyManage/itemInformation/index.vue

@@ -0,0 +1,94 @@
+<template>
+  <div class="ele-body">
+    <el-card shadow="never">
+      <ele-split-layout
+        width="266px"
+        allow-collapse
+        :right-style="{ overflow: 'hidden' }"
+      >
+        <div>
+          <!-- 操作按钮 -->
+          <ele-toolbar class="ele-toolbar-actions">
+            <div style="margin: 5px 0">
+              <el-button
+                size="small"
+                type="primary"
+                icon="el-icon-plus"
+                class="ele-btn-icon"
+                @click="openEdit()"
+              >
+                新建物品
+              </el-button>
+            </div>
+          </ele-toolbar>
+          <div class="ele-border-lighter sys-organization-list">
+            <el-tree
+              ref="tree"
+              :data="treeData"
+              highlight-current
+              node-key="id"
+              :props="{ label: 'name' }"
+              :expand-on-click-node="false"
+              :default-expand-all="true"
+              @node-click="onNodeClick"
+            />
+          </div>
+        </div>
+        <template v-slot:content>
+          <item-list :current="current" />
+        </template>
+      </ele-split-layout>
+    </el-card>
+  </div>
+</template>
+
+<script>
+  import itemList from './components/item-list';
+  import { getTreeByPid } from '@/api/classifyManage';
+
+  export default {
+    components: { itemList },
+    data () {
+      return {
+        treeData: [],
+        current: {}
+      };
+    },
+    created () {
+      this.getTree();
+    },
+    methods: {
+      onNodeClick (data, node) {
+        this.current = node;
+      },
+      openEdit () {},
+      async getTree () {
+        const res = await getTreeByPid(0);
+
+        if (res.code == '0') {
+          this.treeData = res.data;
+          return;
+        }
+
+        return Promise.reject();
+      }
+    }
+  };
+</script>
+<style lang="scss" scoped>
+  .sys-organization-list {
+    height: calc(100vh - 264px);
+    box-sizing: border-box;
+    border-width: 1px;
+    border-style: solid;
+    overflow: auto;
+  }
+
+  .sys-organization-list :deep(.el-tree-node__content) {
+    height: 40px;
+
+    & > .el-tree-node__expand-icon {
+      margin-left: 10px;
+    }
+  }
+</style>

+ 32 - 20
src/views/system/menu/components/menu-edit.vue

@@ -3,7 +3,7 @@
   <ele-modal
     width="720px"
     :visible="visible"
-    :close-on-click-modal="true"
+    :close-on-click-modal="false"
     custom-class="ele-dialog-form"
     :title="isUpdate ? '修改菜单' : '添加菜单'"
     @update:visible="updateVisible"
@@ -41,6 +41,15 @@
             />
           </el-form-item>
         </el-col>
+        <el-col :span="12">
+          <el-form-item label="组件地址:" prop="component">
+            <el-input
+              clearable
+              v-model="form.component"
+              placeholder="请输入路由地址"
+            />
+          </el-form-item>
+        </el-col>
         <el-col :span="12">
           <el-form-item label="菜单图标:">
             <ele-icon-picker
@@ -85,7 +94,7 @@
 
 <script>
   import { EleIconPicker } from 'ele-admin';
-  import { saveOrUpdate  } from '@/api/system/menu';
+  import { saveOrUpdate } from '@/api/system/menu';
 
   export default {
     components: { EleIconPicker },
@@ -95,11 +104,11 @@
       // 修改回显的数据
       data: Object,
       // 上级菜单id
-      parentId: [Number,String],
+      parentId: [Number, String],
       // 全部菜单数据
       menuList: Array
     },
-    data() {
+    data () {
       const defaultForm = {
         id: null,
         parentId: '',
@@ -107,8 +116,9 @@
         type: 1,
         icon: '',
         url: '',
+        component: '',
         sort: null,
-        permissionCode:1
+        permissionCode: 1
       };
       return {
         defaultForm,
@@ -116,10 +126,12 @@
         form: { ...defaultForm },
         // 表单验证规则
         rules: {
-          name: [{required: true,message: '请输入菜单名称',trigger: 'blur'}],
-          sort: [{required: true,message: '请输入排序号', trigger: 'blur'}],
-          url: [{required: true,message: '请输入菜单路由', trigger: 'blur'}],
-          type: [{required: true,message: '请选择菜单类型', trigger: 'blur'}],
+          name: [
+            { required: true, message: '请输入菜单名称', trigger: 'blur' }
+          ],
+          sort: [{ required: true, message: '请输入排序号', trigger: 'blur' }],
+          url: [{ required: true, message: '请输入菜单路由', trigger: 'blur' }],
+          type: [{ required: true, message: '请选择菜单类型', trigger: 'blur' }]
         },
         // 提交状态
         loading: false,
@@ -141,7 +153,7 @@
     },
     methods: {
       /* 保存编辑 */
-      save() {
+      save () {
         this.$refs.form.validate((valid) => {
           if (!valid) {
             return false;
@@ -154,15 +166,15 @@
             parentId: this.form.parentId || 0
           };
           // const saveOrUpdate = this.isUpdate ? updateMenu : addMenu;
-          if(!this.isUpdate){
-            delete data.id
+          if (!this.isUpdate) {
+            delete data.id;
           }
           saveOrUpdate(data)
-            .then(res => {
+            .then((res) => {
               this.loading = false;
-              if(this.isUpdate){
+              if (this.isUpdate) {
                 this.$message.success('菜单编辑成功');
-              }else{
+              } else {
                 this.$message.success('菜单新增成功');
               }
               this.updateVisible(false);
@@ -175,11 +187,11 @@
         });
       },
       /* 更新visible */
-      updateVisible(value) {
+      updateVisible (value) {
         this.$emit('update:visible', value);
       },
       /* menuType选择改变 */
-      onMenuTypeChange() {
+      onMenuTypeChange () {
         // if (this.form.menuType === 0) {
         //   this.form.authority = null;
         //   this.form.openType = 0;
@@ -197,12 +209,12 @@
         // }
       },
       /* openType选择改变 */
-      onOpenTypeChange() {
+      onOpenTypeChange () {
         if (this.form.openType === 2) {
           this.form.component = null;
           this.form.authority = null;
         }
-      },
+      }
       /* 判断是否是外链 */
       // isUrl(url) {
       //   return !!(
@@ -218,7 +230,7 @@
       // }
     },
     watch: {
-      visible(visible) {
+      visible (visible) {
         if (visible) {
           if (this.data) {
             // const isInnerLink = this.isUrl(this.data.component) ? 1 : 0;

+ 1 - 1
vue.config.js

@@ -15,7 +15,7 @@ module.exports = {
     proxy: {
       // 当我们的本地的请求 有/api的时候,就会代理我们的请求地址向另外一个服务器发出请求
       '/api': {
-        // target: 'http://192.168.3.51:18086', // 测试
+        // target: 'http://192.168.3.51:86', // 测试
 
         //#gitignoreline_start
         //#gitignoreline_end