yongCode пре 5 месеци
родитељ
комит
cb5943254f
5 измењених фајлова са 133 додато и 82 уклоњено
  1. 0 1
      src/utils/index.js
  2. 19 2
      src/utils/request.js
  3. 16 14
      src/views/DetailView.vue
  4. 79 45
      src/views/HomeView.vue
  5. 19 20
      vite.config.js

+ 0 - 1
src/utils/index.js

@@ -19,7 +19,6 @@ export const getFillNums = (selectorName, list, width) => {
       const clientWidth = target.clientWidth
       // 每行最多有几个
       const rowMaxNum = Math.floor(clientWidth / width)
-      console.log(rowMaxNum)
       resolve(list.length % rowMaxNum === 0 ? 0 : rowMaxNum - (list.length % rowMaxNum))
     }
   })

+ 19 - 2
src/utils/request.js

@@ -1,7 +1,12 @@
 import axios from 'axios'
-
+import { ElMessage } from 'element-plus'
 axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
-
+const errorCode = {
+  '401': '认证失败,无法访问系统资源',
+  '403': '当前操作没有权限',
+  '404': '访问资源不存在',
+  'default': '系统未知错误,请反馈给管理员'
+}
 // 创建axios实例
 const service = axios.create({
   // axios中请求配置有baseURL选项,表示请求URL公共部分
@@ -15,11 +20,14 @@ service.interceptors.response.use(
   (res) => {
     // 未设置状态码则默认成功状态
     const code = res.data.code || 200
+    // 获取错误信息
+    const msg = errorCode[code] || res.data.msg || errorCode['default']
     // 二进制数据则直接返回
     if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
       return res.data
     }
     if (code !== 200) {
+      ElMessage({ message: msg, type: 'error' })
       return Promise.reject('error')
     } else {
       return Promise.resolve(res.data)
@@ -27,6 +35,15 @@ service.interceptors.response.use(
   },
   (error) => {
     console.log('err' + error)
+    let { message } = error;
+    if (message == "Network Error") {
+      message = "后端接口连接异常";
+    } else if (message.includes("timeout")) {
+      message = "系统接口请求超时";
+    } else if (message.includes("Request failed with status code")) {
+      message = "系统接口" + message.substr(message.length - 3) + "异常";
+    }
+    ElMessage({ message: message, type: 'error', duration: 5 * 1000 })
     return Promise.reject(error)
   }
 )

+ 16 - 14
src/views/DetailView.vue

@@ -6,7 +6,7 @@
       ></div>
       <div class="relative z-1 p-4 w-full md:w-[1280px] mx-auto">
         <div
-          class="font-['PingFang-Heavy'] px-3 font-semibold text-xl md:text-[32px] md:leading-tight"
+          class="font-['PingFang-Heavy'] px-3 mibold text-xl md:text-[32px] md:leading-tight"
         >
           工具数字化展示
         </div>
@@ -53,7 +53,7 @@
             <div
               class="font-['PingFang-Heavy'] font-semibold text-xl md:text-[20px] md:leading-tight"
             >
-              {{ queryToolName }}
+              {{ toolInfoRef.toolName }}
             </div>
             <div
               class="bg-[#E6F7FF] border border-[#004EA2] rounded px-3 text-[#004EA2] text-center mt-9 font-normal text-xs w-[200px] h-[22px] leading-[22px] truncate"
@@ -123,10 +123,17 @@
                 />
               </div>
             </div>
-
-            <div class="font-['PingFang-SC'] text-sm font-normal mt-10">
-              <div>附件:</div>
-              <van-cell-group>
+            <div class="font-['PingFang-SC'] text-sm font-normal mt-4">
+              <div class="font-semibold">标准规格说明:</div>
+              <div>{{ toolInfoRef.specifications }}</div>
+            </div>
+            <div class="font-['PingFang-SC'] text-sm font-normal mt-4">
+              <div class="font-semibold">举例:</div>
+              <div>{{ toolInfoRef.example }}</div>
+            </div>
+            <div class="font-['PingFang-SC'] text-sm font-normal mt-4">
+              <div class="font-semibold">附件:</div>
+              <van-cell-group v-if="fileList.length > 0">
                 <van-cell v-for="file in fileList" :key="file.id">
                   <template #title>
                     <span class="cursor-pointer" @click="fileDownload(file)">{{
@@ -143,6 +150,7 @@
                   </template>
                 </van-cell>
               </van-cell-group>
+              <van-empty v-else image-size="100" description="暂无数据" />
             </div>
           </div>
         </div>
@@ -163,7 +171,6 @@ import { ElMessage } from 'element-plus'
 const router = useRouter()
 const route = useRoute()
 const queryId = ref(route.query.id)
-const queryToolName = ref(route.query.toolName)
 
 const wlList = ref([])
 // const wlSelectId = ref(0)
@@ -176,6 +183,7 @@ const sytPath = ref('')
 const devPath = import.meta.env.VITE_APP_BASE_API
 const breadTitle = ref('')
 const typeOptions1Ref = ref([])
+const toolInfoRef = ref({})
 
 // 物料搜索相关参数
 const queryParams = ref({
@@ -198,13 +206,7 @@ const init = () => {
   // 查详情
   detailList({ id: queryId.value }).then((res) => {
     const toolDetails = res.data.toolDetails || []
-    // wlList.value = toolDetails.filter((item) => item.informationType === 'wl')
-    // // console.log(wlList.value)
-    // if (wlList.value.length > 0) {
-    //   // selectWlCode.value = wlList.value[0].materialNo
-    //   // selectMaterialName.value = wlList.value[0].materialName
-    //   wlSelectId.value = wlList.value[0].id
-    // }
+    toolInfoRef.value = res.data.toolData || {}
     sytList.value = toolDetails.filter((item) => item.informationType === 'syt')
     if (sytList.value.length > 0) {
       detailImg.value = sytList.value[0].id

+ 79 - 45
src/views/HomeView.vue

@@ -55,13 +55,13 @@
               <van-dropdown-item
                 v-model="type1ValueRef"
                 :options="dropdownTypeOptions1"
-                title="一级分类"
+                :title="type1DropMenuTextRef === '全部' ? '一级分类' : type1DropMenuTextRef"
                 @change="handleChangeDropdownOfType1"
               />
               <van-dropdown-item
                 v-model="type2ValueRef"
                 :options="dropdownTypeOptions2"
-                title="二级分类"
+                :title="type2DropMenuTextRef === '全部' ? '二级分类' : type2DropMenuTextRef"
                 @change="handleChangeDropdownOfType2"
               />
             </van-dropdown-menu>
@@ -108,31 +108,38 @@
       finished-text="没有更多了"
       @load="onLoad"
     >
-      <div class="tool-card-content w-full px-4 flex flex-wrap md:max-w-[1440px] mx-auto">
-        <div class="tool-card" v-for="item in toolsListRef" :key="item" @click="handleDetail(item)">
-          <el-image class="tool-img" :src="`${devPath + item.picturePath}`" fit="contain">
-            <template #error>
-              <div class="w-full h-full flex items-center justify-center">
-                <van-icon name="photo-fail" color="#dcdee0" size="32" />
+      <div class="w-full px-4 ">
+        <div class="tool-card-content w-full flex flex-wrap mx-auto md:max-w-[1440px]">
+          <div
+            class="tool-card"
+            v-for="item in toolsListRef"
+            :key="item"
+            @click="handleDetail(item)"
+          >
+            <el-image class="tool-img" :src="`${devPath + item.picturePath}`" fit="contain">
+              <template #error>
+                <div class="w-full h-full flex items-center justify-center">
+                  <van-icon name="photo-fail" color="#dcdee0" size="32" />
+                </div>
+              </template>
+            </el-image>
+            <div class="px-3 pt-2 flex-1 flex flex-col">
+              <div class="font-[PingFang-Heavy] truncate">{{ item.toolName }}</div>
+              <div class="text-[#585F66] text-xs mt-1 line-clamp-2 break-all">
+                {{ item.describe }}
+              </div>
+              <div class="flex-1 flex items-center justify-end" v-if="+item.toolNum">
+                <span class="text-2xl font-['DIN'] font-semibold text-[#004EA2]">{{
+                  item.toolNum
+                }}</span>
+                <span class="text-sm font-['PingFang-Heavy'] font-semibold ml-1 text-[#004EA2]"
+                  >件</span
+                >
               </div>
-            </template>
-          </el-image>
-          <div class="px-3 pt-2 flex-1 flex flex-col">
-            <div class="font-[PingFang-Heavy] truncate">{{ item.toolName }}</div>
-            <div class="text-[#585F66] text-xs mt-1 line-clamp-2 break-all">
-              {{ item.describe }}
-            </div>
-            <div class="flex-1 flex items-center justify-end" v-if="+item.toolNum">
-              <span class="text-2xl font-['DIN'] font-semibold text-[#004EA2]">{{
-                item.toolNum
-              }}</span>
-              <span class="text-sm font-['PingFang-Heavy'] font-semibold ml-1 text-[#004EA2]"
-                >件</span
-              >
             </div>
           </div>
+          <div class="tool-card-none" v-for="item in noneCardNum" :key="item"></div>
         </div>
-        <div class="tool-card-none" v-for="item in noneCardNum" :key="item"></div>
       </div>
     </van-list>
     <van-back-top />
@@ -164,6 +171,9 @@ const hotToolsRef = ref([])
 
 const type1ValueRef = ref('')
 const type2ValueRef = ref('')
+// 下拉选择的文本
+const type1DropMenuTextRef = ref('全部')
+const type2DropMenuTextRef = ref('全部')
 // 分类列表1级
 const typeOptions1Ref = ref([])
 // 分类列表2级
@@ -199,27 +209,42 @@ const noneCardNum = ref(0)
 const onLoad = (value) => {
   listTools({
     level: '3',
-    parentId: value,
+    // 优先级,指定的 parentId > 二级分类 id > 一级分类 id > null
+    parentId: value || type2ValueRef.value || type1ValueRef.value || null,
     toolName: searchValueRef.value,
     pageNum: pageNum.value,
     pageSize: pageSize.value,
     delFlag: 0
   }).then((res) => {
-    toolsListRef.value = toolsListRef.value.concat(res.rows)
+    if (pageNum.value === 1) {
+      toolsListRef.value = res.rows
+      pageNum.value = 2
+    } else {
+      toolsListRef.value = toolsListRef.value.concat(res.rows)
+      pageNum.value += 1
+    }
     //  加载状态结束
     loadingRef.value = false
-
-    pageNum.value += 1
     if (res.rows.length < pageSize.value) finished.value = true
     else finished.value = false
     getFillNums('.tool-card-content', toolsListRef.value, device.value === 'pc' ? 220 : 165).then(
       (nums) => {
-        console.log('getFillNums', nums)
+        // console.log('getFillNums', nums)
         noneCardNum.value = nums
       }
     )
   })
 }
+const getType2Tools = (value) => {
+  listTools({
+    level: '2',
+    parentId: value,
+    pageSize: 999
+  }).then((res) => {
+    typeOptions2Ref.value = res.rows
+  })
+}
+
 const init = () => {
   loadingRef.value = true
   // 一级分类
@@ -230,27 +255,21 @@ const init = () => {
   })
   type1ValueRef.value = route.query.id ? Number(route.query.id) : ''
   type2ValueRef.value = ''
-  // 二级分类
-  // listTools({
-  //   level: '2',
-  //   parentId: route.query.id ? route.query.id : '',
-  //   pageSize: 999
-  // }).then((res) => {
-  //   typeOptions2Ref.value = res.rows
-  // })
+  if (type1ValueRef.value) {
+    getType2Tools(type1ValueRef.value)
+  }
   onLoad(route.query.id)
   // 常用工具列表
   getCommonTool().then((res) => {
     hotToolsRef.value = res.data.data.length > 10 ? res.data.data.slice(0, 10) : res.data.data
   })
 }
-init()
 
 // 搜索
 const handleSearch = (pId = '') => {
   if (loadingRef.value) return
-  toolsListRef.value = []
   pageNum.value = 1
+  // toolsListRef.value = []
   onLoad(pId)
   // 每次搜索时存一下搜索内容的次数,方便后台统计常用工具
   searchValueRef.value && setCommonTool({ toolName: searchValueRef.value })
@@ -258,20 +277,25 @@ const handleSearch = (pId = '') => {
 // 点击热门关键字搜索
 const handleKeySearch = (toolName) => {
   searchValueRef.value = toolName
-  toolsListRef.value = []
   handleSearch()
 }
 
 // 点击一级菜单
 const handleChangeDropdownOfType1 = (value) => {
-  // resetList()
+  if (loadingRef.value) return
   // 取消勾选
-  if (type1ValueRef.value === value && device.value === "pc") {
+  if (type1ValueRef.value === value && device.value === 'pc') {
     type1ValueRef.value = ''
+    type2ValueRef.value = ''
     typeOptions2Ref.value = []
     handleSearch()
   } else {
     type1ValueRef.value = value
+    if (device.value === 'phone') {
+      type2DropMenuTextRef.value = '全部'
+      const targetOfDropDownItem = dropdownTypeOptions1.value.find((item) => item.value == value)
+      type1DropMenuTextRef.value = targetOfDropDownItem.text
+    }
     listTools({
       level: '2',
       parentId: value,
@@ -279,18 +303,23 @@ const handleChangeDropdownOfType1 = (value) => {
     }).then((res) => {
       typeOptions2Ref.value = res.rows
     })
+
     handleSearch(value)
   }
   type2ValueRef.value = value
 }
 // 点击二级菜单
 const handleChangeDropdownOfType2 = (value) => {
-  // resetList()
+  if (loadingRef.value) return
   // 取消勾选
-  if (type2ValueRef.value === value && device.value === "pc") {
+  if (type2ValueRef.value === value && device.value === 'pc') {
     type2ValueRef.value = ''
     handleSearch(type1ValueRef.value)
   } else {
+    if (device.value === 'phone') {
+      const targetOfDropDownItem = dropdownTypeOptions2.value.find((item) => item.value == value)
+      type2DropMenuTextRef.value = targetOfDropDownItem.text
+    }
     type2ValueRef.value = value
     handleSearch(value)
   }
@@ -301,8 +330,10 @@ const handleClear = () => {
   handleSearch()
 }
 const handleDetail = (row) => {
-  router.push({ path: '/detail', query: { id: row.id, toolName: row.toolName } })
+  router.push({ path: '/detail', query: { id: row.id } })
 }
+
+init()
 </script>
 
 <style lang="scss" scoped>
@@ -313,9 +344,12 @@ const handleDetail = (row) => {
   @apply flex-1 flex flex-wrap;
 }
 .menu-item {
-  @apply pl-6 py-1 cursor-pointer;
+  @apply pl-3 pr-3 py-1 cursor-pointer text-center font-semibold;
   &.active {
     color: #004ea2;
+    background-color: #dee6ef;
+    border: 1px solid #004ea2;
+    border-radius: 4px;
   }
 }
 

+ 19 - 20
vite.config.js

@@ -1,6 +1,6 @@
 import { fileURLToPath, URL } from 'node:url'
 
-import { defineConfig , loadEnv} from 'vite'
+import { defineConfig, loadEnv } from 'vite'
 import vue from '@vitejs/plugin-vue'
 import VueDevTools from 'vite-plugin-vue-devtools'
 import VueSetupExtend from 'vite-plugin-vue-setup-extend'
@@ -16,25 +16,24 @@ const createAutoImport = () => {
 }
 // https://vitejs.dev/config/
 export default defineConfig(({ mode }) => {
-  const env = loadEnv(mode, process.cwd());
-console.log(env)
+  const env = loadEnv(mode, process.cwd())
+  console.log(mode, env)
+  const plugins = [
+    vue(),
+    VueSetupExtend(),
+    createAutoImport(),
+    AutoImport({
+      resolvers: [VantResolver()]
+    }),
+    Components({
+      resolvers: [VantResolver()]
+    })
+  ]
+  if (mode === 'development') {
+    plugins.push(VueDevTools())
+  }
   return {
-    base: mode === 'development' ? '/' : '/web',
-    build: {
-      outDir: 'web'
-    },
-    plugins: [
-      vue(),
-      // VueDevTools(),
-      VueSetupExtend(),
-      createAutoImport(),
-      AutoImport({
-        resolvers: [VantResolver()]
-      }),
-      Components({
-        resolvers: [VantResolver()]
-      })
-    ],
+    plugins: plugins,
     resolve: {
       alias: {
         '@': fileURLToPath(new URL('./src', import.meta.url))
@@ -44,7 +43,7 @@ console.log(env)
       host: true,
       proxy: {
         '/dev-api': {
-          target: 'http://172.16.10.61:8080',
+          target: 'http://172.16.10.61:8080/prod-api',
           // target: 'https://vue.ruoyi.vip/prod-api',
           changeOrigin: true,
           rewrite: (p) => p.replace(/^\/dev-api/, '')