Jelajahi Sumber

feat: 工具管理和分类管理页面开发,接口联调

yongCode 1 tahun lalu
induk
melakukan
fbae5d21aa

+ 9 - 0
src/api/bussiness/index.js

@@ -18,6 +18,14 @@ export function listToolTypes(query) {
   });
 }
 
+// 根据 id 获取工具详情
+export function getToolDetailById(id){
+  return request({
+    url: `/tool/basis/${id}`,
+    method: "get",
+  });
+}
+
 // 获取工具类型字典
 export function queryToolDict(level,parentId) {
   return new Promise((resolve, reject) => {
@@ -39,6 +47,7 @@ export function queryToolDict(level,parentId) {
       .catch((err) => reject(err));
   });
 }
+
 // 添加工具、分类基本信息
 export function toolAdd(data) {
   return request({

TEMPAT SAMPAH
src/assets/images/bg_gear.png


TEMPAT SAMPAH
src/assets/images/bg_mian.png


TEMPAT SAMPAH
src/assets/images/bg_wrench.png


TEMPAT SAMPAH
src/assets/images/login-background.jpg


TEMPAT SAMPAH
src/assets/images/login-background.png


TEMPAT SAMPAH
src/assets/images/tools.gif


+ 1 - 1
src/assets/styles/variables.module.scss

@@ -42,7 +42,7 @@ $--color-warning: #E6A23C;
 $--color-danger: #F56C6C;
 $--color-info: #909399;
 
-$base-sidebar-width: 200px;
+$base-sidebar-width: 240px;
 
 // the :export directive is the magic sauce for webpack
 // https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass

+ 47 - 7
src/components/FileUpload/index.vue

@@ -24,15 +24,35 @@
       <template v-if="fileType"> 格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template>
       的文件
     </div>
+    <!-- 图片列表 -->
+    <transition-group v-if="imageMode" class="el-upload-list el-upload-list--picture-card" name="el-fade-in-linear" tag="ul">
+      <li :key="file.uid" class="el-upload-list__item" v-for="(file, index) in fileList">
+        <el-image
+          style="width: 100%; height: 100%"
+          :src="`${baseUrl}${file.url}`"
+          :zoom-rate="1.2"
+          :max-scale="7"
+          :min-scale="0.2"
+          :preview-src-list="fullUrlFileList"
+          :initial-index="index"
+          fit="cover"
+        />
+        <div class="upload-list-options" style="cursor: pointer;">
+          <el-icon class="upload-list-options-delete" :size="20" @click="handleDelete(index)">
+            <Delete />
+          </el-icon>
+        </div>
+      </li>
+    </transition-group>
     <!-- 文件列表 -->
-    <transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul">
+    <transition-group v-else class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul">
       <li :key="file.uid" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList">
-        <el-link :href="`${baseUrl}${file.url}`" :underline="false" target="_blank">
-          <span class="el-icon-document"> {{ getFileName(file.name) }} </span>
-        </el-link>
-        <div class="ele-upload-list__item-content-action">
-          <el-link :underline="false" @click="handleDelete(index)" type="danger">删除</el-link>
-        </div>
+          <el-link :href="`${baseUrl}${file.url}`" :underline="false" target="_blank">
+            <span class="el-icon-document"> {{ getFileName(file.name) }} </span>
+          </el-link>
+          <div class="ele-upload-list__item-content-action">
+            <el-link :underline="false" @click="handleDelete(index)" type="danger">删除</el-link>
+          </div>
       </li>
     </transition-group>
   </div>
@@ -59,6 +79,11 @@ const props = defineProps({
     type: Array,
     default: () => ["doc","docx","xls","xlsx", "ppt", "txt", "pdf"],
   },
+  // 图片模式
+  imageMode: {
+    type: Boolean,
+    default: false
+  },
   // 是否显示提示
   isShowTip: {
     type: Boolean,
@@ -97,6 +122,9 @@ watch(() => props.modelValue, val => {
   }
 },{ deep: true, immediate: true });
 
+const fullUrlFileList = computed(()=>{
+  return fileList.value.map(item => `${baseUrl}${item.url}`)
+})
 // 上传前校检格式和大小
 function handleBeforeUpload(file) {
   // 校检文件类型
@@ -206,4 +234,16 @@ function listToString(list, separator) {
 .ele-upload-list__item-content-action .el-link {
   margin-right: 10px;
 }
+.upload-list-options{
+  position: absolute;
+  right: 4px;
+  top: 4px;
+}
+.upload-list-options-delete{
+  transition: transform .3s ease-in-out;
+  &:hover{
+    transform: scale(1.2);
+    color: #f56c6c;
+  }
+}
 </style>

+ 14 - 0
src/router/index.js

@@ -84,6 +84,20 @@ export const constantRoutes = [
   //     }
   //   ]
   // },
+  // {
+  //   path: '/',
+  //   component: Layout,
+  //   meta: { title: '', icon: ''},
+  //   hidden: true,
+  //   children: [
+  //     {
+  //       path: 'material',
+  //       component: () => import('@/views/material/index'),
+  //       name: 'Material',
+  //       meta: { title: '物料管理', icon: 'component' },
+  //     },
+  //   ]
+  // },
   {
     path: '/',
     component: Layout,

+ 31 - 24
src/views/classification/hooks/useSubmitForm.js

@@ -1,10 +1,14 @@
-import { toolAdd, toolUpdate, addFileByBasisId, updateFileByBasisId } from "@/api/bussiness";
+import {
+  toolAdd,
+  toolUpdate,
+  updateFileByBasisId,
+} from "@/api/bussiness";
 
 const useSubmitForm = (getList) => {
   const { proxy } = getCurrentInstance();
   const open = ref(false);
   const title = ref("");
-  const formLoading = ref(false)
+  const formLoading = ref(false);
   const data = reactive({
     form: {
       parentId: undefined,
@@ -19,9 +23,6 @@ const useSubmitForm = (getList) => {
       toolName: [
         { required: true, message: "分类名称不能为空", trigger: "blur" },
       ],
-      describe: [
-        { required: true, message: "分类描述不能为空", trigger: "blur" },
-      ],
     },
   });
 
@@ -29,7 +30,7 @@ const useSubmitForm = (getList) => {
 
   // 表单分类选项改变
   const handleFormTypeChange = (val) => {
-    if (!val){
+    if (!val) {
       form.value.manualFileList = [];
       form.value.resourceFileList = [];
     }
@@ -47,24 +48,27 @@ const useSubmitForm = (getList) => {
   };
 
   // 更新关联的文件
-  const fileUpdate = (basisId,type) => {
-    const manualFileList = form.value.manualFileList.map(item => ({
+  const fileUpdate = (basisId) => {
+    const manualFileList = form.value.manualFileList.map((item) => ({
       id: item.id,
       basisId: basisId,
       fileName: item.name,
       filePath: item.url,
-      informationType: 'sc'
-    }))
-    const resourceFileList = form.value.resourceFileList.map(item => ({
+      informationType: "sc",
+    }));
+    const resourceFileList = form.value.resourceFileList.map((item) => ({
       id: item.id,
       basisId: basisId,
       fileName: item.name,
       filePath: item.url,
-      informationType: 'zl'
-    }))
-    if(type === 'update') return updateFileByBasisId(manualFileList.concat(resourceFileList))
-    else return addFileByBasisId(manualFileList.concat(resourceFileList))
-  }
+      informationType: "zl",
+    }));
+    const allFiles = manualFileList.concat(resourceFileList);
+    return updateFileByBasisId({
+      basisId: basisId,
+      fileList: allFiles,
+    });
+  };
 
   // 更新工具分类
   const updateToolType = () => {
@@ -72,15 +76,18 @@ const useSubmitForm = (getList) => {
       ...form.value,
       parentId: form.value.parentId || "0",
       level: form.value.parentId ? "2" : "1",
-    }
+    };
     // const allFiles = form.value.manualFileList.concat(form.value.resourceFileList)
-    const promiseApis = [toolUpdate(baseParams),fileUpdate(form.value.id,'update')]
+    const promiseApis = [
+      toolUpdate(baseParams),
+      fileUpdate(form.value.id),
+    ];
     Promise.all(promiseApis).then((res) => {
       proxy.$modal.msgSuccess("修改成功");
       open.value = false;
       getList();
     });
-  }
+  };
 
   // 添加工具分类
   const addToolType = () => {
@@ -90,22 +97,22 @@ const useSubmitForm = (getList) => {
       level: form.value.parentId ? "2" : "1",
     };
     toolAdd(params).then((res) => {
-      fileUpdate(res.data,'add').then(()=>{
+      fileUpdate(res.data).then(() => {
         proxy.$modal.msgSuccess("新增成功");
         open.value = false;
         getList();
-      })
+      });
     });
-  }
+  };
 
   /** 提交按钮 */
   const submitForm = () => {
     proxy.$refs["toolTypesRef"].validate((valid) => {
       if (valid) {
         if (form.value.id != undefined) {
-          updateToolType()
+          updateToolType();
         } else {
-          addToolType()
+          addToolType();
         }
       }
     });

+ 17 - 4
src/views/classification/hooks/useTable.js

@@ -1,4 +1,4 @@
-import { listFileByBasisId, toolDelete } from "@/api/bussiness";
+import { getToolDetailById, listFileByBasisId, toolDelete } from "@/api/bussiness";
 import { groupByKey } from "@/utils"
 
 const useTable = (getList, updateTypeOneDict, reset, open, title,form,formLoading) => {
@@ -12,7 +12,7 @@ const useTable = (getList, updateTypeOneDict, reset, open, title,form,formLoadin
 
   /** 多选框选中数据 */
   const handleSelectionChange = (selection) => {
-    ids.value = selection.map((item) => item.postId);
+    ids.value = selection.map((item) => item.id);
     single.value = selection.length != 1;
     multiple.value = !selection.length;
   };
@@ -25,6 +25,17 @@ const useTable = (getList, updateTypeOneDict, reset, open, title,form,formLoadin
     title.value = "添加分类";
   };
 
+  // 点击表格上的修改按钮
+  const handleSelecterUpdate = () => {
+    console.log(ids.value)
+    const targetId = ids.value[0];
+    formLoading.value = true;
+    getToolDetailById(targetId).then((res)=>{
+      console.log(res)
+      handleUpdate(res.data)
+    })
+  }
+
   /** 修改按钮操作 */
   const handleUpdate = (row) => {
     reset();
@@ -59,11 +70,12 @@ const useTable = (getList, updateTypeOneDict, reset, open, title,form,formLoadin
   };
   /** 删除按钮操作 */
   const handleDelete = (row) => {
-    const toolIds = row.id || ids.value;
+    const toolTypeIds = row.id || ids.value;
+    console.log(toolTypeIds)
     proxy.$modal
       .confirm('是否确认删除该分类?')
       .then(function () {
-        return toolDelete(toolIds);
+        return toolDelete(toolTypeIds);
       })
       .then(() => {
         getList();
@@ -78,6 +90,7 @@ const useTable = (getList, updateTypeOneDict, reset, open, title,form,formLoadin
     single,
     multiple,
     handleAdd,
+    handleSelecterUpdate,
     handleUpdate,
     handleDelete,
     handleSelectionChange

+ 12 - 12
src/views/classification/index.vue

@@ -2,12 +2,7 @@
   <div class="app-container">
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button
-          type="primary"
-          plain
-          icon="Plus"
-          @click="handleAdd"
-          v-hasPermi="['system:post:add']"
+        <el-button type="primary" plain icon="Plus" @click="handleAdd"
           >新增</el-button
         >
       </el-col>
@@ -17,8 +12,7 @@
           plain
           icon="Edit"
           :disabled="single"
-          @click="handleUpdate"
-          v-hasPermi="['system:post:edit']"
+          @click="handleSelecterUpdate"
           >修改</el-button
         >
       </el-col>
@@ -29,7 +23,6 @@
           icon="Delete"
           :disabled="multiple"
           @click="handleDelete"
-          v-hasPermi="['system:post:remove']"
           >删除</el-button
         >
       </el-col>
@@ -42,7 +35,7 @@
       @selection-change="handleSelectionChange"
     >
       <el-table-column type="selection" width="55" align="center" />
-      <el-table-column label="分类编号" prop="id" />
+      <!-- <el-table-column label="分类编号" prop="id" /> -->
       <el-table-column label="分类名称" prop="toolName" />
       <el-table-column label="描述" prop="describe" />
       <el-table-column
@@ -72,7 +65,13 @@
       </el-table-column>
     </el-table>
     <!-- 添加或修改岗位对话框 -->
-    <el-dialog :title="title" v-model="open" width="500px" append-to-body>
+    <el-dialog
+      :title="title"
+      v-model="open"
+      width="500px"
+      append-to-body
+      :close-on-click-modal="false"
+    >
       <el-form
         ref="toolTypesRef"
         :model="form"
@@ -130,7 +129,7 @@
         </el-form-item>
       </el-form>
       <template #footer>
-        <div class="dialog-footer">
+        <div style="text-align: center">
           <el-button type="primary" @click="submitForm">确 定</el-button>
           <el-button @click="cancel">取 消</el-button>
         </div>
@@ -181,6 +180,7 @@ const {
   multiple,
   handleAdd,
   handleUpdate,
+  handleSelecterUpdate,
   handleDelete,
   handleSelectionChange,
 } = useTable(getList, updateTypeOneDict, reset, open, title, form, formLoading);

+ 77 - 0
src/views/components/bgTools.vue

@@ -0,0 +1,77 @@
+<template>
+  <div class="tools" :style="{transform: `translateY(-50%) scale(${scaleVal})`}">
+    <img class="bg_main" src="@/assets/images/bg_mian.png" alt="" />
+    <img class="bg_gear" src="@/assets/images/bg_gear.png" alt="" />
+    <img class="bg_wrench" src="@/assets/images/bg_wrench.png" alt="" />
+  </div>
+</template>
+
+<script setup>
+
+import { useWindowSize } from '@vueuse/core'
+
+const { width, height } = useWindowSize();
+const scaleVal = ref(1)
+console.log(width)
+watch(width, value => {
+  scaleVal.value = value / 1920;
+  console.log(value,scaleVal.value)
+})
+
+</script>
+
+<style lang="scss" scoped>
+.tools{
+  width: 1124px;
+  height: 1080px;
+  position: absolute;
+  left: 4%;
+  top: 50%;
+  transform-origin: 0 50%;
+  .bg_main{
+    width: 100%;
+    height: 100%;
+  }
+  .bg_gear{
+    width: 28%;
+    height: 28%;
+    position: absolute;
+    right: 80px;
+    bottom: 280px;
+    animation: rotate_gear 12s linear infinite;
+    transform-origin: 45.5% 44%;
+  }
+  .bg_wrench{
+    width: 48%;
+    height: 48%;
+    position: absolute;
+    left: 24px;
+    bottom: 100px;
+    animation: rotate_wrench 10s linear infinite;
+  }
+}
+
+@keyframes rotate_wrench {
+  0% {
+    transform: translate(-100px, -80px) rotate(48deg);
+  }
+  50% {
+    transform: translate(0px, 0px) rotate(-0deg);
+  }
+  100%{
+    transform: translate(-100px, -80px) rotate(48deg);
+  }
+}
+
+@keyframes rotate_gear {
+  0% {
+    transform: translate(40px, -80px) rotate(30deg);
+  }
+  50% {
+    transform: translate(0px, 0px) rotate(-0deg);
+  }
+  100%{
+    transform: translate(40px, -80px) rotate(30deg);
+  }
+}
+</style>

+ 9 - 6
src/views/login.vue

@@ -1,5 +1,6 @@
 <template>
   <div class="login">
+    <bgTools />
     <el-form
       ref="loginRef"
       :model="loginForm"
@@ -74,10 +75,6 @@
         </div>
       </el-form-item>
     </el-form>
-    <!--  底部  -->
-    <!-- <div class="el-login-footer">
-      <span>Copyright © 2018-2024 ruoyi.vip All Rights Reserved.</span>
-    </div> -->
   </div>
 </template>
 
@@ -86,6 +83,7 @@ import { getCodeImg } from "@/api/login";
 import Cookies from "js-cookie";
 import { encrypt, decrypt } from "@/utils/jsencrypt";
 import useUserStore from "@/store/modules/user";
+import bgTools from "./components/bgTools";
 
 const userStore = useUserStore();
 const route = useRoute();
@@ -194,15 +192,19 @@ getCookie();
 $greenSeaweed: rgb(24, 200, 223);
 $blueQueen: rgb(41, 104, 170);
 .login {
+  width: 100vw;
+  height: 100vh;
+  overflow: hidden;
   display: flex;
-  justify-content: center;
+  justify-content: flex-end;
   align-items: center;
   height: 100%;
-  background-image: url("../assets/images/login-background.jpg");
+  background-image: url("../assets/images/login-background.png");
   background-size: cover;
   position: relative;
   z-index: 2;
 }
+
 .title {
   margin: 0px auto 30px auto;
   text-align: center;
@@ -218,6 +220,7 @@ $blueQueen: rgb(41, 104, 170);
   overflow: hidden;
   position: relative;
   z-index: 2;
+  right: 12%;
   &::before,
   &::after {
     content: "";

+ 49 - 0
src/views/material/hooks/useSearchForm.js

@@ -0,0 +1,49 @@
+import { queryToolDict } from "@/api/bussiness";
+
+const useSearchForm = (getList) => {
+  const { proxy } = getCurrentInstance();
+  const queryParams = ref({
+    toolName: "",
+    levelOneTypeId: "",
+    levelTwoTypeId: "",
+  })
+  const levelTwoDict = ref([]);
+
+  // 一级分类选择之后查询对应的二级分类
+  const handleChangeLevelOneType = (val) => {
+    queryParams.value.levelTwoTypeId = ""
+    if (val) {
+      queryToolDict("2", val).then((data) => {
+        levelTwoDict.value = data || [];
+      });
+    } else {
+      levelTwoDict.value = [];
+    }
+  };
+  /** 搜索按钮操作 */
+  const handleQuery = () => {
+    const params = {
+      toolName: queryParams.value.toolName || "",
+      parentId:
+        queryParams.value.levelTwoTypeId ||
+        queryParams.value.levelOneTypeId ||
+        undefined,
+    };
+    getList(params);
+  };
+  /** 重置按钮操作 */
+  const resetQuery = () => {
+    proxy.resetForm("queryRef");
+    handleQuery();
+  };
+
+  return {
+    queryParams,
+    levelTwoDict,
+    handleChangeLevelOneType,
+    handleQuery,
+    resetQuery
+  }
+}
+
+export default useSearchForm;

+ 172 - 0
src/views/material/hooks/useSubmitForm.js

@@ -0,0 +1,172 @@
+import {
+  toolAdd,
+  toolUpdate,
+  queryToolDict,
+  updateFileByBasisId,
+} from "@/api/bussiness";
+
+const useSubmitForm = (getList) => {
+  const { proxy } = getCurrentInstance();
+  const formLoading = ref(false);
+  const form = ref({
+    toolName: "",
+    aliasName: "",
+    levelOneId: "",
+    levelTwoId: "",
+    describe: "",
+    specifications: "",
+    example: "",
+    toolNum: 0,
+    manualFileList: [],
+    resourceFileList: [],
+    imageList: [],
+  });
+  const checkNums = (rule, value, callback) => {
+    if(value <= 0){
+      callback(new Error('数量必须大于0'))
+    }
+    callback()
+  }
+  const rules = ref({
+    toolName: [
+      { required: true, message: "分类名称不能为空", trigger: "blur" },
+    ],
+    specifications: [
+      { required: true, message: "规格说明不能为空", trigger: "blur" },
+    ],
+    example: [{ required: true, message: "举例不能为空", trigger: "blur" }],
+    levelOneId: [
+      { required: true, message: "所属一级分类不能为空", trigger: "change" },
+    ],
+    levelTwoId: [
+      { required: true, message: "所属二级分类不能为空", trigger: "change" },
+    ],
+    toolNum:[
+      { required: true, message: "数量不能为空", trigger: "blur" },
+      { validator: checkNums, trigger: 'change' },
+    ]
+  });
+  const open = ref(false);
+  const title = ref("");
+  const submitFormLevelTwoDict = ref([]);
+  // 更新关联的文件
+  const fileUpdate = (basisId) => {
+    const manualFileList = form.value.manualFileList.map((item) => ({
+      id: item.id,
+      basisId: basisId,
+      fileName: item.name,
+      filePath: item.url,
+      informationType: "sc",
+    }));
+    const resourceFileList = form.value.resourceFileList.map((item) => ({
+      id: item.id,
+      basisId: basisId,
+      fileName: item.name,
+      filePath: item.url,
+      informationType: "zl",
+    }));
+    const imageList = form.value.imageList.map((item) => ({
+      id: item.id,
+      basisId: basisId,
+      fileName: item.name,
+      filePath: item.url,
+      informationType: "syt",
+    }));
+    const allFiles = [...manualFileList, ...resourceFileList, ...imageList];
+    return updateFileByBasisId({
+      basisId: basisId,
+      fileList: allFiles,
+    });
+  };
+  // 更新工具
+  const updateTool = () => {
+    const baseParams = {
+      ...form.value,
+      parentId: form.value.levelTwoId,
+      level: "3",
+    };
+    // const allFiles = form.value.manualFileList.concat(form.value.resourceFileList)
+    const promiseApis = [
+      toolUpdate(baseParams),
+      fileUpdate(form.value.id),
+    ];
+    Promise.all(promiseApis).then((res) => {
+      proxy.$modal.msgSuccess("修改成功");
+      open.value = false;
+      getList();
+    });
+  };
+
+  // 添加工具
+  const addTool = () => {
+    const params = {
+      ...form.value,
+      parentId: form.value.levelTwoId,
+      level: "3",
+    };
+    toolAdd(params).then((res) => {
+      fileUpdate(res.data).then(() => {
+        proxy.$modal.msgSuccess("新增成功");
+        open.value = false;
+        getList();
+      });
+    });
+  };
+  /** 提交按钮 */
+  const submitForm = () => {
+    proxy.$refs["toolRef"].validate((valid) => {
+      if (valid) {
+        if (form.value.id != undefined) {
+          updateTool();
+        } else {
+          addTool();
+        }
+      }
+    });
+  };
+  /** 取消按钮 */
+  const cancel = () => {
+    open.value = false;
+    reset();
+  };
+  /** 表单重置 */
+  const reset = () => {
+    form.value = {
+      toolName: "",
+      aliasName: "",
+      levelOneId: "",
+      levelTwoId: "",
+      describe: "",
+      toolNum: 0,
+      manualFileList: [],
+      resourceFileList: [],
+      imageList: [],
+    };
+    proxy.resetForm("toolRef");
+  };
+  /** 获取二级分类字典 */
+  const updateTypeTwoDict = (parentId) => {
+    queryToolDict("2", parentId).then((data) => {
+      submitFormLevelTwoDict.value = data || [];
+    });
+  };
+  // 一级分类改变时,更新二级分类列表,并清空一级分类
+  const handleChangeSubmitFormLevelType = (val) => {
+    form.value.levelTwoId = "";
+    updateTypeTwoDict(val);
+  };
+  return {
+    form,
+    rules,
+    open,
+    title,
+    formLoading,
+    submitFormLevelTwoDict,
+    submitForm,
+    cancel,
+    reset,
+    handleChangeSubmitFormLevelType,
+  };
+};
+
+export default useSubmitForm;

+ 130 - 0
src/views/material/hooks/useTable.js

@@ -0,0 +1,130 @@
+import { listFileByBasisId,getToolDetailById, queryToolDict,toolDelete } from "@/api/bussiness";
+import { groupByKey } from "@/utils";
+
+const useTable = (
+  open,
+  title,
+  form,
+  formLoading,
+  submitFormLevelTwoDict,
+  queryParams,
+  getList,
+  updateTypeOneDict,
+  reset
+) => {
+  const { proxy } = getCurrentInstance();
+
+  const toolList = ref([]);
+  const loading = ref(true);
+  const ids = ref([]);
+  const single = ref(true);
+  const multiple = ref(true);
+
+  /** 多选框选中数据 */
+  const handleSelectionChange = (selection) => {
+    ids.value = selection.map((item) => item.id);
+    single.value = selection.length != 1;
+    multiple.value = !selection.length;
+  };
+
+  /** 新增按钮操作 */
+  const handleAdd = () => {
+    reset();
+    updateTypeOneDict();
+    open.value = true;
+    title.value = "添加工具";
+  };
+  // 获取类型id
+  const getTypeId = (ancestors, level) => {
+    return ancestors.split(",")[level];
+  };
+  /** 获取二级分类字典 */
+  const updateTypeTwoDict = (parentId) => {
+    queryToolDict("2", parentId).then((data) => {
+      submitFormLevelTwoDict.value = data || [];
+    });
+  };
+
+    // 点击表格上的修改按钮
+    const handleSelecterUpdate = () => {
+      console.log(ids.value)
+      const targetId = ids.value[0];
+      formLoading.value = true;
+      getToolDetailById(targetId).then((res)=>{
+        console.log(res)
+        handleUpdate(res.data)
+      })
+    }
+  /** 修改按钮操作 */
+  const handleUpdate = (row) => {
+    reset();
+    updateTypeOneDict();
+    open.value = true;
+    formLoading.value = true;
+    listFileByBasisId({
+      basisId: row.id,
+      delFlag: "0",
+    })
+      .then((res) => {
+        const allFiles = (res.rows || []).map((item) => ({
+          id: item.id,
+          name: item.fileName,
+          url: item.filePath,
+          informationType: item.informationType,
+        }));
+        const fileMap = groupByKey(allFiles, "informationType");
+        const typeOneId = +getTypeId(row.ancestors, 1);
+        updateTypeTwoDict(typeOneId)
+        form.value = {
+          id: row.id,
+          toolName: row.toolName,
+          aliasName: row.aliasName,
+          levelOneId: typeOneId,
+          levelTwoId: row.parentId,
+          describe: row.describe,
+          toolNum: row.toolNum || 0,
+          specifications: row.specifications,
+          example: row.example,
+          // 手册附件
+          manualFileList: fileMap["sc"] || [],
+          // 资料附件
+          resourceFileList: fileMap["zl"] || [],
+          // 示意图
+          imageList: fileMap["syt"] || [],
+        };
+        title.value = "修改工具";
+      })
+      .finally(() => {
+        formLoading.value = false;
+      });
+  };
+  /** 删除按钮操作 */
+  const handleDelete = (row) => {
+    const toolIds = row.id || ids.value;
+    console.log(toolIds)
+    proxy.$modal
+      .confirm("是否确认删除该工具?")
+      .then(function () {
+        return toolDelete(toolIds);
+      })
+      .then(() => {
+        getList(queryParams.value);
+        proxy.$modal.msgSuccess("删除成功");
+      })
+      .catch(() => {});
+  };
+
+  return {
+    toolList,
+    loading,
+    single,
+    multiple,
+    handleSelectionChange,
+    handleAdd,
+    handleUpdate,
+    handleDelete,
+    handleSelecterUpdate,
+  };
+};
+
+export default useTable;

+ 162 - 173
src/views/material/index.vue

@@ -6,16 +6,16 @@
       :inline="true"
       v-show="showSearch"
     >
-      <el-form-item label="物料名称" prop="toolName">
+      <el-form-item label="工具品种" prop="toolName">
         <el-input
           v-model="queryParams.toolName"
-          placeholder="请输入物料名称"
+          placeholder="请输入工具品种"
           clearable
           style="width: 200px"
           @keyup.enter="handleQuery"
         />
       </el-form-item>
-      <el-form-item label="一级类型" prop="levelOneTypeId">
+      <el-form-item label="大类" prop="levelOneTypeId">
         <el-select
           v-model="queryParams.levelOneTypeId"
           placeholder="请选择"
@@ -31,7 +31,7 @@
           />
         </el-select>
       </el-form-item>
-      <el-form-item label="二级类" prop="levelTwoTypeId">
+      <el-form-item label="二级类" prop="levelTwoTypeId">
         <el-select
           v-model="queryParams.levelTwoTypeId"
           placeholder="请选择"
@@ -56,12 +56,7 @@
 
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button
-          type="primary"
-          plain
-          icon="Plus"
-          @click="handleAdd"
-          v-hasPermi="['system:post:add']"
+        <el-button type="primary" plain icon="Plus" @click="handleAdd"
           >新增</el-button
         >
       </el-col>
@@ -71,8 +66,7 @@
           plain
           icon="Edit"
           :disabled="single"
-          @click="handleUpdate"
-          v-hasPermi="['system:post:edit']"
+          @click="handleSelecterUpdate"
           >修改</el-button
         >
       </el-col>
@@ -83,7 +77,6 @@
           icon="Delete"
           :disabled="multiple"
           @click="handleDelete"
-          v-hasPermi="['system:post:remove']"
           >删除</el-button
         >
       </el-col>
@@ -99,13 +92,15 @@
     >
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column label="工具编号" align="center" prop="id" />
-      <el-table-column label="工具名称" align="center" prop="toolName" />
-      <el-table-column label="工具规格" align="center" prop="specifications" />
+      <el-table-column label="工具品种" align="center" prop="toolName" />
+      <el-table-column label="工具别名" align="center" prop="aliasName" />
+      <el-table-column label="规格标准" align="center" prop="specifications" />
+      <el-table-column label="举例" align="center" prop="example" />
       <el-table-column label="描述" align="center" prop="describe" />
       <el-table-column label="数量" align="center" prop="toolNum" />
       <el-table-column
         label="操作"
-        width="180"
+        width="240"
         align="center"
         class-name="small-padding fixed-width"
       >
@@ -118,6 +113,14 @@
             v-hasPermi="['system:post:edit']"
             >修改</el-button
           >
+          <el-button
+            link
+            type="primary"
+            icon="Edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['system:post:edit']"
+            >物料管理</el-button
+          >
           <el-button
             link
             type="primary"
@@ -138,41 +141,112 @@
       @pagination="getList"
     />
     <!-- 添加或修改岗位对话框 -->
-    <el-dialog :title="title" v-model="open" width="500px" append-to-body>
-      <el-form ref="postRef" :model="form" :rules="rules" label-width="80px">
-        <el-form-item label="物料名称" prop="postName">
-          <el-input v-model="form.postName" placeholder="请输入岗位名称" />
+    <el-dialog
+      :title="title"
+      v-model="open"
+      width="66vw"
+      append-to-body
+      :close-on-click-modal="false"
+    >
+      <el-form
+        ref="toolRef"
+        :model="form"
+        :rules="rules"
+        label-width="120px"
+        v-loading="formLoading"
+      >
+        <el-form-item label="工具品种" prop="toolName">
+          <el-input v-model="form.toolName" placeholder="请输入工具品种" />
         </el-form-item>
-        <el-form-item label="岗位编码" prop="postCode">
-          <el-input v-model="form.postCode" placeholder="请输入编码名称" />
+        <el-form-item label="工具别称" prop="aliasName">
+          <el-input v-model="form.aliasName" placeholder="请输入工具别称" />
         </el-form-item>
-        <el-form-item label="岗位顺序" prop="postSort">
+        <el-form-item label="大类" prop="levelOneId">
+          <el-select
+            v-model="form.levelOneId"
+            placeholder="请选择"
+            clearable
+            style="width: 200px"
+            @change="handleChangeSubmitFormLevelType"
+          >
+            <el-option
+              v-for="dict in levelOneDict"
+              :key="dict.id"
+              :label="dict.label"
+              :value="dict.id"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="二级分类" prop="levelTwoId">
+          <el-select
+            v-model="form.levelTwoId"
+            placeholder="请选择"
+            clearable
+            style="width: 200px"
+          >
+            <el-option
+              v-for="dict in submitFormLevelTwoDict"
+              :key="dict.id"
+              :label="dict.label"
+              :value="dict.id"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="工具描述" prop="describe">
+          <el-input
+            v-model="form.describe"
+            type="textarea"
+            placeholder="请输入内容"
+          />
+        </el-form-item>
+        <el-form-item label="工具数量" prop="toolNum">
           <el-input-number
-            v-model="form.postSort"
-            controls-position="right"
+            v-model="form.toolNum"
             :min="0"
+            :step="1"
+            step-strictly
           />
         </el-form-item>
-        <el-form-item label="岗位状态" prop="status">
-          <el-radio-group v-model="form.status">
-            <el-radio
-              v-for="dict in sys_normal_disable"
-              :key="dict.value"
-              :label="dict.value"
-              >{{ dict.label }}</el-radio
-            >
-          </el-radio-group>
+        <el-form-item label="规格说明" prop="specifications">
+          <el-input
+            v-model="form.specifications"
+            type="textarea"
+            placeholder="请输入内容"
+          />
         </el-form-item>
-        <el-form-item label="备注" prop="remark">
+        <el-form-item label="举例" prop="example">
           <el-input
-            v-model="form.remark"
+            v-model="form.example"
             type="textarea"
             placeholder="请输入内容"
           />
         </el-form-item>
+        <el-form-item label="示意图" prop="imageList">
+          <FileUpload
+            v-model="form.imageList"
+            :fileType="['png', 'jpg', 'jpeg']"
+            :fileSize="20"
+            :limit="5"
+            imageMode
+          />
+        </el-form-item>
+        <el-form-item label="使用手册" prop="manualFileList">
+          <FileUpload
+            v-model="form.manualFileList"
+            :fileSize="10"
+            :limit="10"
+          />
+        </el-form-item>
+        <el-form-item label="附件资料" prop="resourceFileList">
+          <FileUpload
+            v-model="form.resourceFileList"
+            :fileSize="10"
+            :limit="10"
+          />
+        </el-form-item>
       </el-form>
       <template #footer>
-        <div class="dialog-footer">
+        <div style="text-align: center">
           <el-button type="primary" @click="submitForm">确 定</el-button>
           <el-button @click="cancel">取 消</el-button>
         </div>
@@ -182,6 +256,10 @@
 </template>
 
 <script setup name="Material">
+import useSearchForm from "./hooks/useSearchForm.js";
+import useSubmitForm from "./hooks/useSubmitForm.js";
+import useTable from "./hooks/useTable.js";
+
 import {
   listPost,
   addPost,
@@ -193,43 +271,12 @@ import { listTools, queryToolDict } from "@/api/bussiness";
 
 const { proxy } = getCurrentInstance();
 
-const toolList = ref([]);
-const open = ref(false);
-const loading = ref(true);
 const showSearch = ref(true);
-const ids = ref([]);
-const single = ref(true);
-const multiple = ref(true);
-const total = ref(0);
-const title = ref("");
-const levelOneDict = ref([]);
-const levelTwoDict = ref([]);
-
-const data = reactive({
-  form: {},
-  queryParams: {
-    toolName: "",
-    levelOneTypeId: "",
-    levelTwoTypeId: "",
-  },
-  pager: {
-    pageNum: 1,
-    pageSize: 10,
-  },
-  rules: {
-    // postName: [
-    //   { required: true, message: "岗位名称不能为空", trigger: "blur" },
-    // ],
-    // postCode: [
-    //   { required: true, message: "岗位编码不能为空", trigger: "blur" },
-    // ],
-    // postSort: [
-    //   { required: true, message: "岗位顺序不能为空", trigger: "blur" },
-    // ],
-  },
+const pager = ref({
+  pageNum: 1,
+  pageSize: 10,
 });
-
-const { queryParams, pager, form, rules } = toRefs(data);
+const total = ref(0);
 
 /** 查询岗位列表 */
 const getList = (params = {}) => {
@@ -247,115 +294,57 @@ const getList = (params = {}) => {
     loading.value = false;
   });
 };
-
+const levelOneDict = ref([]);
 /** 获取一级分类字典 */
 const updateTypeOneDict = () => {
   queryToolDict("1").then((data) => {
     levelOneDict.value = data || [];
   });
 };
+updateTypeOneDict();
 
-const handleChangeLevelOneType = (val) => {
-  queryParams.value.levelTwoTypeId = ""
-  if (val) {
-    queryToolDict("2", val).then((data) => {
-      levelTwoDict.value = data || [];
-    });
-  } else {
-    levelTwoDict.value = [];
-  }
-};
+const {
+  queryParams,
+  levelTwoDict,
+  handleChangeLevelOneType,
+  handleQuery,
+  resetQuery,
+} = useSearchForm(getList);
 
-/** 取消按钮 */
-const cancel = () => {
-  open.value = false;
-  reset();
-};
-/** 表单重置 */
-const reset = () => {
-  form.value = {
-    postId: undefined,
-    postCode: undefined,
-    postName: undefined,
-    postSort: 0,
-    status: "0",
-    remark: undefined,
-  };
-  proxy.resetForm("postRef");
-};
+const {
+  form,
+  rules,
+  open,
+  title,
+  formLoading,
+  submitFormLevelTwoDict,
+  submitForm,
+  cancel,
+  reset,
+  handleChangeSubmitFormLevelType,
+} = useSubmitForm(getList);
+
+const {
+  toolList,
+  loading,
+  single,
+  multiple,
+  handleSelectionChange,
+  handleAdd,
+  handleUpdate,
+  handleDelete,
+  handleSelecterUpdate
+} = useTable(
+  open,
+  title,
+  form,
+  formLoading,
+  submitFormLevelTwoDict,
+  queryParams,
+  getList,
+  updateTypeOneDict,
+  reset
+);
 
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  const params = {
-    toolName: queryParams.value.toolName || "",
-    parentId:
-      queryParams.value.levelTwoTypeId ||
-      queryParams.value.levelOneTypeId ||
-      undefined,
-  };
-  getList(params);
-};
-/** 重置按钮操作 */
-const resetQuery = () => {
-  proxy.resetForm("queryRef");
-  handleQuery();
-};
-/** 多选框选中数据 */
-const handleSelectionChange = (selection) => {
-  ids.value = selection.map((item) => item.postId);
-  single.value = selection.length != 1;
-  multiple.value = !selection.length;
-};
-/** 新增按钮操作 */
-const handleAdd = () => {
-  reset();
-  open.value = true;
-  title.value = "添加岗位";
-};
-/** 修改按钮操作 */
-const handleUpdate = (row) => {
-  reset();
-  const postId = row.postId || ids.value;
-  getPost(postId).then((response) => {
-    form.value = response.data;
-    open.value = true;
-    title.value = "修改岗位";
-  });
-};
-/** 提交按钮 */
-const submitForm = () => {
-  proxy.$refs["postRef"].validate((valid) => {
-    if (valid) {
-      if (form.value.postId != undefined) {
-        updatePost(form.value).then((response) => {
-          proxy.$modal.msgSuccess("修改成功");
-          open.value = false;
-          getList(queryParams.value);
-        });
-      } else {
-        addPost(form.value).then((response) => {
-          proxy.$modal.msgSuccess("新增成功");
-          open.value = false;
-          getList(queryParams.value);
-        });
-      }
-    }
-  });
-};
-/** 删除按钮操作 */
-const handleDelete = (row) => {
-  const postIds = row.postId || ids.value;
-  proxy.$modal
-    .confirm('是否确认删除岗位编号为"' + postIds + '"的数据项?')
-    .then(function () {
-      return delPost(postIds);
-    })
-    .then(() => {
-      getList(queryParams.value);
-      proxy.$modal.msgSuccess("删除成功");
-    })
-    .catch(() => {});
-};
-updateTypeOneDict();
 getList(queryParams.value);
 </script>