Bladeren bron

存储字典, 列表组件增加下拉框搜索

lxf 2 jaren geleden
bovenliggende
commit
3af48026b7

+ 34 - 26
src/api/login.js

@@ -1,60 +1,68 @@
-import request from '@/utils/request'
+import request from "@/utils/request";
 
 // 登录方法
-export function login(username, password, code, uuid,tenantId) {
+export function login(username, password, code, uuid, tenantId) {
   const data = {
     username,
     password,
     code,
-    uuid
-  }
+    uuid,
+  };
   return request({
-    url: '/login',
+    url: "/login",
     headers: {
       isToken: false,
-      tenantId:tenantId
+      tenantId: tenantId,
     },
-    method: 'post',
-    data: data
-  })
+    method: "post",
+    data: data,
+  });
 }
 
 // 注册方法
 export function register(data) {
   return request({
-    url: '/register',
+    url: "/register",
     headers: {
-      isToken: false
+      isToken: false,
     },
-    method: 'post',
-    data: data
-  })
+    method: "post",
+    data: data,
+  });
 }
 
 // 获取用户详细信息
 export function getInfo() {
   return request({
-    url: '/getInfo',
-    method: 'get'
-  })
+    url: "/getInfo",
+    method: "get",
+  });
+}
+
+// 获取用户所有字典
+export function allDictMap() {
+  return request({
+    url: "/allDictMap",
+    method: "post",
+  });
 }
 
 // 退出方法
 export function logout() {
   return request({
-    url: '/logout',
-    method: 'post'
-  })
+    url: "/logout",
+    method: "post",
+  });
 }
 
 // 获取验证码
 export function getCodeImg() {
   return request({
-    url: '/captchaImage',
+    url: "/captchaImage",
     headers: {
-      isToken: false
+      isToken: false,
     },
-    method: 'get',
-    timeout: 20000
-  })
-}
+    method: "get",
+    timeout: 20000,
+  });
+}

+ 9 - 5
src/components/byTable/index.vue

@@ -1,11 +1,14 @@
 <template>
-  <el-form :inline="true" :model="pagination" v-if="searchConfig && searchConfig.length > 0">
+  <el-form :inline="true" :model="pagination" v-if="searchConfig && searchConfig.length > 0" @submit.native.prevent>
     <el-form-item v-for="(item, index) in searchConfig" :key="index" :label="item.label + ':'" :prop="item.prop">
-      <el-input v-if="item.type === 'input'" v-model="pagination[item.prop]" :placeholder="'请输入' + item.label" />
+      <el-input v-if="item.type === 'input'" v-model="pagination[item.prop]" :placeholder="'请输入' + item.label" @keyup.enter.native="searchFn" />
+      <el-select v-else-if="item.type === 'select'" v-model="pagination[item.prop]" :placeholder="'请选择' + item.label" @change="searchFn">
+        <el-option v-for="itemDict in useUserStore().allDict[item.dictKey]" :key="itemDict.dictKey" :label="itemDict.dictValue" :value="itemDict.dictKey" />
+      </el-select>
     </el-form-item>
     <el-form-item>
-      <el-button size="small" @click="searchFn" class="searchBtn">搜索</el-button>
-      <el-button size="small" @click="clickReset">重置</el-button>
+      <el-button @click="searchFn" class="searchBtn">搜索</el-button>
+      <el-button @click="clickReset">重置</el-button>
     </el-form-item>
   </el-form>
   <div class="header-actions" v-if="getActionList.length != 0">
@@ -84,6 +87,7 @@ import { isFunction as isFn, isBoolean } from "./type";
 import ElementsMapping from "./ElementsMapping";
 import ComponentsMapping from "./ComponentsMapping";
 import { computed, defineComponent, getCurrentInstance, ref, watch } from "vue";
+import useUserStore from "../../store/modules/user";
 export default defineComponent({
   name: "Table",
   components: {
@@ -574,6 +578,6 @@ export default defineComponent({
   border: 1px solid #20b2aa;
 }
 ::v-deep(.el-form-item) {
-    margin-right: 16px !important;
+  margin-right: 16px !important;
 }
 </style>

+ 3 - 28
src/components/headerBar/header-bar.vue

@@ -123,7 +123,7 @@
         <notice v-model="noticeTableModal"></notice>
         <el-dropdown @command="handleCommand" class="right-menu-item hover-effect" trigger="click">
           <div class="dropdown-box">
-            {{ userData }}
+            {{ userStore.user.nickName }}
           </div>
           <template #dropdown>
             <el-dropdown-menu>
@@ -145,22 +145,20 @@
 </template>
 
 <script setup>
-import Cookies from "js-cookie";
-import { ElMessageBox, ElNotification, ElMessage } from "element-plus";
+import { ElMessageBox, ElMessage } from "element-plus";
 import useUserStore from "@/store/modules/user";
 import "@/components/headerBar/header.scss";
 import notice from "@/components/notice/index";
+
 const router = useRouter();
 const userStore = useUserStore();
 const { proxy } = getCurrentInstance();
-const sidebarRouters = ref([]);
 const sidebarRoutersCopy = ref([]);
 const isChildMenu = ref(false);
 const autoListChidrenNum = ref(0);
 const isEidtType = ref(false);
 const leftBanerType = ref(2);
 const noticeTableModal = ref(false);
-const userData = ref(Cookies.get("nickName") || "");
 const commonsRouterList = ref([]);
 const activeLeftData = ref({});
 const openLeftBaner = (i, index) => {
@@ -170,15 +168,6 @@ const openLeftBaner = (i, index) => {
   routerInit(i);
 };
 let menuName = ref("");
-const logoUrl = ref();
-// const getLogo = () => {
-//   proxy.post("/tenantInfo/getLogo", {}).then((res) => {
-//     if (res && res.length > 0 && res[0].fileUrl) {
-//       logoUrl.value = res[0].fileUrl;
-//     }
-//   });
-// };
-// getLogo();
 const userMenuEdit = () => {
   proxy
     .post("/sysUserMenu/edit", {
@@ -193,11 +182,9 @@ const userMenuEdit = () => {
       isEidtType.value = false;
     });
 };
-
 const deleteCommonsRouter = (i, index) => {
   commonsRouterList.value.splice(index, 1);
 };
-
 const addCommonsRouter = (index, jindex, nindex, n) => {
   for (let i = 0; i < commonsRouterList.value.length; i++) {
     const element = commonsRouterList.value[i];
@@ -219,7 +206,6 @@ const addCommonsRouter = (index, jindex, nindex, n) => {
   commonsRouterList.value.push(n);
   sidebarRoutersCopy.value[index].children[jindex].children[nindex].isCommonsBanner = true;
 };
-
 const routerInit = (item) => {
   //二维转一维
   const arr = [];
@@ -227,10 +213,8 @@ const routerInit = (item) => {
     const element = item.children[i];
     if (element.type === 1) {
       element.isTitle = true;
-
       arr.push(element);
     }
-
     if (element.children && element.children.length > 0) {
       for (let j = 0; j < element.children.length; j++) {
         const jelement = element.children[j];
@@ -269,7 +253,6 @@ function handleCommand(command) {
       break;
   }
 }
-
 function logout() {
   ElMessageBox.confirm(proxy.t("header.areYouSureYouWantToLogOutAndExitTheSystem"), proxy.t("common.prompt"), {
     confirmButtonText: proxy.t("common.confirm"),
@@ -283,7 +266,6 @@ function logout() {
     })
     .catch(() => {});
 }
-
 //使用id计算拼接url
 const commonsBannerToRouter = (i) => {
   sidebarRoutersCopy.value.map((item) => {
@@ -301,25 +283,18 @@ const commonsBannerToRouter = (i) => {
     }
   });
 };
-
 //获取浏览器宽度
 function getBrowserWidth() {
   return document.documentElement.clientWidth;
 }
-
 //计算auto-list 能放下几个
 function calcAutoListChidren() {
   autoListChidrenNum.value = Math.floor((getBrowserWidth() - 616) / 120);
 }
-
 //一维数组转tree
-
 onMounted(() => {
   calcAutoListChidren();
   window.addEventListener("resize", calcAutoListChidren);
-  proxy.get("/getInfo").then((res) => {
-    userData.value = res.user.nickName;
-  });
   proxy.get("/system/menu/list").then((res) => {
     res.data = res.data.map((item) => {
       return {

+ 1 - 1
src/layout/index.vue

@@ -115,7 +115,7 @@ function setLayout() {
   outline: 0px !important;
 }
 ::v-deep(.box-card) {
-  max-height: calc(100vh - 120px);
+  height: calc(100vh - 120px);
   overflow-y: auto;
   overflow-x: hidden;
 }

+ 2 - 0
src/main.js

@@ -11,6 +11,7 @@ import App from "./App";
 import store from "./store";
 import router from "./router";
 import directive from "./directive"; // directive
+import useUserStore from "@/store/modules/user";
 
 // 注册指令
 import plugins from "./plugins"; // plugins
@@ -82,6 +83,7 @@ app.config.globalProperties.random = random;
 app.config.globalProperties.deepClone = deepClone;
 app.config.globalProperties.timeInterval = timeInterval;
 app.config.globalProperties.compareTime = compareTime;
+app.config.globalProperties.useUserStore = useUserStore;
 
 // 全局组件挂载
 app.component("Pagination", Pagination);

+ 5 - 2
src/store/modules/user.js

@@ -1,4 +1,4 @@
-import { login, logout, getInfo } from "@/api/login";
+import { login, logout, getInfo, allDictMap } from "@/api/login";
 import { getToken, setToken, removeToken } from "@/utils/auth";
 import defAva from "@/assets/images/profile.jpg";
 
@@ -10,6 +10,7 @@ const useUserStore = defineStore("user", {
     roles: [],
     permissions: [],
     user: {},
+    allDict: {},
   }),
   actions: {
     // 登录
@@ -35,9 +36,11 @@ const useUserStore = defineStore("user", {
       return new Promise((resolve, reject) => {
         getInfo()
           .then((res) => {
+            allDictMap().then((res) => {
+              this.allDict = res.data
+            });
             const user = res.user;
             const avatar = user.avatar == "" || user.avatar == null ? defAva : import.meta.env.VITE_APP_BASE_API + user.avatar;
-
             if (res.roles && res.roles.length > 0) {
               // 验证返回的roles是否是一个非空数组
               this.roles = res.roles;

+ 223 - 87
src/views/group/BOM/management/index.vue

@@ -1,120 +1,256 @@
 <template>
-  <el-card class="box-card">
-    <byTable
-      :source="sourceList.data"
-      :pagination="sourceList.pagination"
-      :config="config"
-      :loading="loading"
-      :selectConfig="selectConfig"
-      highlight-current-row
-      @get-list="getList">
-      <template #amount="{ item }">
-        <div>
-          <span style="padding-right: 4px">{{ item.currency }}</span>
-          <span>{{ moneyFormat(item.amount, 2) }}</span>
-        </div>
+  <div>
+    <el-row :gutter="10">
+      <el-col :span="4">
+        <el-card class="box-card">
+          <el-input v-model="filterTree" placeholder="请输入BOM分类" />
+          <el-tree
+            ref="treeCategory"
+            :data="categoryTreeData"
+            :props="{ children: 'children', label: 'name' }"
+            node-key="id"
+            default-expand-all
+            :expand-on-click-node="false"
+            :indent="10"
+            :filter-node-method="filterNodeMethod"
+            @node-click="handleNodeClick" />
+        </el-card>
+      </el-col>
+      <el-col :span="20">
+        <el-card class="box-card">
+          <byTable
+            :hideTable="true"
+            :hidePagination="true"
+            :source="sourceList.data"
+            :pagination="sourceList.pagination"
+            :config="config"
+            :loading="loading"
+            :searchConfig="searchConfig"
+            highlight-current-row
+            :action-list="[
+              {
+                text: '新增',
+                action: () => openModal(),
+              },
+            ]"
+            @get-list="getList"
+            @clickReset="clickReset">
+          </byTable>
+          <el-table :data="sourceList.data" row-key="id" default-expand-all>
+            <el-table-column prop="name" label="分类名称" min-width="180" />
+            <el-table-column prop="sort" label="排序" align="center" width="100" />
+            <el-table-column label="操作" align="center" width="180">
+              <template #default="{ row }">
+                <div>
+                  <el-button type="primary" @click="addChildNode(row)" text>添加子节点</el-button>
+                  <el-button type="primary" @click="clickUpdate(row)" v-if="row.parentId" text>编辑</el-button>
+                  <el-button type="primary" @click="clickDelete(row)" v-if="row.parentId" text>删除</el-button>
+                </div>
+              </template>
+            </el-table-column>
+          </el-table>
+        </el-card>
+      </el-col>
+    </el-row>
+
+    <el-dialog :title="modalType == 'add' ? '新增分类' : '编辑分类'" v-if="openDialog" v-model="openDialog" width="400">
+      <!-- <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="submit">
+        <template #parentId>
+          <div style="width: 100%">
+            <el-cascader
+              v-model="formData.data.parentId"
+              :options="sourceList.data"
+              :props="{ checkStrictly: true, value: 'id', label: 'name', emitPath: false }"
+              clearable
+              style="width: 100%" />
+          </div>
+        </template>
+      </byForm> -->
+      <template #footer>
+        <el-button @click="openDialog = false" size="large">取 消</el-button>
+        <el-button type="primary" @click="submitForm()" v-loading="btnLoading" size="large">确 定</el-button>
       </template>
-    </byTable>
-  </el-card>
+    </el-dialog>
+  </div>
 </template>
 
 <script setup>
 import byTable from "@/components/byTable/index";
+import byForm from "@/components/byForm/index";
 import { ElMessage, ElMessageBox } from "element-plus";
 
 const { proxy } = getCurrentInstance();
-const orderStatus = ref([]);
+const filterTree = ref("");
+const treeCategory = ref(null);
+const categoryTreeData = ref([]);
+const getTreeList = () => {
+  proxy.post("/bomClassify/tree", {}).then((res) => {
+    categoryTreeData.value = res;
+  });
+};
+getTreeList();
+watch(filterTree, (val) => {
+  treeCategory.value.filter(val);
+});
+const filterNodeMethod = (value, data) => {
+  if (!value) return true;
+  return data.name.includes(value);
+};
+const handleNodeClick = (val) => {
+  console.log(val);
+};
 const sourceList = ref({
-  data: [{ code: "踩踩踩踩踩踩踩踩踩踩踩踩踩踩踩踩踩踩从" }, {}],
+  data: [],
   pagination: {
-    total: 1000,
-    pageNum: 1,
-    pageSize: 10,
-    keyword: "",
-    status: "",
-    payStatus: "",
+    total: 0,
+    name: "",
   },
 });
-const selectConfig = computed(() => {
+const loading = ref(false);
+const searchConfig = computed(() => {
   return [
     {
-      label: "质检状态",
-      prop: "status",
-      data: [],
-    },
-    {
-      label: "订单类型",
-      prop: "payStatus",
-      data: [],
+      type: "input",
+      prop: "name",
+      label: "分类名称",
     },
     {
-      label: "结论",
-      prop: "payStatus",
-      data: [],
+      type: "select",
+      prop: "species",
+      dictKey: "bom_species",
+      label: "种类",
     },
   ];
 });
 const config = computed(() => {
+  return [];
+});
+const getList = async (req) => {
+  sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
+  loading.value = true;
+  proxy.post("/bomClassify/tree", sourceList.value.pagination).then((res) => {
+    sourceList.value.data = res;
+    setTimeout(() => {
+      loading.value = false;
+    }, 200);
+  });
+};
+getList();
+const clickReset = () => {
+  treeCategory.setCurrentKey(null);
+  getList({ name: "" });
+};
+const modalType = ref("add");
+const submit = ref(null);
+const openDialog = ref(false);
+const formOption = reactive({
+  inline: true,
+  labelWidth: 100,
+  itemWidth: 100,
+  rules: [],
+});
+const formData = reactive({
+  data: {},
+});
+const formConfig = computed(() => {
   return [
     {
-      attrs: {
-        label: "采购单号",
-        prop: "code",
-        "min-width": 180,
-      },
+      type: "slot",
+      prop: "parentId",
+      slotName: "parentId",
+      label: "上级分类",
     },
-    // {
-    //   attrs: {
-    //     label: "供应商",
-    //     prop: "sellCorporationId",
-    //     "min-width": 220,
-    //   },
-    //   render(type) {
-    //     return proxy.dictValueLabel(type, supplierList.value);
-    //   },
-    // },
     {
-      attrs: {
-        label: "操作",
-        width: 160,
-        align: "center",
-        fixed: "right",
-      },
-      renderHTML(row) {
-        return [];
-      },
+      type: "input",
+      prop: "name",
+      label: "分类名称",
+      itemType: "text",
+    },
+    {
+      type: "input",
+      prop: "code",
+      label: "分类编码",
+      itemType: "text",
+    },
+    {
+      type: "number",
+      prop: "sort",
+      label: "排序",
+      precision: 0,
+    },
+    {
+      type: "input",
+      prop: "remark",
+      label: "备注",
+      itemType: "textarea",
     },
   ];
 });
-const getDict = () => {
-  proxy.getDictOne(["order_status"]).then((res) => {
-    if (res["order_status"] && res["order_status"].length > 0) {
-      orderStatus.value = res["order_status"].map((x) => ({
-        label: x.dictValue,
-        value: x.dictKey,
-      }));
-    }
+const rules = ref({
+  parentId: [{ required: true, message: "请选择上级分类", trigger: "change" }],
+  name: [{ required: true, message: "请输入分类名称", trigger: "blur" }],
+  code: [{ required: true, message: "请输入分类编码", trigger: "blur" }],
+});
+const btnLoading = ref(false);
+const openModal = () => {
+  modalType.value = "add";
+  formData.data = {};
+  btnLoading.value = false;
+  openDialog.value = true;
+};
+const addChildNode = (row) => {
+  modalType.value = "add";
+  formData.data = {
+    parentId: row.id,
+  };
+  btnLoading.value = false;
+  openDialog.value = true;
+};
+const submitForm = () => {
+  submit.value.handleSubmit(() => {
+    btnLoading.value = true;
+    proxy.post("/bomClassify/" + modalType.value, formData.data).then(
+      () => {
+        ElMessage({
+          message: modalType.value == "add" ? "添加成功" : "编辑成功",
+          type: "success",
+        });
+        openDialog.value = false;
+        btnLoading.value = false;
+        getList();
+      },
+      (err) => {
+        console.log(err);
+        btnLoading.value = false;
+      }
+    );
   });
 };
-getDict();
-const getList = async (req) => {
-  console.log(req);
-  //   sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
-  //   loading.value = true;
-  //   proxy.post("/ehsdPurchase/page", sourceList.value.pagination).then((res) => {
-  //     console.log(res);
-  //     sourceList.value.data = res.rows;
-  //     sourceList.value.pagination.total = res.total;
-  //     setTimeout(() => {
-  //       loading.value = false;
-  //     }, 200);
-  //   });
+const clickUpdate = (row) => {
+  modalType.value = "edit";
+  formData.data = {
+    id: row.id,
+    parentId: row.parentId,
+    name: row.name,
+    code: row.code,
+    sort: row.sort,
+    remark: row.remark,
+  };
+  btnLoading.value = false;
+  openDialog.value = true;
+};
+const clickDelete = (row) => {
+  ElMessageBox.confirm("你是否确认此操作", "提示", {
+    confirmButtonText: "确定",
+    cancelButtonText: "取消",
+    type: "warning",
+  }).then(() => {
+    proxy.post("/bomClassify/delete", { id: row.id }).then(() => {
+      ElMessage({ message: "删除成功", type: "success" });
+      getList();
+    });
+  });
 };
-getList();
 </script>
 
-<style lang="scss" scoped>
-.tenant {
-  padding: 10px;
-}
-</style>
+<style lang="scss" scoped></style>