weixin_52219567 3 місяців тому
батько
коміт
9ca6e65598
40 змінених файлів з 6275 додано та 261 видалено
  1. 14 0
      package-lock.json
  2. 18 0
      src/api/plan/index.ts
  3. 39 0
      src/api/search/index.ts
  4. BIN
      src/assets/images/home/indexFuli1.png
  5. BIN
      src/assets/images/home/indexFuli2.png
  6. BIN
      src/assets/images/home/indexMro1.png
  7. BIN
      src/assets/images/home/indexMro2.png
  8. BIN
      src/assets/images/home/indexMro3.png
  9. BIN
      src/assets/images/pay/pay1.png
  10. BIN
      src/assets/images/pay/pay2.png
  11. BIN
      src/assets/images/pay/pay3.png
  12. BIN
      src/assets/images/pay/pay4.png
  13. BIN
      src/assets/images/pay/pay5.png
  14. BIN
      src/assets/images/pay/pay6.png
  15. 1 0
      src/assets/styles/common.scss
  16. 1 1
      src/assets/styles/ruoyi.scss
  17. 134 0
      src/components/Pagination/index.vue
  18. 2 4
      src/layout/components/breadcrumb.vue
  19. 212 11
      src/layout/components/nav.vue
  20. 2 2
      src/layout/components/search.vue
  21. 59 5
      src/router/index.ts
  22. 28 0
      src/store/modules/category.ts
  23. 4 4
      src/utils/siteConfig.ts
  24. 28 9
      src/views/cart/index.vue
  25. 720 4
      src/views/home/index-fuli.vue
  26. 821 4
      src/views/home/index-mro.vue
  27. 1392 4
      src/views/home/index.vue
  28. 129 106
      src/views/item/index.vue
  29. 34 5
      src/views/payc/index.vue
  30. 361 0
      src/views/plan/guide.vue
  31. 376 0
      src/views/plan/procure.vue
  32. 371 0
      src/views/plan/project.vue
  33. 184 0
      src/views/plan_info/guide.vue
  34. 273 0
      src/views/plan_info/procure.vue
  35. 149 0
      src/views/plan_info/project.vue
  36. 296 0
      src/views/search/brand.vue
  37. 162 29
      src/views/search/index.vue
  38. 320 0
      src/views/search/special.vue
  39. 29 13
      src/views/solve/real.vue
  40. 116 60
      src/views/trad/index.vue

+ 14 - 0
package-lock.json

@@ -18,6 +18,7 @@
         "axios": "1.13.1",
         "crypto-js": "4.2.0",
         "echarts": "5.6.0",
+        "element-china-area-data": "^6.1.0",
         "element-plus": "2.11.7",
         "file-saver": "2.0.5",
         "highlight.js": "11.11.1",
@@ -3859,6 +3860,11 @@
         "node": ">= 16"
       }
     },
+    "node_modules/china-division": {
+      "version": "2.7.0",
+      "resolved": "https://registry.npmmirror.com/china-division/-/china-division-2.7.0.tgz",
+      "integrity": "sha512-4uUPAT+1WfqDh5jytq7omdCmHNk3j+k76zEG/2IqaGcYB90c2SwcixttcypdsZ3T/9tN1TTpBDoeZn+Yw/qBEA=="
+    },
     "node_modules/chokidar": {
       "version": "4.0.3",
       "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-4.0.3.tgz",
@@ -4276,6 +4282,14 @@
       "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==",
       "dev": true
     },
+    "node_modules/element-china-area-data": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmmirror.com/element-china-area-data/-/element-china-area-data-6.1.0.tgz",
+      "integrity": "sha512-IkpcjwQv2A/2AxFiSoaISZ+oMw1rZCPUSOg5sOCwT5jKc96TaawmKZeY81xfxXsO0QbKxU5LLc6AirhG52hUmg==",
+      "dependencies": {
+        "china-division": "^2.7.0"
+      }
+    },
     "node_modules/element-plus": {
       "version": "2.11.7",
       "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.11.7.tgz",

+ 18 - 0
src/api/plan/index.ts

@@ -52,6 +52,15 @@ export function getCustomerIndustry(query: any) {
   });
 }
 
+// 项目类型
+export function getProjectTypeList(query: any) {
+  return request({
+    url: '/system/indexSystem/getProjectTypeList',
+    method: 'get',
+    params: query
+  });
+}
+
 // 适配场景列表
 export function getAdaptSceneList(query: any) {
   return request({
@@ -116,3 +125,12 @@ export function getProjectCaseDetail(id: any) {
     method: 'get'
   });
 }
+
+// 咨迅详情
+
+export function getYouYzXunInfo(id: any) {
+  return request({
+    url: '/system/indexSystem/getYouYiZiXunInfo/' + id,
+    method: 'get'
+  });
+}

+ 39 - 0
src/api/search/index.ts

@@ -17,3 +17,42 @@ export const getBrandPage = (query: any) => {
     params: query
   });
 };
+
+//特价商品分类
+export const getSpecialCategoryList = (query: any) => {
+  return request({
+    url: '/product/indexProduct/getSpecialCategoryList',
+    method: 'get',
+    params: query
+  });
+};
+
+
+//特价商品品牌
+export const getSpecialBrandList = (query: any) => {
+  return request({
+    url: '/product/indexProduct/getSpecialBrandList',
+    method: 'get',
+    params: query
+  });
+};
+
+//特价商品
+
+export const getSpecialProductList = (query: any) => {
+  return request({
+    url: '/product/indexProduct/getSpecialProductList',
+    method: 'get',
+    params: query
+  });
+};
+
+//通过分类去查询品牌
+
+export const getBrandByCategoryList = (query: any) => {
+  return request({
+    url: '/product/indexProduct/getBrandByCategoryList',
+    method: 'get',
+    params: query
+  });
+};

BIN
src/assets/images/home/indexFuli1.png


BIN
src/assets/images/home/indexFuli2.png


BIN
src/assets/images/home/indexMro1.png


BIN
src/assets/images/home/indexMro2.png


BIN
src/assets/images/home/indexMro3.png


BIN
src/assets/images/pay/pay1.png


BIN
src/assets/images/pay/pay2.png


BIN
src/assets/images/pay/pay3.png


BIN
src/assets/images/pay/pay4.png


BIN
src/assets/images/pay/pay5.png


BIN
src/assets/images/pay/pay6.png


+ 1 - 0
src/assets/styles/common.scss

@@ -12,6 +12,7 @@
 .inline-block{display: inline-block;}
 
 .ellipsis{overflow: hidden;white-space: nowrap;text-overflow: ellipsis;}
+.ellipsis2{display: -webkit-box;-webkit-line-clamp: 2;line-clamp: 2; /* 添加标准属性 */-webkit-box-orient: vertical;overflow: hidden;text-overflow: ellipsis;}
 
 
   //分页

+ 1 - 1
src/assets/styles/ruoyi.scss

@@ -227,7 +227,7 @@ h6 {
 }
 
 .text-primary {
-  color: inherit;
+  color: var(--el-color-primary);
 }
 
 .text-success {

+ 134 - 0
src/components/Pagination/index.vue

@@ -0,0 +1,134 @@
+<template>
+  <div :class="{ hidden: hidden }" class="pagination-container">
+    <!-- 游标分页模式 -->
+    <div v-if="cursorMode" class="cursor-pagination">
+      <el-button :disabled="currentPage === 1" @click="handlePrevPage"> 上一页 </el-button>
+      <span class="page-info">第 {{ currentPage }} 页</span>
+      <el-button :disabled="!hasMore" @click="handleNextPage"> 下一页 </el-button>
+      <el-select v-model="pageSize" @change="handleSizeChange" style="width: 100px" class="ml-2">
+        <el-option v-for="size in pageSizes" :key="size" :label="`${size}条/页`" :value="size" />
+      </el-select>
+    </div>
+
+    <!-- 传统分页模式 -->
+    <el-pagination
+      v-else
+      v-model:current-page="currentPage"
+      v-model:page-size="pageSize"
+      :background="background"
+      :layout="layout"
+      :page-sizes="pageSizes"
+      :pager-count="pagerCount"
+      :total="total"
+      @size-change="handleSizeChange"
+      @current-change="handleCurrentChange"
+    />
+  </div>
+</template>
+
+<script setup name="Pagination" lang="ts">
+import { scrollTo } from '@/utils/scroll-to';
+import { propTypes } from '@/utils/propTypes';
+
+const props = defineProps({
+  total: propTypes.number,
+  page: propTypes.number.def(1),
+  limit: propTypes.number.def(20),
+  way: propTypes.number.def(1),
+  pageSizes: { type: Array<number>, default: () => [10, 20, 30, 50] },
+  // 移动端页码按钮的数量端默认值5
+  pagerCount: propTypes.number.def(document.body.clientWidth < 992 ? 5 : 7),
+  layout: propTypes.string.def('total, sizes, prev, pager, next, jumper'),
+  background: propTypes.bool.def(true),
+  autoScroll: propTypes.bool.def(true),
+  hidden: propTypes.bool.def(false),
+  float: propTypes.string.def('right'),
+  // 游标分页模式
+  cursorMode: propTypes.bool.def(false),
+  // 是否还有更多数据(游标分页使用)
+  hasMore: propTypes.bool.def(true)
+});
+
+const emit = defineEmits(['update:page', 'update:limit', 'update:way', 'pagination']);
+const currentPage = computed({
+  get() {
+    return props.page;
+  },
+  set(val) {
+    emit('update:page', val);
+  }
+});
+const pageSize = computed({
+  get() {
+    return props.limit;
+  },
+  set(val) {
+    emit('update:limit', val);
+  }
+});
+function handleSizeChange(val: number) {
+  if (!props.cursorMode && currentPage.value * val > props.total) {
+    currentPage.value = 1;
+  }
+  emit('pagination', { page: currentPage.value, limit: val });
+  if (props.autoScroll) {
+    scrollTo(0, 800);
+  }
+}
+function handleCurrentChange(val: number) {
+  emit('pagination', { page: val, limit: pageSize.value });
+  if (props.autoScroll) {
+    scrollTo(0, 800);
+  }
+}
+// 游标分页:下一页
+function handleNextPage() {
+  if (props.hasMore) {
+    currentPage.value += 1;
+    emit('update:way', 1);
+    emit('pagination', { page: currentPage.value, limit: pageSize.value, way: 1 });
+    if (props.autoScroll) {
+      scrollTo(0, 800);
+    }
+  }
+}
+// 游标分页:上一页
+function handlePrevPage() {
+  if (currentPage.value > 1) {
+    currentPage.value -= 1;
+    emit('update:way', 0);
+    emit('pagination', { page: currentPage.value, limit: pageSize.value, way: 0 });
+    if (props.autoScroll) {
+      scrollTo(0, 800);
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.pagination-container {
+  .el-pagination {
+    float: v-bind(float);
+  }
+
+  .cursor-pagination {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    gap: 16px;
+    float: v-bind(float);
+
+    .page-info {
+      font-size: 14px;
+      color: #606266;
+    }
+
+    .ml-2 {
+      margin-left: 8px;
+    }
+  }
+}
+.pagination-container.hidden {
+  display: none;
+}
+</style>

+ 2 - 4
src/layout/components/breadcrumb.vue

@@ -2,7 +2,7 @@
   <!-- 面包屑组件 -->
   <div class="breadcrumb flex-row-center" :style="{ 'background': meta.breadcrumbColor ? meta.breadcrumbColor : '#ffffff' }">
     <div class="breadcrumb-bos flex-row-start">
-      <div class="home" @click="goHome">首页</div>
+      <div class="home" @click="onPath('/index')">首页</div>
       <template v-if="meta.navList && meta.navList.length > 0">
         <div v-for="(item, index) in meta.navList" :key="index" class="nav-list">
           <el-icon style="margin: 0 4px"><ArrowRight /></el-icon>
@@ -16,6 +16,7 @@
 </template>
 
 <script setup lang="ts">
+import { onPath } from '@/utils/siteConfig';
 const router = useRouter();
 const route = useRoute();
 
@@ -26,9 +27,6 @@ watch(route, () => {
   meta.value = route.meta;
 });
 
-const goHome = () => {
-  router.push('/');
-};
 
 const goPath = (res: any) => {
   router.push(res.url);

+ 212 - 11
src/layout/components/nav.vue

@@ -2,27 +2,97 @@
   <!-- 导航组件 -->
   <div class="nav flex-row-center">
     <div class="nav-bos">
-      <div class="nav-all flex-row-center">
+      <div class="nav-all flex-row-center" @mouseenter="openClassify">
         <img src="@/assets/images/layout/layout2.png" alt="" />
         <div>全部商品分类</div>
       </div>
-      <div v-for="(item, index) in navList" :key="index" class="nav-list">{{ item.title }}</div>
+      <div @click="onPath(item.url)" v-for="(item, index) in navList" :key="index" class="nav-list" :class="item.url == route.path ? 'hig' : ''">
+        {{ item.title }}
+      </div>
+      <div class="nav-classify" v-if="classifyOpen" @mouseleave="leaveClassify">
+        <div class="classify">
+          <div
+            class="classify-list"
+            v-for="(item, index) in classifyList"
+            :class="item.id == classifyId && classifyShow ? 'classify-hig' : ''"
+            :key="index"
+            @mouseenter="enterClassify(item)"
+          >
+            <div class="label ellipsis" @click="onPath('/search?type=1&topCategoryId=' + item.id)">{{ item.label }}</div>
+            <div class="info info1 ellipsis" v-if="item.extra && item.extra.oneLable1">{{ item.extra.oneLable1 }}</div>
+            <div class="info ellipsis" v-if="item.extra && item.extra.oneLable2">{{ item.extra.oneLable2 }}</div>
+            <div class="classify-border" v-if="item.id == classifyId && classifyShow"></div>
+          </div>
+        </div>
+        <div class="classify-bos" v-if="classifyShow">
+          <div v-for="(item, index) in classifyInfo" :key="index" class="classify-item" @click="onPath('/search?type=2&middleCategoryId=' + item.id)">
+            <div class="two-level ellipsis">{{ item.label || '' }}</div>
+            <el-icon class="classify-icon" :size="14" color="#364153">
+              <ArrowRight />
+            </el-icon>
+            <div class="classify-label">
+              <div v-for="(item1, index1) in item.children" :key="index1" @click="onPath('/search?type=3&bottomCategoryId=' + item1.id)">
+                {{ item1.label || '' }}
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
     </div>
   </div>
 </template>
 
 <script setup lang="ts">
-import { title } from 'process';
-
+import { onPath } from '@/utils/siteConfig';
+import { categoryStore } from '@/store/modules/category';
+const categoryStoreStore = categoryStore();
+const route = useRoute();
+const classifyList = ref<any>([]);
+const classifyOpen = ref<any>(false);
+const classifyShow = ref<any>(false);
+const classifyId = ref<any>('');
+const classifyInfo = ref<any>([]);
 const navList = ref<any>([
-  { title: '首页' },
-  { title: '工业品商城' },
-  { title: '福礼商城' },
+  { title: '首页', url: '/index' },
+  { title: '工业品商城', url: '/indexMro' },
+  { title: '福礼商城', url: '/indexFuli' },
   { title: '商用工程' },
-  { title: '场景采购' },
-  { title: '解决方案' },
-  { title: '特价专区' }
+  { title: '采购指南', url: '/plan/guide' },
+  { title: '解决方案', url: '/plan' },
+  { title: '特价专区', url: '/search/special' }
 ]);
+
+onMounted(async () => {
+  try {
+    // 根据当前路由路径获取分类数据
+    let path = route.path;
+    if (path != '/indexMro' && path != '/indexFuli') {
+      path = '/index';
+    }
+    classifyList.value = await categoryStoreStore.fetchCategories(path);
+  } catch (error) {
+    console.error('获取分类失败:', error);
+  }
+});
+
+//移入分类
+const openClassify = () => {
+  const path = route.path;
+  if (path != '/indexMro' && path != '/indexFuli' && path != '/index') {
+    classifyOpen.value = true;
+  }
+};
+const enterClassify = (res: any) => {
+  classifyShow.value = true;
+  classifyId.value = res.id;
+  classifyInfo.value = res.children;
+};
+
+//移出分类
+const leaveClassify = () => {
+  classifyOpen.value = false;
+  classifyShow.value = false;
+};
 </script>
 
 <style lang="scss" scoped>
@@ -36,8 +106,10 @@ const navList = ref<any>([
   .nav-bos {
     width: 1200px;
     display: flex;
+    position: relative;
 
     .nav-all {
+      width: 234px;
       height: 48px;
       background: #e7000b;
       padding: 0 10px;
@@ -56,13 +128,142 @@ const navList = ref<any>([
       line-height: 48px;
       font-size: 16px;
       color: #364153;
-      padding-left: 32px;
+      margin: 0 16px;
+      text-align: center;
       cursor: pointer;
 
+      &.hig {
+        color: #e7000b;
+        position: relative;
+        &::before {
+          content: '';
+          position: absolute;
+          bottom: 0;
+          left: 0px;
+          display: inline-block;
+          width: 100%;
+          height: 3px;
+          background: #e7000b;
+          margin-right: 8px;
+        }
+      }
+
       &:hover {
         color: #e7000b;
       }
     }
+
+    // 分类
+    .nav-classify {
+      position: absolute;
+      top: 100%;
+      left: 0;
+      z-index: 20;
+      .classify {
+        width: 234px;
+        background: #ffffff;
+
+        .classify-list {
+          width: 100%;
+          height: 40px;
+          cursor: pointer;
+          display: flex;
+          align-items: center;
+          padding-left: 15px;
+          position: relative;
+
+          &.classify-hig {
+            border: 1px solid var(--el-color-primary);
+            border-right: 0px solid var(--el-color-primary);
+          }
+
+          .label {
+            max-width: 100px;
+            font-weight: 600;
+            font-size: 14px;
+            color: #101828;
+            white-space: nowrap;
+            margin-right: 10px;
+
+            &:hover {
+              color: var(--el-color-primary);
+            }
+          }
+
+          .info {
+            max-width: 50px;
+            font-size: 12px;
+            color: #364153;
+            white-space: nowrap;
+
+            &.info1 {
+              margin-right: 6px;
+            }
+
+            &:hover {
+              color: var(--el-color-primary);
+            }
+          }
+
+          .classify-border {
+            position: absolute;
+            right: -1px;
+            top: 0px;
+            width: 1px;
+            height: 38px;
+            background-color: #ffffff;
+            z-index: 2;
+          }
+        }
+      }
+
+      .classify-bos {
+        position: absolute;
+        top: 0;
+        left: 100%;
+        width: 966px;
+        height: 100%;
+        border: 1px solid var(--el-color-primary);
+        background-color: #ffffff;
+        overflow-y: auto;
+        padding-left: 30px;
+
+        .classify-item {
+          display: flex;
+          padding-top: 10px;
+          border-bottom: 1px solid #e5e7eb;
+
+          .two-level {
+            width: 90px;
+            font-size: 14px;
+            color: var(--el-color-primary);
+            cursor: pointer;
+          }
+
+          .classify-icon {
+            margin: 4px 15px 0 15px;
+          }
+
+          .classify-label {
+            display: flex;
+            flex-wrap: wrap;
+            flex: 1;
+            font-size: 14px;
+            color: #364153;
+
+            div {
+              margin-right: 20px;
+              margin-bottom: 10px;
+              cursor: pointer;
+
+              &:hover {
+                color: var(--el-color-primary);
+              }
+            }
+          }
+        }
+      }
+    }
   }
 }
 </style>

+ 2 - 2
src/layout/components/search.vue

@@ -7,7 +7,7 @@
         <div class="search-div flex-row-start">
           <div class="search-input flex-row-center">
             <el-input class="el-input" v-model="input" placeholder="搜索商品、品牌、分类..." />
-            <div class="bnt flex-row-center" @click="onPath('/search')">
+            <div class="bnt flex-row-center" @click="onPath('/search?type=1&input=' + input)">
               <el-icon color="#ffffff" size="20">
                 <Search />
               </el-icon>
@@ -35,7 +35,7 @@
 
 <script setup lang="ts">
 import { onPath } from '@/utils/siteConfig';
-const input = ref('');
+const input = ref<any>('');
 const route = useRoute();
 const meta = ref<any>({});
 meta.value = route.meta;

+ 59 - 5
src/router/index.ts

@@ -64,21 +64,21 @@ export const constantRoutes: RouteRecordRaw[] = [
     children: [
       {
         path: '/index',
-        component: () => import('@/views/index.vue'),
+        component: () => import('@/views/home/index.vue'),
         name: 'Index',
-        meta: { title: '优易365', icon: 'dashboard', affix: true, nav: true }
+        meta: { title: '优易365', affix: true, nav: true }
       },
       {
         path: '/indexB',
         component: () => import('@/views/home/index-b.vue'),
         name: 'IndexB',
-        meta: { title: '企业购商城', icon: 'dashboard', affix: true, nav: true }
+        meta: { title: '企业购商城', affix: true, nav: true }
       },
       {
         path: '/indexMro',
         component: () => import('@/views/home/index-mro.vue'),
         name: 'IndexMro',
-        meta: { title: '工业品商城', icon: 'dashboard', affix: true, nav: true }
+        meta: { title: '工业品商城', affix: true, nav: true }
       },
       {
         path: '/indexFuli',
@@ -110,6 +110,18 @@ export const constantRoutes: RouteRecordRaw[] = [
         name: 'Search',
         meta: { title: '搜索', icon: 'dashboard', affix: true, nav: true }
       },
+      {
+        path: '/search/special',
+        component: () => import('@/views/search/special.vue'),
+        name: 'SearchSpecial',
+        meta: { title: '特价专区', icon: 'dashboard', affix: true, nav: true }
+      },
+      {
+        path: '/search/brand',
+        component: () => import('@/views/search/brand.vue'),
+        name: 'SearchBrand',
+        meta: { title: '品牌闪购', icon: 'dashboard', affix: true, nav: true }
+      },
       {
         path: '/item',
         component: () => import('@/views/item/index.vue'),
@@ -135,7 +147,7 @@ export const constantRoutes: RouteRecordRaw[] = [
         meta: { title: '支付订单', nav: true }
       },
       {
-        path: 'solve/real',
+        path: '/solve/real',
         component: () => import('@/views/solve/real.vue'),
         name: 'solveReal',
         meta: { title: '资讯详情', nav: true, breadcrumb: true, breadcrumbColor: '#F4F4F4' }
@@ -188,6 +200,48 @@ export const constantRoutes: RouteRecordRaw[] = [
         name: 'PlanInfo',
         meta: { title: '解决方案详情', nav: true, breadcrumb: true, navList: [{ title: '解决方案', url: '/plan' }] }
       },
+      {
+        path: '/plan/procure',
+        component: () => import('@/views/plan/procure.vue'),
+        name: 'PlanProcure',
+        meta: { title: '采购方案', nav: true, breadcrumb: true }
+      },
+      {
+        path: '/plan_info/procure',
+        component: () => import('@/views/plan_info/procure.vue'),
+        name: 'PlanInfoProcure',
+        meta: { title: '采购方案详情', nav: true, breadcrumb: true, navList: [{ title: '采购方案', url: '/plan/procure' }] }
+      },
+      {
+        path: '/plan/guide',
+        component: () => import('@/views/plan/guide.vue'),
+        name: 'PlanGuide',
+        meta: { title: '采购指南', nav: true, breadcrumb: true }
+      },
+      {
+        path: '/plan_info/guide',
+        component: () => import('@/views/plan_info/guide.vue'),
+        name: 'PlanInfoGuide',
+        meta: { title: '采购指南详情', nav: true, breadcrumb: true, breadcrumbColor: '#F4F4F4', navList: [{ title: '采购指南', url: '/plan/guide' }] }
+      },
+      {
+        path: '/plan/project',
+        component: () => import('@/views/plan/project.vue'),
+        name: 'PlanProject',
+        meta: { title: '项目案例', nav: true, breadcrumb: true }
+      },
+      {
+        path: '/plan_info/project',
+        component: () => import('@/views/plan_info/project.vue'),
+        name: 'PlanInfoProject',
+        meta: {
+          title: '项目案例详情',
+          nav: true,
+          breadcrumb: true,
+          breadcrumbColor: '#F4F4F4',
+          navList: [{ title: '采购指南', url: '/plan/project' }]
+        }
+      },
       {
         path: '/i',
         name: 'I',

+ 28 - 0
src/store/modules/category.ts

@@ -0,0 +1,28 @@
+import { getProductCategoryTree } from '@/api/home/index';
+import { getGiftCategoryList } from '@/api/home/index-fuli';
+
+export const categoryStore = defineStore('category', () => {
+  const categories = ref<any>({
+    '/index': [],
+    '/indexMro': [],
+    '/indexFuli': []
+  });
+
+  const fetchCategories = async (key: string) => {
+    if (categories.value[key].length > 0) return categories.value[key];
+    try {
+      const response =
+        key == '/index' ? await getProductCategoryTree({}) : key == '/indexMro' ? await getProductCategoryTree({}) : await getGiftCategoryList({});
+      categories.value[key] = response.data;
+      return response.data;
+    } catch (error) {
+      console.error('获取分类失败:', error);
+      throw error;
+    }
+  };
+
+  return {
+    categories,
+    fetchCategories
+  };
+});

+ 4 - 4
src/utils/siteConfig.ts

@@ -32,14 +32,14 @@ export const SITE_ROUTES: Record<any, string[]> = {
   breg: ['/breg'], //企业注册
   greg: ['/greg'], //供应商注册
   passport: ['/login'], //登录页
-  search: ['/search'], //搜索
+  search: ['/search', '/search/special'], //搜索
   item: ['/item'], //商品详情,
   cart: ['/cart'], //商品详情
   trad: ['/trad'], //确认订单信息
   payc: ['/payc'], //支付订单
   order: ['/order/orderManage', '/order/orderManage/detail', '/order/orderAudit', '/order/afterSale', '/order/batchOrder', '/order/orderEvaluation'], //订单列表
-  plan: ['/plan'], //解决方案
-  plan_info: ['/plan_info'], //信息展示
+  plan: ['/plan', '/plan/procure', '/plan/guide', '/plan/project'], //解决方案
+  plan_info: ['/plan_info', '/plan_info/procure', '/plan_info/guide', '/plan_info/project'], //信息展示
   i: ['/i'], //个人信息
   easybuv: ['/easybuv'] //地址管理
 };
@@ -103,7 +103,7 @@ export function getApiBase() {
   } else {
     // return '/dev-api'
     // return 'http://192.168.1.52:8080';
-    return 'https://ceshi.xiaoluwebsite.xyz';
+    return 'https://jingyang.xiaoluwebsite.xyz';
   }
 }
 

+ 28 - 9
src/views/cart/index.vue

@@ -3,7 +3,7 @@
     <div class="cart-bos">
       <div class="cart-head flex-row-between">
         <div class="flex-row-start head1">
-          <img src="@/assets/images/dark.svg" alt="" />
+          <img src="@/assets/images/cart1.png" alt="" />
           <div>我的购物车</div>
         </div>
         <div class="head2">导出订单</div>
@@ -16,6 +16,7 @@
           backgroundColor: '#F2F3F5',
           fontWeight: 'normal'
         }"
+        @selection-change="handleSelectionChange1"
       >
         <el-table-column type="selection" width="55" />
         <el-table-column label="商品信息" width="490">
@@ -121,7 +122,7 @@
           <span>,活动优惠:0.00</span>
           <span class="span1">合计:</span>
           <span class="span2">¥0.00</span>
-          <el-button class="bnt" type="primary">去结算</el-button>
+          <el-button class="bnt" type="primary" @click="goTrad">去结算</el-button>
         </div>
       </div>
     </div>
@@ -130,7 +131,9 @@
 
 <script setup lang="ts">
 const tableData = ref<any>([]);
+const selectedList = ref<any>([]);
 const noTableData = ref<any>([]);
+
 const checked1 = ref(false);
 
 import { shoppingCartList, deleteProductShoppingCart } from '@/api/goods/index';
@@ -143,17 +146,24 @@ onMounted(() => {
 const getInfo = () => {
   shoppingCartList({}).then((res) => {
     if (res.code == 200) {
-      res.rows.forEach((item: any) => {
-        if (item.productStatus == 1) {
-          tableData.value.push(item);
-        } else {
-          noTableData.value.push(item);
-        }
-      });
+      if (res.rows && res.rows.length > 0) {
+        res.rows.forEach((item: any) => {
+          if (item.productStatus == 1) {
+            tableData.value.push(item);
+          } else {
+            noTableData.value.push(item);
+          }
+        });
+      }
     }
   });
 };
 
+//购物车选中
+const handleSelectionChange1 = (val: any) => {
+  selectedList.value = val;
+};
+
 const onDel = (row: any) => {
   ElMessageBox.confirm(`确定要删除吗?`, '提示', {
     confirmButtonText: '确定',
@@ -168,6 +178,15 @@ const onDel = (row: any) => {
     });
   });
 };
+
+const goTrad = () => {
+  if (selectedList.value.length == 0) {
+    ElMessage.warning('请选择商品');
+    return;
+  }
+  const ids = selectedList.value.map((item: any) => item.shoppingCartId).join(',');
+  onPath('/trad?ids=' + ids);
+};
 </script>
 
 <style lang="scss" scoped>

+ 720 - 4
src/views/home/index-fuli.vue

@@ -1,9 +1,725 @@
 <template>
-  <div>
-    <h1>福礼商城</h1>
+  <div class="home-pages">
+    <div class="head-pages">
+      <!--  头部 -->
+      <div class="home-head" @mouseleave="leaveClassify">
+        <div class="classify" :class="classifyShow ? 'classify-show' : ''">
+          <div
+            class="classify-list"
+            v-for="(item, index) in classifyList"
+            :class="item.id == classifyId && classifyShow ? 'classify-hig' : ''"
+            :key="index"
+            @mouseenter="enterClassify(item)"
+            v-show="classifyShow ? true : Number(index) < 13"
+          >
+            <div class="label ellipsis" @click="onPath('/search?id=' + item.id)">{{ item.label }}</div>
+            <div class="info info1 ellipsis" v-if="item.extra && item.extra.oneLable1">{{ item.extra.oneLable1 }}</div>
+            <div class="info ellipsis" v-if="item.extra && item.extra.oneLable2">{{ item.extra.oneLable2 }}</div>
+            <div v-if="item.id == classifyId && classifyShow" class="classify-border"></div>
+            <!--  -->
+          </div>
+        </div>
+        <div class="classify-bos" v-if="classifyShow">
+          <div v-for="(item, index) in classifyInfo" :key="index" class="classify-item">
+            <div class="two-level ellipsis">{{ item.label || '' }}</div>
+            <el-icon class="classify-icon" :size="14" color="#364153">
+              <ArrowRight />
+            </el-icon>
+            <div class="classify-label">
+              <div v-for="(item1, index1) in item.children" :key="index1">{{ item1.label || '' }}</div>
+            </div>
+          </div>
+        </div>
+        <!-- 轮播区域 -->
+        <div class="carousel-bos">
+          <el-carousel trigger="click" height="540px">
+            <el-carousel-item v-for="item in carouselList" :key="item">
+              <img :src="item.imageUrl" alt="" />
+            </el-carousel-item>
+          </el-carousel>
+        </div>
+        <!-- 右边 -->
+        <div class="head-right">
+          <div class="login-bos">
+            <div class="login-box">
+              <img :src="userInfo.avatar ? userInfo.avatar : profile" alt="" />
+              <div>
+                <div class="login1">您好,欢迎来到优易达</div>
+                <div class="login2">{{ userInfo.nickName ? userInfo.nickName : '请先登录' }}</div>
+              </div>
+            </div>
+            <div class="login-btn">
+              <el-button v-if="!userInfo.nickName" type="primary" round size="small" style="width: 64px" @click="onPath('/login')">登录</el-button>
+              <el-button v-if="!userInfo.nickName" type="primary" plain round size="small" style="width: 64px" @click="onPath('/reg')"
+                >注册</el-button
+              >
+              <el-button v-if="userInfo.nickName" type="primary" plain round size="small" style="width: 64px" @click="onPath('/reg')">退出</el-button>
+            </div>
+          </div>
+          <div class="real-time">
+            <div class="real-title flex-row-between">
+              <div class="real1">优易资讯</div>
+              <div class="real2 flex-row-start">
+                <div>更多</div>
+                <el-icon :size="13" color="#83899F">
+                  <ArrowRight />
+                </el-icon>
+              </div>
+            </div>
+            <template v-for="(item, index) in realList" :key="index">
+              <div class="real-list ellipsis" v-if="Number(index) < 7">{{ item.announcementTitle }}</div>
+            </template>
+          </div>
+          <div class="interests">
+            <div class="interests-title">企业会员权益</div>
+            <div class="interests-bos">
+              <div v-for="(item, index) in interestsList" :key="index" class="interests-item flex-column-center">
+                <img :src="item.imageUrl" alt="" />
+                <div>{{ item.title }}</div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="pages-bos">
+      <!-- 场景采购 -->
+      <div class="home-title flex-row-center">
+        <img src="@/assets/images/home/indexFuli1.png" alt="" />
+        场景采购
+        <img src="@/assets/images/home/indexFuli2.png" alt="" />
+      </div>
+      <div class="scenario-bos">
+        <template v-for="(item, index) in scenario" :key="index">
+          <div v-if="Number(index) < 4" class="scenario-list">
+            <img class="shop-img" :src="item.imageUrl" alt="" />
+          </div>
+        </template>
+      </div>
+      <!-- 热门定制 -->
+      <div class="home-title flex-row-center">
+        <img src="@/assets/images/home/indexFuli1.png" alt="" />
+        热门定制
+        <img src="@/assets/images/home/indexFuli2.png" alt="" />
+      </div>
+      <div class="sell-bos">
+        <template v-for="(item, index) in popular" :key="index">
+          <div v-if="Number(index) < 5" class="sell-list">
+            <img class="sell-img" :src="item.productImage ? item.productImage.split(',')[0] : ''" alt="" />
+            <div class="sell-name ellipsis2">{{ item.name || '格力KFR-72LW/定频冷暖空调柜机3P格力KFR行车自行车自行车行政村在' }}</div>
+            <div class="sell-price">
+              <span class="price1">¥{{ item.memberPrice || '23.22' }}</span>
+              <span class="price2">¥{{ item.marketPrice || '52.12' }}</span>
+            </div>
+          </div>
+        </template>
+      </div>
+      <!-- 循环数据 -->
+      <div class="goods-bos" v-for="(item, index) in goodsList" :key="index">
+        <img class="goods-main" :src="item.mainImg" alt="" />
+        <div class="goods-box">
+          <div v-for="(item1, index1) in 8" :key="index1" class="goods-list">
+            <img class="goods-img" :src="item.productImage ? item.productImage.split(',')[0] : ''" alt="" />
+            <div class="goods-name ellipsis2">{{ item.name || '格力KFR-72LW/定频冷暖空调柜机3P格力KFR行车自行车自行车行政村在' }}</div>
+            <div class="goods-price">
+              <span class="price1">¥{{ item.memberPrice || '23.22' }}</span>
+              <span class="price2">¥{{ item.marketPrice || '52.12' }}</span>
+            </div>
+          </div>
+        </div>
+      </div>
+      <!-- 为您推荐 -->
+      <div class="home-title flex-row-center">
+        <img src="@/assets/images/home/indexFuli1.png" alt="" />
+        为您推荐
+        <img src="@/assets/images/home/indexFuli2.png" alt="" />
+      </div>
+      <div class="sell-bos recommend">
+        <div v-for="(item, index) in 15" :key="index" class="sell-list">
+          <img class="sell-img" :src="item.productImage ? item.productImage.split(',')[0] : ''" alt="" />
+          <div class="sell-name ellipsis2">{{ item.name || '格力KFR-72LW/定频冷暖空调柜机3P格力KFR行车自行车自行车行政村在' }}</div>
+          <div class="sell-price">
+            <span class="price1">¥{{ item.memberPrice || '23.22' }}</span>
+            <span class="price2">¥{{ item.marketPrice || '52.12' }}</span>
+          </div>
+        </div>
+      </div>
+    </div>
   </div>
 </template>
 
-<script setup lang="ts"></script>
+<script setup lang="ts">
+import { onPath } from '@/utils/siteConfig';
+import { getToken } from '@/utils/auth';
+import { getInfo } from '@/api/login';
+import profile from '@/assets/images/profile.jpg';
+import {
+  getGiftCategoryList,
+  getHomeAdList,
+  getIconAdList,
+  getNoticeList,
+  getRecommendAdList,
+  getHotCustomGiftFloorList,
+  getAdvertisementGiftFloorList,
+  getGiftFloorLinkProductList,
+  getRecommendGiftFloorList
+} from '@/api/home/index-fuli';
 
-<style lang="scss" scoped></style>
+import { getProductCategoryTree } from '@/api/home/index';
+
+onMounted(() => {
+  if (getToken()) {
+    getInfo().then((res) => {
+      if (res.code == 200) {
+        userInfo.value = res.data.user;
+      }
+    });
+  }
+});
+
+const userInfo = ref<any>({});
+const classifyList = ref<any>([]);
+const classifyShow = ref<any>(false);
+const classifyId = ref<any>('');
+const classifyInfo = ref<any>([]);
+const carouselList = ref<any>([]);
+const realList = ref<any>([]);
+const interestsList = ref<any>([]);
+const scenario = ref<any>([]);
+const popular = ref<any>([]);
+const goodsList = ref<any>([{}, {}, {}]);
+const recommend = ref<any>([{}, {}, {}]);
+
+//头部分类
+getProductCategoryTree({}).then((res) => {
+  if (res.code == 200) {
+    classifyList.value = res.data;
+  }
+});
+
+//移入分类
+const enterClassify = (res: any) => {
+  classifyShow.value = true;
+  classifyId.value = res.id;
+  classifyInfo.value = res.children;
+};
+
+//移出分类
+const leaveClassify = () => {
+  classifyShow.value = false;
+};
+
+// //头部分类
+// getGiftCategoryList({}).then((res) => {
+//   if (res.code == 200) {
+//     classifyList.value = res.data;
+//   }
+// });
+
+//轮播广告
+getHomeAdList({}).then((res) => {
+  if (res.code == 200) {
+    carouselList.value = res.data;
+  }
+});
+
+// 会员权益
+getIconAdList({}).then((res) => {
+  if (res.code == 200) {
+    interestsList.value = res.data;
+  }
+});
+
+// 咨询
+getNoticeList({}).then((res) => {
+  if (res.code == 200) {
+    realList.value = res.data;
+  }
+});
+
+// 荐广告(福利装修-推荐广告)场景采购
+getRecommendAdList({}).then((res) => {
+  if (res.code == 200) {
+    scenario.value = res.data;
+  }
+});
+
+//热门定制
+getHotCustomGiftFloorList({}).then((res) => {
+  if (res.code == 200) {
+    popular.value = res.data;
+  }
+});
+
+//循环
+getAdvertisementGiftFloorList({}).then((res) => {
+  if (res.code == 200) {
+    goodsList.value = res.data;
+    res.data.forEach((item: any) => {
+      getGiftFloorLinkProductList({ floorId: item.id }).then((res) => {
+        if (res.code == 200) {
+        }
+      });
+    });
+  }
+});
+
+//为你推荐
+getRecommendGiftFloorList({}).then((res) => {
+  if (res.code == 200) {
+    recommend.value = res.data;
+  }
+});
+</script>
+
+<style lang="scss" scoped>
+.home-pages {
+  width: 100%;
+  .head-pages {
+    width: 100%;
+    background: #ead3ab;
+
+    // 头部
+    .home-head {
+      width: 1200px;
+      margin: 0 auto;
+      position: relative;
+      display: flex;
+      gap: 0px 10px;
+
+      .classify {
+        width: 234px;
+        height: 540px;
+        background: #ffffff;
+        &.classify-show {
+          position: absolute;
+          z-index: 10;
+          height: auto;
+          min-height: 540px;
+        }
+
+        .classify-list {
+          width: 100%;
+          height: 40px;
+          cursor: pointer;
+          display: flex;
+          align-items: center;
+          padding-left: 15px;
+          position: relative;
+          z-index: 12;
+
+          &.classify-hig {
+            border: 1px solid var(--el-color-primary);
+            border-right: 0px solid #ffffff;
+          }
+
+          .label {
+            max-width: 100px;
+            font-weight: 600;
+            font-size: 14px;
+            color: #101828;
+            white-space: nowrap;
+            margin-right: 10px;
+
+            &:hover {
+              color: var(--el-color-primary);
+            }
+          }
+
+          .info {
+            max-width: 50px;
+            font-size: 12px;
+            color: #364153;
+            white-space: nowrap;
+
+            &.info1 {
+              margin-right: 6px;
+            }
+
+            &:hover {
+              color: var(--el-color-primary);
+            }
+          }
+
+          .classify-border {
+            position: absolute;
+            right: -1px;
+            top: 0px;
+            width: 1px;
+            height: 38px;
+            background-color: #ffffff;
+            z-index: 6;
+          }
+        }
+      }
+
+      .classify-bos {
+        position: absolute;
+        top: 0;
+        right: 0;
+        width: 966px;
+        height: 100%;
+        border: 1px solid var(--el-color-primary);
+        background-color: #ffffff;
+        overflow-y: auto;
+        padding-left: 30px;
+        z-index: 5;
+
+        .classify-item {
+          display: flex;
+          padding-top: 10px;
+          border-bottom: 1px solid #e5e7eb;
+
+          .two-level {
+            width: 90px;
+            font-size: 14px;
+            color: var(--el-color-primary);
+            cursor: pointer;
+          }
+
+          .classify-icon {
+            margin: 4px 15px 0 15px;
+          }
+
+          .classify-label {
+            display: flex;
+            flex-wrap: wrap;
+            flex: 1;
+            font-size: 14px;
+            color: #364153;
+
+            div {
+              margin-right: 20px;
+              margin-bottom: 10px;
+              cursor: pointer;
+
+              &:hover {
+                color: var(--el-color-primary);
+              }
+            }
+          }
+        }
+      }
+
+      // 头部中间
+      .carousel-bos {
+        width: 756px;
+        height: 540px;
+        img {
+          width: 756px;
+          height: 540px;
+        }
+      }
+
+      //右边
+      .head-right {
+        flex: 1;
+        width: 0;
+        height: 540px;
+        background: #ffffff;
+        display: flex;
+        flex-direction: column;
+
+        .login-bos {
+          width: calc(100% - 20px);
+          height: 110px;
+          border-bottom: 1px solid #e5e7eb;
+          margin: 0 10px;
+          display: flex;
+          flex-direction: column;
+          justify-content: space-between;
+          padding: 16px 0;
+
+          .login-box {
+            display: flex;
+            align-items: center;
+
+            img {
+              width: 40px;
+              height: 40px;
+              margin-right: 8px;
+              border-radius: 40px;
+            }
+
+            .login-btn {
+              width: 100%;
+            }
+
+            .login1 {
+              font-size: 13px;
+              color: #444444;
+            }
+
+            .login2 {
+              margin-top: 2px;
+              font-size: 12px;
+              color: #6a7282;
+            }
+          }
+        }
+
+        .real-time {
+          width: calc(100% - 20px);
+          height: 227px;
+          border-bottom: 1px solid #e5e7eb;
+          margin: 0 10px;
+          padding-top: 15px;
+
+          .real-title {
+            position: relative;
+            margin-bottom: 12px;
+
+            &::after {
+              content: '';
+              top: 3px;
+              left: 0;
+              position: absolute;
+              width: 4px;
+              height: 14px;
+              background: var(--el-color-primary);
+            }
+
+            .real1 {
+              font-weight: 600;
+              font-size: 14px;
+              color: #1d2129;
+              padding-left: 15px;
+            }
+
+            .real2 {
+              font-size: 13px;
+              color: #83899f;
+              cursor: pointer;
+            }
+          }
+
+          .real-list {
+            width: 100%;
+            font-size: 14px;
+            color: #1d2129;
+            margin-bottom: 12px;
+            cursor: pointer;
+
+            &:hover {
+              color: var(--el-color-primary);
+            }
+          }
+        }
+
+        .interests {
+          flex: 1;
+          width: calc(100% - 20px);
+          margin: 0 10px;
+          padding-top: 15px;
+
+          .interests-title {
+            position: relative;
+            font-weight: 600;
+            font-size: 14px;
+            color: #1d2129;
+            padding-left: 15px;
+
+            &::after {
+              content: '';
+              top: 3px;
+              left: 0;
+              position: absolute;
+              width: 4px;
+              height: 14px;
+              background: var(--el-color-primary);
+            }
+          }
+
+          .interests-bos {
+            display: flex;
+            flex-wrap: wrap;
+
+            .interests-item {
+              width: 33.333%;
+              font-size: 12px;
+              color: #101828;
+              margin-top: 15px;
+              cursor: pointer;
+
+              &:hover {
+                color: var(--el-color-primary);
+              }
+
+              img {
+                width: 34px;
+                height: 34px;
+                margin-bottom: 7px;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  .pages-bos {
+    width: 1200px;
+    margin: 0 auto;
+
+    //标题
+    .home-title {
+      width: 1200px;
+      height: 56px;
+      background: #ffffff;
+      border-radius: 10px;
+      margin-top: 30px;
+      font-weight: 600;
+      font-size: 20px;
+      color: #ff4f20;
+      img {
+        width: 43px;
+        height: 28px;
+        margin: 0 10px;
+      }
+    }
+
+    // 场景采购
+    .scenario-bos {
+      width: 1200px;
+      display: flex;
+      gap: 0 10px;
+      margin-top: 12px;
+
+      .scenario-list {
+        width: 292.5px;
+        height: 182px;
+        border-radius: 10px;
+        overflow: hidden;
+        cursor: pointer;
+        transition: transform 0.2s ease;
+        img {
+          width: 292.5px;
+          height: 182px;
+        }
+        &:hover {
+          transform: translateY(-2px);
+        }
+      }
+    }
+
+    //热门定制
+    .sell-bos {
+      width: 1200px;
+      display: flex;
+      gap: 0 20px;
+      margin-top: 12px;
+
+      .sell-list {
+        width: 224px;
+        height: 306px;
+        background: #ffffff;
+        border-radius: 10px;
+        padding: 20px;
+        display: flex;
+        flex-direction: column;
+        justify-content: space-between;
+        cursor: pointer;
+        transition: transform 0.2s ease;
+        &:hover {
+          transform: translateY(-2px);
+        }
+
+        .sell-img {
+          width: 184px;
+          height: 182px;
+        }
+
+        .sell-name {
+          width: 184px;
+          height: 38px;
+          font-size: 14px;
+          color: #101828;
+        }
+
+        .sell-price {
+          .price1 {
+            color: var(--el-color-primary);
+            font-size: 16px;
+            color: #e7000b;
+          }
+          .price2 {
+            font-size: 12px;
+            color: #99a1af;
+            line-height: 20px;
+            text-decoration-line: line-through;
+            text-transform: none;
+            margin-left: 6px;
+          }
+        }
+      }
+    }
+
+    //循环数据
+    .goods-bos {
+      width: 1200px;
+      margin-top: 30px;
+      display: flex;
+      .goods-main {
+        width: 232px;
+        height: 560px;
+        border-radius: 10px;
+        margin-right: 10px;
+      }
+      .goods-box {
+        flex: 1;
+        height: 560px;
+        display: flex;
+        flex-wrap: wrap;
+        gap: 10px;
+        .goods-list {
+          width: 232px;
+          height: 275px;
+          background: #ffffff;
+          border-radius: 10px;
+          padding: 20px;
+          display: flex;
+          flex-direction: column;
+          justify-content: space-between;
+          cursor: pointer;
+          transition: transform 0.2s ease;
+          &:hover {
+            transform: translateY(-2px);
+          }
+          .goods-img {
+            height: 150px;
+            width: 192px;
+          }
+          .goods-name {
+            width: 192px;
+            height: 38px;
+            font-size: 14px;
+            color: #101828;
+          }
+
+          .goods-price {
+            .price1 {
+              color: var(--el-color-primary);
+              font-size: 16px;
+              color: #e7000b;
+            }
+            .price2 {
+              font-size: 12px;
+              color: #99a1af;
+              line-height: 20px;
+              text-decoration-line: line-through;
+              text-transform: none;
+              margin-left: 6px;
+            }
+          }
+        }
+      }
+    }
+
+    .recommend {
+      margin-bottom: 30px;
+      gap: 10px 20px;
+      flex-wrap: wrap;
+    }
+  }
+}
+</style>

+ 821 - 4
src/views/home/index-mro.vue

@@ -1,9 +1,826 @@
 <template>
-  <div>
-    <h1>工业品商城</h1>
+  <div class="home-pages">
+    <div class="head-pages">
+      <!--  头部 -->
+      <div class="home-head" @mouseleave="leaveClassify">
+        <!-- 分类 -->
+        <div class="classify" :class="classifyShow ? 'classify-show' : ''">
+          <div
+            class="classify-list"
+            v-for="(item, index) in classifyList"
+            :class="item.id == classifyId && classifyShow ? 'classify-hig' : ''"
+            :key="index"
+            @mouseenter="enterClassify(item)"
+            v-show="classifyShow ? true : Number(index) < 8"
+          >
+            <div class="label ellipsis" @click="onPath('/search?id=' + item.id)">{{ item.label }}</div>
+            <div class="two-level">
+              <template v-for="(item1, index1) in item.children" :key="index1">
+                <div class="two-hig" v-if="Number(index1) < 2">{{ item1.label }}</div>
+                <div style="margin: 0 4px" v-if="index1 == 0 && item.children.length > 1">/</div>
+              </template>
+            </div>
+          </div>
+        </div>
+        <div class="classify-bos" v-if="classifyShow">
+          <div v-for="(item, index) in classifyInfo" :key="index" class="classify-item">
+            <div class="two-level ellipsis">{{ item.label || '' }}</div>
+            <el-icon class="classify-icon" :size="14" color="#364153">
+              <ArrowRight />
+            </el-icon>
+            <div class="classify-label">
+              <div v-for="(item1, index1) in item.children" :key="index1">{{ item1.label || '' }}</div>
+            </div>
+          </div>
+        </div>
+        <!-- 轮播区域 -->
+        <div class="carousel-bos">
+          <el-carousel trigger="click" height="540px">
+            <el-carousel-item v-for="item in carouselList" :key="item">
+              <img :src="item.imageUrl" alt="" />
+            </el-carousel-item>
+          </el-carousel>
+        </div>
+        <!-- 右边 -->
+        <div class="head-right">
+          <div class="login-bos">
+            <div class="login-box">
+              <img :src="userInfo.avatar ? userInfo.avatar : profile" alt="" />
+              <div>
+                <div class="login1">您好,欢迎来到优易达</div>
+                <div class="login2">{{ userInfo.nickName ? userInfo.nickName : '请先登录' }}</div>
+              </div>
+            </div>
+            <div class="login-btn">
+              <el-button v-if="!userInfo.nickName" type="primary" round size="small" style="width: 64px" @click="onPath('/login')">登录</el-button>
+              <el-button v-if="!userInfo.nickName" type="primary" plain round size="small" style="width: 64px" @click="onPath('/reg')"
+                >注册</el-button
+              >
+              <el-button v-if="userInfo.nickName" type="primary" plain round size="small" style="width: 64px" @click="onPath('/reg')">退出</el-button>
+            </div>
+          </div>
+          <div class="real-time">
+            <div class="real-title flex-row-between">
+              <div class="real1">优易资讯</div>
+              <div class="real2 flex-row-start">
+                <div>更多</div>
+                <el-icon :size="13" color="#83899F">
+                  <ArrowRight />
+                </el-icon>
+              </div>
+            </div>
+            <template v-for="(item, index) in realList" :key="index">
+              <div class="real-list ellipsis" v-if="Number(index) < 7">{{ item.announcementTitle }}</div>
+            </template>
+          </div>
+          <div class="interests">
+            <div class="interests-title">企业会员权益</div>
+            <div class="interests-bos">
+              <div v-for="(item, index) in interestsList" :key="index" class="interests-item flex-column-center">
+                <img :src="item.imageUrl" alt="" />
+                <div>{{ item.title }}</div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="pages-bos">
+      <!-- 轮播展位商品 -->
+      <div class="sell-bos">
+        <template v-for="(item, index) in sellList" :key="index">
+          <div v-if="Number(index) < 5" class="sell-list">
+            <img class="sell-img" :src="item.productImage ? item.productImage.split(',')[0] : ''" alt="" />
+            <div class="sell-name ellipsis2">{{ item.itemName || '格力KFR-72LW/定频冷暖空调柜机3P格力KFR行车自行车自行车行政村在' }}</div>
+            <div class="sell-price">
+              <span class="price1">¥{{ item.memberPrice || '23.22' }}</span>
+              <span class="price2">¥{{ item.marketPrice || '52.12' }}</span>
+            </div>
+          </div>
+        </template>
+      </div>
+      <!-- 商业标签(工业装修-商业标签) -->
+      <div class="trade-bos">
+        <template v-for="(item, index) in tradeList" :key="index">
+          <div v-if="Number(index) < 4" class="trade-list flex-row-between">
+            <div class="trade-box flex-column-between">
+              <div class="trade-title">新品推荐</div>
+              <div class="trade-info ellipsis2">
+                品质卓越,严选新品,直击企业效能升级需求,多场景适品质卓越,严选新品,直击企业效能升级需求,多场景适
+              </div>
+              <img class="trade-look" src="@/assets/images/home/indexMro1.png" alt="" />
+            </div>
+            <img class="trade-img" src="" alt="" />
+          </div>
+        </template>
+      </div>
+      <!-- 循环-商品 -->
+      <div class="goods-bos" v-for="(item, index) in goodsList" :key="index">
+        <div class="goods-title flex-row-center">
+          <img src="@/assets/images/home/indexMro2.png" alt="" />
+          <span class="text-primary">电气控制产品</span>
+          <span>精选</span>
+          <img src="@/assets/images/home/indexMro3.png" alt="" />
+        </div>
+        <div class="goods-box">
+          <img class="goods-one" src="" alt="" />
+          <div class="goods-shop">
+            <template v-for="(item1, index1) in 10" :key="index1">
+              <div v-if="Number(index1) < 8" class="shop-list flex-column-between">
+                <img class="shop-img" :src="item.productImage ? item.productImage.split(',')[0] : ''" alt="" />
+                <div class="shop-name ellipsis2">{{ item.itemName || '格力KFR-72LW/定频冷暖空调柜机3P格力KFR行车自行车自行车行政村在' }}</div>
+                <div class="shop-price">
+                  <span class="price1">¥{{ item.memberPrice || '23.22' }}</span>
+                  <span class="price2">¥{{ item.marketPrice || '52.12' }}</span>
+                </div>
+              </div>
+            </template>
+          </div>
+          <div class="goods-brand flex-column-between">
+            <div class="brand-bos">
+              <template v-for="(item1, index1) in 8" :key="index1">
+                <img clear-both v-if="Number(index1) < 6" class="brand-img" src="" alt="" />
+              </template>
+            </div>
+            <div class="brand-more flex-row-center">
+              <div>更多品牌</div>
+              <el-icon><ArrowRight /></el-icon>
+            </div>
+          </div>
+        </div>
+      </div>
+      <!-- 为你推荐 -->
+      <div class="goods-title flex-row-center">
+        <img src="@/assets/images/home/indexMro2.png" alt="" />
+        <span class="text-primary">为你推荐</span>
+        <img src="@/assets/images/home/indexMro3.png" alt="" />
+      </div>
+      <div class="nav-bos flex-row-center">
+        <template v-for="(item, index) in 10" :key="index">
+          <div class="nav-list" :class="index == 0 ? 'hig' : ''" v-if="Number(index) < 9">为你推荐</div>
+        </template>
+      </div>
+      <!-- 轮播展位商品 -->
+      <div class="sell-bos recommend">
+        <div v-for="(item, index) in 20" :key="index" class="sell-list">
+          <img class="sell-img" :src="item.productImage ? item.productImage.split(',')[0] : ''" alt="" />
+          <div class="sell-name ellipsis2">{{ item.itemName || '格力KFR-72LW/定频冷暖空调柜机3P格力KFR行车自行车自行车行政村在' }}</div>
+          <div class="sell-price">
+            <span class="price1">¥{{ item.memberPrice || '23.22' }}</span>
+            <span class="price2">¥{{ item.marketPrice || '52.12' }}</span>
+          </div>
+        </div>
+      </div>
+    </div>
   </div>
 </template>
 
-<script setup lang="ts"></script>
+<script setup lang="ts">
+import {
+  getProductCategoryTree,
+  getHomeAdList,
+  getHomeIconAd,
+  getCarouselDisplayProductList,
+  getBusinessLabelList,
+  getIndustrialFloor,
+  getIndustrialFloorProductList,
+  getIndustrialFloorBrand,
+  getRecommendedCategory,
+  getRecommendedCategoryProductList
+} from '@/api/home/index-mro';
+import { getYouYiZiXunPage } from '@/api/home/index';
+import { onPath } from '@/utils/siteConfig';
+import { getToken } from '@/utils/auth';
+import { getInfo } from '@/api/login';
+import profile from '@/assets/images/profile.jpg';
 
-<style lang="scss" scoped></style>
+const userInfo = ref<any>({});
+const classifyId = ref<any>('');
+const classifyShow = ref<any>(false);
+const classifyInfo = ref<any>([]);
+const classifyList = ref<any>([]);
+const carouselList = ref<any>([]);
+const realList = ref<any>([]);
+const interestsList = ref<any>([]);
+const sellList = ref<any>([{}, {}, {}, {}, {}]);
+const tradeList = ref<any>([{}, {}, {}, {}, {}]);
+const goodsList = ref<any>([{}, {}, {}]);
+
+onMounted(() => {
+  if (getToken()) {
+    getInfo().then((res) => {
+      if (res.code == 200) {
+        userInfo.value = res.data.user;
+      }
+    });
+  }
+});
+
+//移出分类
+const leaveClassify = () => {
+  classifyShow.value = false;
+};
+
+//移入分类
+const enterClassify = (res: any) => {
+  classifyShow.value = true;
+  classifyId.value = res.id;
+  classifyInfo.value = res.children;
+};
+
+//头部分类
+getProductCategoryTree({}).then((res) => {
+  if (res.code == 200) {
+    classifyList.value = res.data;
+  }
+});
+
+//头部轮播
+getHomeAdList({}).then((res) => {
+  if (res.code == 200) {
+    carouselList.value = res.data;
+  }
+});
+
+//头部优易资讯
+getYouYiZiXunPage({}).then((res) => {
+  if (res.code == 200) {
+    realList.value = res.data;
+  }
+});
+
+//头部会员权益
+getHomeIconAd({}).then((res) => {
+  if (res.code == 200) {
+    interestsList.value = res.data;
+  }
+});
+
+//轮播展位商品(工业装修-轮播展位商品)
+getCarouselDisplayProductList({}).then((res) => {
+  if (res.code == 200) {
+    // sellList.value = res.data;
+  }
+});
+
+//商业标签(工业装修-商业标签)
+getBusinessLabelList({}).then((res) => {
+  if (res.code == 200) {
+    // tradeList.value = res.data;
+  }
+});
+
+//循环
+getIndustrialFloor({}).then((res) => {
+  if (res.code == 200) {
+    // goodsList.value = res.data;
+    res.data.forEach((item: any) => {
+      getIndustrialFloorProductList({ floorId: item.id }).then((res) => {
+        if (res.code == 200) {
+        }
+      });
+      getIndustrialFloorBrand({ floorId: item.id }).then((res) => {
+        if (res.code == 200) {
+        }
+      });
+    });
+  }
+});
+
+//为你推荐-分类
+getRecommendedCategory({}).then((res) => {
+  if (res.code == 200) {
+  }
+});
+
+//为你推荐-商品
+getRecommendedCategoryProductList({}).then((res) => {
+  if (res.code == 200) {
+  }
+});
+</script>
+
+<style lang="scss" scoped>
+.home-pages {
+  width: 100%;
+  .head-pages {
+    width: 100%;
+    background: #000000;
+
+    // 头部
+    .home-head {
+      width: 1200px;
+      margin: 0 auto;
+      position: relative;
+      display: flex;
+      gap: 0px 10px;
+
+      .classify {
+        width: 234px;
+        height: 540px;
+        background: #323232;
+        padding: 10px 0px;
+        &.classify-show {
+          position: absolute;
+          z-index: 10;
+          height: auto;
+          min-height: 540px;
+        }
+
+        .classify-list {
+          width: 100%;
+          height: 60px;
+          cursor: pointer;
+          position: relative;
+          display: flex;
+          flex-direction: column;
+          justify-content: center;
+          padding-left: 25px;
+
+          &.classify-hig {
+            border: 1px solid var(--el-color-primary);
+            border-right: 0px solid var(--el-color-primary);
+          }
+
+          .label {
+            width: 100%;
+            font-size: 14px;
+            color: #ffffff;
+            white-space: nowrap;
+            margin-right: 10px;
+
+            &:hover {
+              color: var(--el-color-primary);
+            }
+          }
+
+          .two-level {
+            display: flex;
+            align-items: center;
+            font-size: 12px;
+            color: #a2a2a2;
+            margin-top: 6px;
+
+            .two-hig {
+              &:hover {
+                color: var(--el-color-primary);
+              }
+            }
+          }
+        }
+      }
+
+      .classify-bos {
+        position: absolute;
+        top: 0;
+        right: 0;
+        width: 966px;
+        height: 100%;
+        border: 1px solid var(--el-color-primary);
+        background-color: #ffffff;
+        overflow-y: auto;
+        padding-left: 30px;
+        z-index: 10;
+
+        .classify-item {
+          display: flex;
+          padding-top: 10px;
+          border-bottom: 1px solid #e5e7eb;
+
+          .two-level {
+            width: 90px;
+            font-size: 14px;
+            color: var(--el-color-primary);
+            cursor: pointer;
+          }
+
+          .classify-icon {
+            margin: 4px 15px 0 15px;
+          }
+
+          .classify-label {
+            display: flex;
+            flex-wrap: wrap;
+            flex: 1;
+            font-size: 14px;
+            color: #364153;
+
+            div {
+              margin-right: 20px;
+              margin-bottom: 10px;
+              cursor: pointer;
+
+              &:hover {
+                color: var(--el-color-primary);
+              }
+            }
+          }
+        }
+      }
+
+      // 头部中间
+      .carousel-bos {
+        width: 756px;
+        height: 540px;
+        img {
+          width: 756px;
+          height: 540px;
+        }
+      }
+
+      //右边
+      .head-right {
+        flex: 1;
+        width: 0;
+        height: 540px;
+        background: #ffffff;
+        display: flex;
+        flex-direction: column;
+
+        .login-bos {
+          width: calc(100% - 20px);
+          height: 110px;
+          border-bottom: 1px solid #e5e7eb;
+          margin: 0 10px;
+          display: flex;
+          flex-direction: column;
+          justify-content: space-between;
+          padding: 16px 0;
+
+          .login-box {
+            display: flex;
+            align-items: center;
+
+            img {
+              width: 40px;
+              height: 40px;
+              margin-right: 8px;
+              border-radius: 40px;
+            }
+
+            .login-btn {
+              width: 100%;
+            }
+
+            .login1 {
+              font-size: 13px;
+              color: #444444;
+            }
+
+            .login2 {
+              margin-top: 2px;
+              font-size: 12px;
+              color: #6a7282;
+            }
+          }
+        }
+
+        .real-time {
+          width: calc(100% - 20px);
+          height: 227px;
+          border-bottom: 1px solid #e5e7eb;
+          margin: 0 10px;
+          padding-top: 15px;
+
+          .real-title {
+            position: relative;
+            margin-bottom: 12px;
+
+            &::after {
+              content: '';
+              top: 3px;
+              left: 0;
+              position: absolute;
+              width: 4px;
+              height: 14px;
+              background: var(--el-color-primary);
+            }
+
+            .real1 {
+              font-weight: 600;
+              font-size: 14px;
+              color: #1d2129;
+              padding-left: 15px;
+            }
+
+            .real2 {
+              font-size: 13px;
+              color: #83899f;
+              cursor: pointer;
+            }
+          }
+
+          .real-list {
+            width: 100%;
+            font-size: 14px;
+            color: #1d2129;
+            margin-bottom: 12px;
+            cursor: pointer;
+
+            &:hover {
+              color: var(--el-color-primary);
+            }
+          }
+        }
+
+        .interests {
+          flex: 1;
+          width: calc(100% - 20px);
+          margin: 0 10px;
+          padding-top: 15px;
+
+          .interests-title {
+            position: relative;
+            font-weight: 600;
+            font-size: 14px;
+            color: #1d2129;
+            padding-left: 15px;
+
+            &::after {
+              content: '';
+              top: 3px;
+              left: 0;
+              position: absolute;
+              width: 4px;
+              height: 14px;
+              background: var(--el-color-primary);
+            }
+          }
+
+          .interests-bos {
+            display: flex;
+            flex-wrap: wrap;
+
+            .interests-item {
+              width: 33.333%;
+              font-size: 12px;
+              color: #101828;
+              margin-top: 15px;
+              cursor: pointer;
+
+              &:hover {
+                color: var(--el-color-primary);
+              }
+
+              img {
+                width: 34px;
+                height: 34px;
+                margin-bottom: 7px;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  .pages-bos {
+    width: 1200px;
+    margin: 0 auto;
+
+    //轮播展位商品
+    .sell-bos {
+      width: 1200px;
+      display: flex;
+      gap: 0 20px;
+      margin-top: 30px;
+
+      .sell-list {
+        width: 224px;
+        height: 306px;
+        background: #ffffff;
+        border-radius: 10px;
+        padding: 20px;
+        display: flex;
+        flex-direction: column;
+        justify-content: space-between;
+        cursor: pointer;
+        transition: transform 0.2s ease;
+        &:hover {
+          transform: translateY(-2px);
+        }
+
+        .sell-img {
+          width: 184px;
+          height: 182px;
+        }
+
+        .sell-name {
+          width: 184px;
+          height: 38px;
+          font-size: 14px;
+          color: #101828;
+        }
+
+        .sell-price {
+          .price1 {
+            color: var(--el-color-primary);
+            font-size: 16px;
+            color: #e7000b;
+          }
+          .price2 {
+            font-size: 12px;
+            color: #99a1af;
+            line-height: 20px;
+            text-decoration-line: line-through;
+            text-transform: none;
+            margin-left: 6px;
+          }
+        }
+      }
+    }
+
+    //商业标签(工业装修-商业标签)
+    .trade-bos {
+      width: 1200px;
+      display: flex;
+      gap: 0 10px;
+      margin-top: 30px;
+      .trade-list {
+        width: 292.5px;
+        height: 146px;
+        background: #ffffff;
+        border-radius: 4px;
+        padding: 22px;
+        cursor: pointer;
+        transition: transform 0.2s ease;
+        &:hover {
+          transform: translateY(-2px);
+        }
+        .trade-box {
+          width: 144px;
+          height: 100%;
+          .trade-title {
+            font-weight: 600;
+            font-size: 16px;
+            color: #000000;
+          }
+          .trade-info {
+            font-size: 12px;
+            color: #364153;
+            height: 32px;
+          }
+          .trade-look {
+            width: 89px;
+            height: 28px;
+          }
+        }
+        .trade-img {
+          width: 79px;
+          height: 79px;
+        }
+      }
+    }
+    //标题
+    .goods-title {
+      width: 1200px;
+      height: 56px;
+      border-radius: 10px;
+      background: #ffffff;
+      font-weight: 600;
+      font-size: 20px;
+      margin-top: 20px;
+      img {
+        width: 30px;
+        height: 21px;
+        margin: 0 10px;
+      }
+    }
+    //循环-商品
+    .goods-bos {
+      .goods-box {
+        display: flex;
+        gap: 0 10px;
+        margin-top: 15px;
+        .goods-one {
+          width: 236px;
+          height: 560px;
+          border-radius: 10px;
+          background: #ffffff;
+          cursor: pointer;
+          transition: transform 0.2s ease;
+          &:hover {
+            transform: translateY(-2px);
+          }
+        }
+        .goods-shop {
+          width: 802px;
+          height: 560px;
+          display: flex;
+          flex-wrap: wrap;
+          gap: 10px;
+          .shop-list {
+            width: 193px;
+            height: 275px;
+            background: #ffffff;
+            border-radius: 10px;
+            padding: 20px;
+            cursor: pointer;
+            transition: transform 0.2s ease;
+            &:hover {
+              transform: translateY(-2px);
+            }
+
+            .shop-img {
+              width: 153px;
+              height: 150px;
+              border-radius: 6px;
+            }
+
+            .shop-name {
+              width: 153px;
+              height: 38px;
+              font-size: 14px;
+              color: #101828;
+            }
+
+            .shop-price {
+              .price1 {
+                color: var(--el-color-primary);
+                font-size: 16px;
+                color: #e7000b;
+              }
+              .price2 {
+                font-size: 12px;
+                color: #99a1af;
+                line-height: 20px;
+                text-decoration-line: line-through;
+                text-transform: none;
+                margin-left: 6px;
+              }
+            }
+          }
+        }
+        .goods-brand {
+          width: 142px;
+          height: 560px;
+          border-radius: 10px;
+          background: #ffffff;
+          padding: 20px 10px;
+          .brand-bos {
+            width: 100%;
+            display: flex;
+            flex-direction: column;
+            gap: 10px 0;
+            img {
+              width: 100%;
+              height: 74px;
+              border-radius: 4px;
+              border: 1px solid #e5e7eb;
+              cursor: pointer;
+              transition: transform 0.2s ease;
+              &:hover {
+                transform: translateY(-2px);
+              }
+            }
+          }
+          .brand-more {
+            color: var(--el-color-primary);
+            font-size: 14px;
+            cursor: pointer;
+          }
+        }
+      }
+    }
+
+    //为你推荐
+    .nav-bos {
+      width: 1200px;
+      height: 48px;
+      background: #ffffff;
+      border-radius: 10px;
+      margin-top: 14px;
+      padding: 0 1.5px;
+      .nav-list {
+        width: 133px;
+        position: relative;
+        font-size: 14px;
+        color: #000000;
+        text-align: center;
+        cursor: pointer;
+        &.hig {
+          color: var(--el-color-primary);
+        }
+        &::after {
+          content: '';
+          position: absolute;
+          right: 0;
+          top: 2.5px;
+          width: 1px;
+          height: 14px;
+          background-color: #e5e7eb;
+        }
+        &:last-child::after {
+          display: none;
+        }
+      }
+    }
+    .recommend {
+      margin-top: 14px;
+      gap: 14px 20px;
+      flex-wrap: wrap;
+      margin-bottom: 60px;
+    }
+  }
+}
+</style>

+ 1392 - 4
src/views/home/index.vue

@@ -1,9 +1,1397 @@
 <template>
-  <div>
-    <h1>优易365主站</h1>
+  <div class="home-pages">
+    <!--  头部 -->
+    <div class="home-head" @mouseleave="leaveClassify">
+      <div class="classify" :class="classifyShow ? 'classify-show' : ''">
+        <div
+          class="classify-list"
+          v-for="(item, index) in classifyList"
+          :class="item.id == classifyId && classifyShow ? 'classify-hig' : ''"
+          :key="index"
+          @mouseenter="enterClassify(item)"
+          v-show="classifyShow ? true : Number(index) < 13"
+        >
+          <div class="label ellipsis" @click="onPath('/search?type=1&topCategoryId=' + item.id)">{{ item.label }}</div>
+          <div class="info info1 ellipsis" v-if="item.extra && item.extra.oneLable1">{{ item.extra.oneLable1 }}</div>
+          <div class="info ellipsis" v-if="item.extra && item.extra.oneLable2">{{ item.extra.oneLable2 }}</div>
+          <div class="classify-border" v-if="item.id == classifyId && classifyShow"></div>
+        </div>
+      </div>
+      <div class="classify-bos" v-if="classifyShow">
+        <div v-for="(item, index) in classifyInfo" :key="index" class="classify-item" @click="onPath('/search?type=2&middleCategoryId=' + item.id)">
+          <div class="two-level ellipsis">{{ item.label || '' }}</div>
+          <el-icon class="classify-icon" :size="14" color="#364153">
+            <ArrowRight />
+          </el-icon>
+          <div class="classify-label">
+            <div v-for="(item1, index1) in item.children" :key="index1" @click="onPath('/search?type=3&bottomCategoryId=' + item1.id)">
+              {{ item1.label || '' }}
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="head-bos">
+        <div class="carousel">
+          <el-carousel trigger="click" height="407px">
+            <el-carousel-item v-for="item in carouselList" :key="item">
+              <img :src="item.imageUrl" alt="" />
+            </el-carousel-item>
+          </el-carousel>
+        </div>
+        <div class="head-box">
+          <div v-for="(item, index) in AdList" :key="index" class="head-item" @click="onPath('/plan?id=' + item.id)">
+            <img :src="item.imageUrl" alt="" />
+            <!-- <div class="head-title">
+              <div class="head1">{{ item.title }}</div>
+              <div class="head2 flex-row-center">
+                <div>查看方案</div>
+                <el-icon><ArrowRight /></el-icon>
+              </div>
+            </div> -->
+          </div>
+        </div>
+      </div>
+      <!-- 右边 -->
+      <div class="head-right">
+        <div class="login-bos">
+          <div class="login-box">
+            <img :src="userInfo.avatar ? userInfo.avatar : profile" alt="" />
+            <div>
+              <div class="login1">您好,欢迎来到优易达</div>
+              <div class="login2">{{ userInfo.nickName ? userInfo.nickName : '请先登录' }}</div>
+            </div>
+          </div>
+          <div class="login-btn">
+            <el-button v-if="!userInfo.nickName" type="primary" round size="small" style="width: 64px" @click="onPath('/login')">登录</el-button>
+            <el-button v-if="!userInfo.nickName" type="primary" plain round size="small" style="width: 64px" @click="onPath('/reg')">注册</el-button>
+            <el-button v-if="userInfo.nickName" type="primary" plain round size="small" style="width: 64px" @click="onPath('/reg')">退出</el-button>
+          </div>
+        </div>
+        <div class="real-time">
+          <div class="real-title flex-row-between">
+            <div class="real1">优易资讯</div>
+            <div class="real2 flex-row-start">
+              <div>更多</div>
+              <el-icon :size="13" color="#83899F">
+                <ArrowRight />
+              </el-icon>
+            </div>
+          </div>
+          <template v-for="(item, index) in realList" :key="index">
+            <div @click="onPath('/solve/real?id=' + item.id)" class="real-list ellipsis" v-if="Number(index) < 7">{{ item.announcementTitle }}</div>
+          </template>
+        </div>
+        <div class="interests">
+          <div class="interests-title">企业会员权益</div>
+          <div class="interests-bos">
+            <div v-for="(item, index) in interestsList" :key="index" class="interests-item flex-column-center">
+              <img :src="item.imageUrl" alt="" />
+              <div>{{ item.title }}</div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <!-- 热门方案 -->
+    <div class="home-title flex-row-between">
+      <div>
+        <span class="title1">{{ hotTitle.title }}</span>
+        <span class="title2">{{ hotTitle.subtitle }}</span>
+      </div>
+      <div class="title-more flex-row-start" @click="onPath(hotTitle.linkUrl ? hotTitle.linkUrl : '/plan', 2)">
+        <div style="margin-right: 5px">{{ hotTitle.linkWord }}</div>
+        <el-icon :size="13" color="#83899F">
+          <ArrowRight />
+        </el-icon>
+      </div>
+    </div>
+    <div class="hot-bos">
+      <template v-for="(item, index) in hotList" :key="index">
+        <div class="hot-list flex-column-center" v-if="Number(index) < 4" @click="onPath('/plan_info?id=' + item.id)">
+          <div class="hot1">{{ item.advertTitle }}</div>
+          <div class="hot2">{{ item.advertBrief }}</div>
+          <img :src="item.coverImage" alt="" />
+        </div>
+      </template>
+    </div>
+    <!-- 场景采购 -->
+    <div class="home-title flex-row-between">
+      <div>
+        <span class="title1">{{ sceneTitle.title }}</span>
+        <span class="title2">{{ sceneTitle.subtitle }}</span>
+      </div>
+      <div class="title-more flex-row-start" @click="onPath(sceneTitle.linkUrl ? sceneTitle.linkUrl : '/plan/procure', 2)">
+        <div style="margin-right: 5px">{{ sceneTitle.linkWord }}</div>
+        <el-icon :size="13" color="#83899F">
+          <ArrowRight />
+        </el-icon>
+      </div>
+    </div>
+    <div class="scene-bos">
+      <template v-for="(item, index) in sceneList" :key="index">
+        <div class="scene-list" v-if="Number(index) < 5" @click="onPath('/plan_info?id=' + item.id)">
+          <div class="scene-box">
+            <div class="scene1">{{ item.advertTitle }}</div>
+            <div class="scene2">{{ item.advertBrief }}</div>
+          </div>
+          <img :src="item.coverImage" alt="" />
+        </div>
+      </template>
+    </div>
+    <!-- 大牌推荐 -->
+    <div class="home-title flex-row-between">
+      <div>
+        <span class="title1">{{ bigbrandTitle.title }}</span>
+        <span class="title2">{{ bigbrandTitle.subtitle }}</span>
+      </div>
+      <div class="title-more flex-row-start">
+        <div style="margin-right: 5px">{{ bigbrandTitle.linkWord }}</div>
+        <el-icon :size="13" color="#83899F">
+          <ArrowRight />
+        </el-icon>
+      </div>
+    </div>
+    <div class="big-brand">
+      <img class="bigBrand-one" :src="bigbrandOne.coverImage" alt="" />
+      <div class="bigBrand-bos">
+        <template v-for="(item, index) in bigbrandList" :key="index">
+          <div class="bigBrand-list" v-if="Number(index) < 10">
+            <img :src="item.coverImage" alt="" />
+            <div class="bigBrand1">{{ item.advertTitle || '' }}</div>
+            <div class="bigBrand2">
+              {{ item.advertBrief || '' }}
+            </div>
+          </div>
+        </template>
+      </div>
+    </div>
+    <!-- 行家精选 -->
+    <div class="home-title flex-row-between">
+      <div>
+        <span class="title1">{{ expertTitle.title }}</span>
+        <span class="title2">{{ expertTitle.subtitle }}</span>
+      </div>
+      <div class="title-more flex-row-start" @click="onPath(hotTitle.linkUrl ? hotTitle.linkUrl : '/search/special', 2)">
+        <div style="margin-right: 5px">{{ expertTitle.linkWord }}</div>
+        <el-icon :size="13" color="#83899F">
+          <ArrowRight />
+        </el-icon>
+      </div>
+    </div>
+    <div class="expert-bos">
+      <template v-for="(item, index) in expertList" :key="index">
+        <div class="expert-list" v-if="Number(index) < 5" @click="onPath('/item?id=' + item.id)">
+          <img :src="item.productImage" alt="" />
+          <div class="itemName ellipsis">{{ item.itemName || '' }}</div>
+          <div class="price">
+            <span class="memberPrice">¥{{ item.memberPrice }}</span>
+            <span class="marketPrice">¥{{ item.marketPrice }}</span>
+          </div>
+        </div>
+      </template>
+    </div>
+    <!-- 采购指南 -->
+    <div class="home-title flex-row-between">
+      <div>
+        <span class="title1">{{ procureTitle.title }}</span>
+        <span class="title2">{{ procureTitle.subtitle }}</span>
+      </div>
+      <div class="title-more flex-row-start" @click="onPath(hotTitle.linkUrl ? hotTitle.linkUrl : '/plan/guide', 2)">
+        <div style="margin-right: 5px">{{ procureTitle.linkWord }}</div>
+        <el-icon :size="13" color="#83899F">
+          <ArrowRight />
+        </el-icon>
+      </div>
+    </div>
+    <div class="procure-bos">
+      <template v-for="(item, index) in expertList" :key="index">
+        <div class="procure-list" v-if="Number(index) < 3">
+          <img :src="item.productImage" alt="" />
+          <div class="procure1">{{ item.itemName || '办公室' }}</div>
+          <div class="procure2">{{ item.itemName || '干款好礼·百大品牌·个性定制' }}</div>
+        </div>
+      </template>
+    </div>
+    <!-- 循环-商品 -->
+    <div v-for="(item1, index1) in homeList" :key="index1">
+      <!-- 头部 -->
+      <div class="home-title flex-row-between">
+        <div>
+          <span class="title1">{{ item1.floorName }}</span>
+          <span class="title2">{{ item1.floorDescribe }}</span>
+        </div>
+        <div class="title-more flex-row-start">
+          <div style="margin-right: 5px">{{ item1.floorLabel }}</div>
+          <el-icon :size="13" color="#83899F">
+            <ArrowRight />
+          </el-icon>
+        </div>
+      </div>
+      <!-- 商品 -->
+      <div class="goods-bos" v-if="item1.imgOne">
+        <img class="goods-img" :src="item1.imgOne" alt="" />
+        <div class="home1-bos" v-if="item1.home1List && item1.home1List.length > 0">
+          <div class="floorName">{{ item1.floorName }}</div>
+          <div v-for="(item2, index2) in item1.home1List" :key="index2" class="home1-list">
+            <img :src="item2.img" alt="" />
+            <div style="flex: 1; width: 0">
+              <div class="advertiseName">{{ item2.advertiseName }}</div>
+              <div class="advertiseDescribe ellipsis">{{ item2.advertiseDescribe }}新政策执行中心城中心城中心啊实打实大苏打实打实水水的</div>
+            </div>
+          </div>
+        </div>
+        <div class="home2-bos" v-if="item1.home2List && item1.home2List.length > 0">
+          <div>
+            <div class="floorName">发现</div>
+            <div class="home2-box">
+              <div v-for="(item2, index2) in item1.home2List" :key="index2" class="home2-list">
+                <div style="flex: 1; width: 0">
+                  <div class="advertiseName ellipsis">{{ item2.advertiseName }}</div>
+                  <div class="advertiseDescribe ellipsis">{{ item2.advertiseDescribe }}</div>
+                  <el-button class="bnt" type="primary" size="small">立即进入</el-button>
+                </div>
+                <img :src="item2.img" alt="" />
+              </div>
+            </div>
+          </div>
+          <div class="home2-two" v-if="item1.infoTwo">
+            <div class="advertiseName">{{ item1.infoTwo.advertiseName }}</div>
+            <div class="advertiseDescribe">{{ item1.infoTwo.advertiseDescribe }}</div>
+            <img :src="item1.infoTwo.img" alt="" />
+          </div>
+        </div>
+      </div>
+      <div class="shop-bos">
+        <div class="shop-nav">
+          <div class="nav-title">采购导航</div>
+          <div class="nav-bos">
+            <div v-for="(item2, index2) in item1.navList" :key="index2" class="nav-list flex-row-center" :class="index2 == 0 ? 'hig' : ''">
+              {{ item2.labelName }}
+            </div>
+          </div>
+        </div>
+        <template v-for="(item2, index2) in item1.shopList" :key="index2">
+          <div class="shop-list" v-if="Number(index2) < 4" @click="onInfo(item2)">
+            <img :src="item2.productImage" alt="" />
+            <div class="itemName">{{ item2.itemName }}</div>
+            <div class="price">
+              <span class="memberPrice">¥{{ item2.memberPrice }}</span>
+              <span class="marketPrice">¥{{ item2.marketPrice }}</span>
+            </div>
+          </div>
+        </template>
+      </div>
+    </div>
+    <!-- 项目案例 -->
+    <div class="home-title flex-row-between">
+      <div>
+        <span class="title1">{{ projectTitle.title }}</span>
+        <span class="title2">{{ projectTitle.subtitle }}</span>
+      </div>
+      <div class="title-more flex-row-start" @click="onPath(projectTitle.linkUrl ? projectTitle.linkUrl : '/plan/project', 2)">
+        <div style="margin-right: 5px">{{ projectTitle.linkWord }}</div>
+        <el-icon :size="13" color="#83899F">
+          <ArrowRight />
+        </el-icon>
+      </div>
+    </div>
+    <div class="project-bos">
+      <template v-for="(item, index) in projectList" :key="index">
+        <div class="project-list" v-if="Number(index) < 3">
+          <img :src="item.uploadProgram" alt="" />
+          <div class="project-box">
+            <div class="project1">{{ item.caseTitle || '' }}</div>
+            <div class="project2">
+              {{ item.projectBrief || '' }}
+            </div>
+            <div class="project-more flex-row-between">
+              <div></div>
+              <div class="flex-row-start">
+                <div style="margin-right: 5px">了解详情</div>
+                <el-icon :size="14" color="#E7000B"><ArrowRight /></el-icon>
+              </div>
+            </div>
+          </div>
+        </div>
+      </template>
+    </div>
   </div>
 </template>
 
-<script setup lang="ts"></script>
+<script setup lang="ts">
+import profile from '@/assets/images/profile.jpg';
+import { onPath } from '@/utils/siteConfig';
+import { getToken } from '@/utils/auth';
+import { getInfo } from '@/api/login';
+import {
+  getProductCategoryTree,
+  getHomeAdList,
+  getYouYiZiXunPage,
+  getEnterpriseMemberEquityList,
+  getHomeThreeAdList,
+  getHotSchemeTitle,
+  getHotSchemeList,
+  getScenePurchaseTitle,
+  getScenePurchaseList,
+  getPlatformFlashSaleTitle,
+  getPlatformFlashSaleList,
+  getExpertSelectionTitle,
+  getPurchaseGuideTitle,
+  getExpertSelectionList,
+  getClassificationFloorList,
+  getClassificationFloorDetail,
+  getClassificationFloorLabel,
+  getClassificationFloorDetail2,
+  getProjectCaseTitle,
+  getProjectCaseList
+} from '@/api/home/index';
 
-<style lang="scss" scoped></style>
+const userInfo = ref<any>({});
+const classifyList = ref<any>([]);
+const classifyShow = ref<any>(false);
+const classifyId = ref<any>('');
+const classifyInfo = ref<any>([]);
+const carouselList = ref<any>([]);
+const realList = ref<any>([]);
+const interestsList = ref<any>([]);
+const AdList = ref<any>([]);
+const hotTitle = ref<any>('');
+const hotList = ref<any>([]);
+const sceneTitle = ref<any>('');
+const sceneList = ref<any>([]);
+const expertTitle = ref<any>('');
+const expertList = ref<any>([{}, {}, {}, {}, {}]);
+const procureTitle = ref<any>('');
+const procureList = ref<any>([{}, {}, {}, {}, {}]);
+const projectTitle = ref<any>('');
+const projectList = ref<any>([{}, {}, {}, {}, {}]);
+
+const bigbrandTitle = ref<any>('');
+const bigbrandList = ref<any>([]);
+const bigbrandOne = ref<any>({});
+
+const homeList = ref<any>([]);
+const router = useRouter();
+
+onMounted(() => {
+  if (getToken()) {
+    getInfo().then((res) => {
+      if (res.code == 200) {
+        userInfo.value = res.data.user;
+      }
+    });
+  }
+});
+
+//移入分类
+const enterClassify = (res: any) => {
+  classifyShow.value = true;
+  classifyId.value = res.id;
+  classifyInfo.value = res.children;
+};
+
+//移出分类
+const leaveClassify = () => {
+  classifyShow.value = false;
+};
+
+//头部分类
+import { categoryStore } from '@/store/modules/category';
+const categoryStoreStore = categoryStore();
+onMounted(async () => {
+  try {
+    // 根据当前路由路径获取分类数据
+    classifyList.value = await categoryStoreStore.fetchCategories('/index');
+  } catch (error) {
+    console.error('获取分类失败:', error);
+  }
+});
+
+//头部轮播
+getHomeAdList({}).then((res) => {
+  if (res.code == 200) {
+    carouselList.value = res.data;
+  }
+});
+
+//头部优易资讯
+getYouYiZiXunPage({}).then((res) => {
+  if (res.code == 200) {
+    realList.value = res.data;
+  }
+});
+
+//头部会员权益
+getEnterpriseMemberEquityList({}).then((res) => {
+  if (res.code == 200) {
+    interestsList.value = res.data;
+  }
+});
+
+//首页三联广告(平台装修-楼层广告-首页三联广告)
+getHomeThreeAdList({}).then((res) => {
+  if (res.code == 200) {
+    AdList.value = res.data;
+  }
+});
+
+//热门方案标题
+getHotSchemeTitle({}).then((res) => {
+  if (res.code == 200) {
+    hotTitle.value = res.data;
+  }
+});
+
+//热门方案列表
+getHotSchemeList({}).then((res) => {
+  if (res.code == 200) {
+    hotList.value = res.data;
+  }
+});
+
+//场景采购标题
+getScenePurchaseTitle({}).then((res) => {
+  if (res.code == 200) {
+    sceneTitle.value = res.data;
+  }
+});
+
+//场景采购列表
+getScenePurchaseList({}).then((res) => {
+  if (res.code == 200) {
+    sceneList.value = res.data;
+  }
+});
+
+//大牌推荐标题(平台闪购标题)
+getPlatformFlashSaleTitle({}).then((res) => {
+  if (res.code == 200) {
+    bigbrandTitle.value = res.data;
+  }
+});
+
+//大牌推荐列表(平台闪购列表)
+getPlatformFlashSaleList({}).then((res) => {
+  if (res.code == 200) {
+    if (res.data.length > 0) {
+      bigbrandOne.value = res.data[0];
+      bigbrandList.value = res.data.slice(1);
+    }
+  }
+});
+
+//行家精选标题
+getExpertSelectionTitle({}).then((res) => {
+  if (res.code == 200) {
+    expertTitle.value = res.data;
+  }
+});
+
+//行家精选列表
+getExpertSelectionList({}).then((res) => {
+  if (res.code == 200) {
+    expertList.value = res.data;
+  }
+});
+
+//采购指南标题
+getPurchaseGuideTitle({}).then((res) => {
+  if (res.code == 200) {
+    procureTitle.value = res.data;
+  }
+});
+
+//项目案例标题(平台装修-项目案例)
+getProjectCaseTitle({}).then((res) => {
+  if (res.code == 200) {
+    projectTitle.value = res.data;
+  }
+});
+
+//项目案例列表(平台装修-项目案例)
+getProjectCaseList({}).then((res) => {
+  if (res.code == 200) {
+    projectList.value = res.data;
+  }
+});
+
+//外面循环
+getClassificationFloorList({}).then(async (res) => {
+  if (res.code == 200) {
+    for (const item of res.data) {
+      try {
+        const datas1 = await getClassificationFloorDetail(item.floorNo);
+        if (datas1.code == 200) {
+          if (datas1.data.length > 0) {
+            item.imgOne = datas1.data[0];
+            if (datas1.data.length > 1) {
+              item.home1List = datas1.data.slice(1, 4);
+            }
+            if (datas1.data.length > 4) {
+              item.home2List = datas1.data.slice(4, 6);
+            }
+            if (datas1.data.length > 6) {
+              item.infoTwo = datas1.data[6];
+            }
+          }
+        }
+
+        const datas2 = await getClassificationFloorLabel(item.floorNo);
+        if (datas2.code == 200) {
+          item.navList = datas2.data;
+        }
+
+        const datas3 = await getClassificationFloorDetail2(item.floorNo);
+        if (datas2.code == 200) {
+          item.shopList = datas3.data;
+        }
+      } catch (error) {}
+    }
+
+    homeList.value = res.data;
+  }
+});
+
+const onInfo = (res: any) => {
+  router.push('/shop/info?id=' + res.id);
+};
+</script>
+
+<style lang="scss" scoped>
+.home-pages {
+  width: 1200px;
+  margin: 0 auto;
+
+  // 头部
+  .home-head {
+    width: 1200px;
+    position: relative;
+    display: flex;
+    gap: 0px 10px;
+
+    .classify {
+      width: 234px;
+      height: 540px;
+      background: #ffffff;
+      &.classify-show {
+        position: absolute;
+        z-index: 10;
+        height: auto;
+        min-height: 540px;
+      }
+
+      .classify-list {
+        width: 100%;
+        height: 40px;
+        cursor: pointer;
+        display: flex;
+        align-items: center;
+        padding-left: 15px;
+        position: relative;
+
+        &.classify-hig {
+          border: 1px solid var(--el-color-primary);
+          border-right: 0px solid var(--el-color-primary);
+        }
+
+        .label {
+          max-width: 100px;
+          font-weight: 600;
+          font-size: 14px;
+          color: #101828;
+          white-space: nowrap;
+          margin-right: 10px;
+
+          &:hover {
+            color: var(--el-color-primary);
+          }
+        }
+
+        .info {
+          max-width: 50px;
+          font-size: 12px;
+          color: #364153;
+          white-space: nowrap;
+
+          &.info1 {
+            margin-right: 6px;
+          }
+
+          &:hover {
+            color: var(--el-color-primary);
+          }
+        }
+
+        .classify-border {
+          position: absolute;
+          right: -1px;
+          top: 0px;
+          width: 1px;
+          height: 38px;
+          background-color: #ffffff;
+          z-index: 2;
+        }
+      }
+    }
+
+    .classify-bos {
+      position: absolute;
+      top: 0;
+      right: 0;
+      width: 966px;
+      height: 100%;
+      border: 1px solid var(--el-color-primary);
+      background-color: #ffffff;
+      overflow-y: auto;
+      padding-left: 30px;
+      z-index: 10;
+
+      .classify-item {
+        display: flex;
+        padding-top: 10px;
+        border-bottom: 1px solid #e5e7eb;
+
+        .two-level {
+          width: 90px;
+          font-size: 14px;
+          color: var(--el-color-primary);
+          cursor: pointer;
+        }
+
+        .classify-icon {
+          margin: 4px 15px 0 15px;
+        }
+
+        .classify-label {
+          display: flex;
+          flex-wrap: wrap;
+          flex: 1;
+          font-size: 14px;
+          color: #364153;
+
+          div {
+            margin-right: 20px;
+            margin-bottom: 10px;
+            cursor: pointer;
+
+            &:hover {
+              color: var(--el-color-primary);
+            }
+          }
+        }
+      }
+    }
+
+    // 头部中间
+    .head-bos {
+      width: 756px;
+
+      .carousel {
+        width: 756px;
+        height: 407px;
+        background: #ffffff;
+
+        img {
+          width: 756px;
+          height: 407px;
+        }
+      }
+
+      .head-box {
+        width: 756px;
+        height: 122px;
+        margin-top: 10px;
+        display: flex;
+        gap: 0 10px;
+        .head-item {
+          flex: 1;
+          background-color: #ffffff;
+          height: 122px;
+          display: flex;
+          // padding-left: 20px;
+          align-items: center;
+          cursor: pointer;
+          border-radius: 5px;
+          overflow: hidden;
+          img {
+            width: 100%;
+            height: 100%;
+            // width: 84px;
+            // height: 84px;
+            // margin-right: 10px;
+            // border-radius: 10px;
+          }
+          .head-title {
+            .head1 {
+              font-weight: 550;
+              font-size: 22px;
+              color: #101828;
+            }
+            .head2 {
+              width: 76px;
+              height: 21px;
+              border-radius: 34px;
+              border: 1px solid #000000;
+              font-size: 12px;
+              color: #000000;
+              margin-top: 6px;
+            }
+          }
+        }
+      }
+    }
+
+    //右边
+    .head-right {
+      flex: 1;
+      width: 0;
+      height: 540px;
+      background: #ffffff;
+      display: flex;
+      flex-direction: column;
+
+      .login-bos {
+        width: calc(100% - 20px);
+        height: 110px;
+        border-bottom: 1px solid #e5e7eb;
+        margin: 0 10px;
+        display: flex;
+        flex-direction: column;
+        justify-content: space-between;
+        padding: 16px 0;
+
+        .login-box {
+          display: flex;
+          align-items: center;
+
+          img {
+            width: 40px;
+            height: 40px;
+            margin-right: 8px;
+            border-radius: 40px;
+          }
+
+          .login-btn {
+            width: 100%;
+          }
+
+          .login1 {
+            font-size: 13px;
+            color: #444444;
+          }
+
+          .login2 {
+            margin-top: 2px;
+            font-size: 12px;
+            color: #6a7282;
+          }
+        }
+      }
+
+      .real-time {
+        width: calc(100% - 20px);
+        height: 227px;
+        border-bottom: 1px solid #e5e7eb;
+        margin: 0 10px;
+        padding-top: 15px;
+
+        .real-title {
+          position: relative;
+          margin-bottom: 12px;
+
+          &::after {
+            content: '';
+            top: 3px;
+            left: 0;
+            position: absolute;
+            width: 4px;
+            height: 14px;
+            background: var(--el-color-primary);
+          }
+
+          .real1 {
+            font-weight: 600;
+            font-size: 14px;
+            color: #1d2129;
+            padding-left: 15px;
+          }
+
+          .real2 {
+            font-size: 13px;
+            color: #83899f;
+            cursor: pointer;
+          }
+        }
+
+        .real-list {
+          width: 100%;
+          font-size: 14px;
+          color: #1d2129;
+          margin-bottom: 12px;
+          cursor: pointer;
+
+          &:hover {
+            color: var(--el-color-primary);
+          }
+        }
+      }
+
+      .interests {
+        flex: 1;
+        width: calc(100% - 20px);
+        margin: 0 10px;
+        padding-top: 15px;
+
+        .interests-title {
+          position: relative;
+          font-weight: 600;
+          font-size: 14px;
+          color: #1d2129;
+          padding-left: 15px;
+
+          &::after {
+            content: '';
+            top: 3px;
+            left: 0;
+            position: absolute;
+            width: 4px;
+            height: 14px;
+            background: var(--el-color-primary);
+          }
+        }
+
+        .interests-bos {
+          display: flex;
+          flex-wrap: wrap;
+
+          .interests-item {
+            width: 33.333%;
+            font-size: 12px;
+            color: #101828;
+            margin-top: 15px;
+            cursor: pointer;
+
+            &:hover {
+              color: var(--el-color-primary);
+            }
+
+            img {
+              width: 34px;
+              height: 34px;
+              margin-bottom: 7px;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  //标题
+  .home-title {
+    width: 1200px;
+    height: 56px;
+    background: #ffffff;
+    margin-top: 30px;
+    padding: 0 20px;
+
+    .title1 {
+      font-weight: 600;
+      font-size: 20px;
+      color: #101828;
+    }
+
+    .title2 {
+      font-size: 14px;
+      color: #364153;
+      margin-left: 10px;
+    }
+
+    .title-more {
+      font-size: 14px;
+      color: #364153;
+      cursor: pointer;
+
+      &:hover {
+        color: var(--el-color-primary);
+      }
+    }
+  }
+
+  //热门方案
+  .hot-bos {
+    height: 176px;
+    width: 1200px;
+    display: flex;
+    gap: 0 18px;
+    margin-top: 12px;
+
+    .hot-list {
+      flex: 1;
+      height: 176px;
+      background: #ffffff;
+      border-radius: 10px 10px 10px 10px;
+      cursor: pointer;
+
+      .hot1 {
+        font-weight: 600;
+        font-size: 16px;
+        color: #101828;
+      }
+
+      .hot2 {
+        font-size: 14px;
+        color: #364153;
+        margin: 2px 0 14px 0;
+      }
+
+      img {
+        width: 80px;
+        height: 80px;
+      }
+    }
+  }
+
+  // 场景采购
+  .scene-bos {
+    height: 304px;
+    width: 1200px;
+    display: flex;
+    gap: 0 18px;
+    margin-top: 12px;
+
+    .scene-list {
+      flex: 1;
+      height: 304px;
+      background: #ffffff;
+      position: relative;
+      cursor: pointer;
+
+      .scene-box {
+        padding-top: 35px;
+        position: absolute;
+        z-index: 2;
+        width: 100%;
+
+        .scene1 {
+          font-weight: 600;
+          font-size: 30px;
+          color: #ffffff;
+          text-align: center;
+          width: 100%;
+        }
+
+        .scene2 {
+          font-size: 17px;
+          color: #ffffff;
+          text-align: center;
+          width: 100%;
+          margin-top: 4px;
+        }
+      }
+
+      img {
+        position: absolute;
+        width: 100%;
+        height: 100%;
+        top: 0;
+        left: 0;
+        background-color: #f4f4f4;
+      }
+    }
+  }
+
+  // 大牌推荐
+  .big-brand {
+    height: 334px;
+    width: 1200px;
+    margin-top: 12px;
+    display: flex;
+
+    .bigBrand-one {
+      width: 233px;
+      height: 334px;
+      margin-right: 10px;
+    }
+
+    .bigBrand-bos {
+      flex: 1;
+      width: 0;
+      display: flex;
+      flex-wrap: wrap;
+      gap: 10px;
+
+      .bigBrand-list {
+        width: 183.4px;
+        height: 162px;
+        background: #ffffff;
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        padding: 32px 20px 0 20px;
+
+        img {
+          width: 152px;
+          height: 29px;
+        }
+
+        .bigBrand1 {
+          font-weight: 600;
+          font-size: 14px;
+          color: #101828;
+          margin: 10px 0 4px 0;
+        }
+
+        .bigBrand2 {
+          font-weight: 400;
+          font-size: 12px;
+          color: #364153;
+          display: -webkit-box;
+          -webkit-line-clamp: 2;
+          line-clamp: 2; /* 添加标准属性 */
+          -webkit-box-orient: vertical;
+          overflow: hidden;
+          text-overflow: ellipsis;
+        }
+      }
+    }
+  }
+
+  // 行家精选
+  .expert-bos {
+    width: 1200px;
+    display: flex;
+    margin-top: 12px;
+    .expert-list {
+      width: 230px;
+      height: 306px;
+      background: #ffffff;
+      margin-left: 12.5px;
+      padding: 20px;
+      cursor: pointer;
+      &:first-child {
+        margin-left: 0;
+      }
+      img {
+        width: 100%;
+        height: 190px;
+      }
+      .itemName {
+        font-weight: 400;
+        font-size: 14px;
+        color: #101828;
+        margin: 27px 0 2px 0;
+      }
+      .price {
+        .memberPrice {
+          color: var(--el-color-primary);
+          font-size: 16px;
+          color: #e7000b;
+        }
+        .marketPrice {
+          font-size: 12px;
+          color: #99a1af;
+          line-height: 20px;
+          text-decoration-line: line-through;
+          text-transform: none;
+          margin-left: 6px;
+        }
+      }
+    }
+  }
+
+  // 采购指南
+  .procure-bos {
+    display: flex;
+    width: 1200px;
+    margin-top: 12px;
+    gap: 0 15px;
+    .procure-list {
+      width: 390px;
+      height: 268px;
+      background: #ffffff;
+      cursor: pointer;
+      img {
+        width: 390px;
+        height: 200px;
+      }
+      .procure1 {
+        padding: 12px 0 4px 20px;
+        font-weight: 600;
+        font-size: 14px;
+        color: #101828;
+      }
+      .procure2 {
+        padding-left: 20px;
+        font-size: 12px;
+        color: #364153;
+      }
+    }
+  }
+
+  //循环-商品
+  .goods-bos {
+    height: 340px;
+    width: 1200px;
+    margin-top: 14px;
+    display: flex;
+
+    .goods-img {
+      width: 230px;
+      height: 340px;
+      cursor: pointer;
+    }
+
+    .home1-bos {
+      width: 476px;
+      height: 340px;
+      background: #ffffff;
+      margin-left: 10px;
+      padding: 18px 20px 0 20px;
+      display: flex;
+      flex-direction: column;
+
+      .floorName {
+        font-weight: 600;
+        font-size: 16px;
+        color: #101828;
+      }
+
+      .home1-list {
+        flex: 1;
+        display: flex;
+        border-bottom: 1px solid #e5e7eb;
+        align-items: center;
+        cursor: pointer;
+
+        .advertiseName {
+          font-weight: 600;
+          font-size: 14px;
+          color: #101828;
+        }
+
+        .advertiseDescribe {
+          font-weight: 400;
+          font-size: 12px;
+          color: #364153;
+          margin-top: 4px;
+        }
+
+        img {
+          width: 72px;
+          height: 72px;
+          margin-right: 10px;
+        }
+
+        &:last-child {
+          border-bottom: none;
+        }
+      }
+    }
+
+    .home2-bos {
+      width: 474px;
+      margin-left: 10px;
+      height: 340px;
+      background: #ffffff;
+      padding: 18px 20px 0 20px;
+      display: flex;
+      justify-content: space-between;
+
+      .floorName {
+        font-weight: 600;
+        font-size: 16px;
+        color: #101828;
+      }
+
+      .home2-box {
+        width: 249px;
+
+        .home2-list {
+          width: 249px;
+          height: 130px;
+          border: 1px solid #e5e7eb;
+          margin-top: 13px;
+          display: flex;
+          align-items: center;
+          padding: 0 10px;
+          cursor: pointer;
+          .advertiseName {
+            font-weight: 600;
+            font-size: 14px;
+            color: #101828;
+          }
+          .advertiseDescribe {
+            font-size: 12px;
+            color: #364153;
+            margin: 4px 0 10px 0;
+          }
+          .bnt {
+            width: 68px;
+            height: 24px;
+          }
+          img {
+            width: 72px;
+            height: 72px;
+            margin-left: 10px;
+          }
+        }
+      }
+      .home2-two {
+        width: 177px;
+        height: 273px;
+        border-radius: 0px 0px 0px 0px;
+        border: 1px solid #e5e7eb;
+        margin-top: 34px;
+        padding: 26px 10px;
+        cursor: pointer;
+
+        .advertiseName {
+          font-weight: 600;
+          font-size: 14px;
+          color: #101828;
+        }
+        .advertiseDescribe {
+          font-size: 12px;
+          color: #364153;
+          margin: 4px 0 30px 0;
+          display: -webkit-box;
+          -webkit-line-clamp: 2;
+          line-clamp: 2; /* 添加标准属性 */
+          -webkit-box-orient: vertical;
+          overflow: hidden;
+          text-overflow: ellipsis;
+        }
+
+        img {
+          width: 123px;
+          height: 122px;
+          margin: 0 17px;
+        }
+      }
+    }
+  }
+  .shop-bos {
+    display: flex;
+    margin-top: 14px;
+    .shop-nav {
+      width: 230px;
+      height: 306px;
+      background: #ffffff;
+      padding: 16px;
+      .nav-title {
+        font-weight: 600;
+        font-size: 16px;
+        color: #101828;
+        margin-bottom: 10px;
+      }
+      .nav-bos {
+        width: 100%;
+        display: flex;
+        flex-wrap: wrap;
+        justify-content: space-between;
+        .nav-list {
+          width: 94px;
+          height: 32px;
+          background: #f4f4f4;
+          border-radius: 4px 4px 4px 4px;
+          font-size: 14px;
+          color: #101828;
+          margin-bottom: 10px;
+          cursor: pointer;
+          &:hover {
+            color: var(--el-color-primary);
+          }
+          &.hig {
+            background: var(--el-color-primary);
+            color: #ffffff;
+          }
+        }
+      }
+    }
+    .shop-list {
+      width: 230px;
+      height: 306px;
+      background: #ffffff;
+      margin-left: 12.5px;
+      padding: 20px;
+      cursor: pointer;
+      img {
+        width: 100%;
+        height: 190px;
+      }
+      .itemName {
+        font-weight: 400;
+        font-size: 14px;
+        color: #101828;
+        margin: 27px 0 2px 0;
+      }
+      .price {
+        .memberPrice {
+          color: var(--el-color-primary);
+          font-size: 16px;
+          color: #e7000b;
+        }
+        .marketPrice {
+          font-size: 12px;
+          color: #99a1af;
+          line-height: 20px;
+          text-decoration-line: line-through;
+          text-transform: none;
+          margin-left: 6px;
+        }
+      }
+    }
+  }
+
+  //项目案例
+  .project-bos {
+    display: flex;
+    width: 1200px;
+    margin-top: 12px;
+    gap: 0 15px;
+    .project-list {
+      width: 390px;
+      height: 350px;
+      cursor: pointer;
+      border-radius: 10px;
+      overflow: hidden;
+      .project-box {
+        width: 390px;
+        height: 156px;
+        background: #ffffff;
+        border-radius: 10px;
+        margin-top: -20px;
+        z-index: 2;
+        position: absolute;
+        padding: 20px;
+      }
+      img {
+        width: 390px;
+        height: 180px;
+      }
+      .project1 {
+        font-weight: 600;
+        font-size: 16px;
+        color: #101828;
+        margin-bottom: 14px;
+      }
+      .project2 {
+        font-size: 14px;
+        color: #364153;
+        display: -webkit-box;
+        -webkit-line-clamp: 2;
+        line-clamp: 2; /* 添加标准属性 */
+        -webkit-box-orient: vertical;
+        overflow: hidden;
+        text-overflow: ellipsis;
+      }
+      .project-more {
+        text-align: right;
+        font-size: 14px;
+        color: var(--el-color-primary);
+        margin-top: 18px;
+      }
+    }
+  }
+}
+</style>

+ 129 - 106
src/views/item/index.vue

@@ -2,9 +2,9 @@
   <div class="shop-pages">
     <div class="shop-head flex-row-start">
       <div class="head-left">
-        <div class="left-carousel">
+        <div class="left-carousel" v-if="carousel && carousel.length > 0">
           <div v-for="(item, index) in carousel" :key="index" class="carousel-item" :class="carouselIndex == index ? 'hig' : ''">
-            <img :src="item.img" alt="" @click="onCarousel(1, index)" />
+            <img :src="item" alt="" @click="onCarousel(1, index)" />
           </div>
         </div>
         <div class="left-next flex-row-center" @click="onCarousel(2)">
@@ -13,49 +13,66 @@
           </el-icon>
         </div>
       </div>
-      <img :src="carousel[carouselIndex].img" alt="" class="carousel-img" />
+      <img v-if="carousel && carousel.length > 0" :src="carousel[carouselIndex]" alt="" class="carousel-img" />
       <div class="head-right flex-column-between">
         <div>
           <div class="right-title">{{ dataInfo.itemName || '' }}</div>
-          <div class="right-num">商品库存 999套</div>
+          <div class="right-num">商品库存 {{ dataInfo.stock || 0 }}套</div>
           <div class="right-price flex-row-between">
             <div class="flex-row-start">
               <div class="price1">
                 <span>¥</span>
-                <span style="font-size: 24px">2654.00</span>
+                <span style="font-size: 24px">{{ dataInfo.standardPrice || 0 }}</span>
               </div>
               <div class="price2">平台价</div>
               <div class="price3">
                 <span>¥</span>
-                <span style="font-size: 16px">2654.00</span>
+                <span style="font-size: 16px">{{ dataInfo.midRangePrice || 0 }}</span>
               </div>
             </div>
             <div class="right-collect flex-row-start" @click="editCollection">
-              <img src="@/assets/images/dark.svg" alt="" />
+              <el-icon v-if="collection" :size="16" color="#e7000b"><StarFilled /></el-icon>
+              <el-icon v-else class="icon-star" :size="16"><Star /></el-icon>
+              <!-- <img src="@/assets/images/dark.svg" alt="" /> -->
               <span>{{ collection ? '已收藏' : '收藏' }}</span>
             </div>
           </div>
           <div class="address flex-row-start">
-            <img class="address-img" src="@/assets/images/dark.svg" alt="" />
-            <div>配送至</div>
-            <div class="address-text ellipsis">湖北省武汉市洪山区湖北省武汉市洪山区</div>
-            <el-icon color="#000000" size="15">
+            <img class="address-img" src="@/assets/images/item1.png" alt="" />
+            <div style="margin-right: 10px">配送至</div>
+            <el-cascader v-model="regionCodes" :options="regionData as any" :placeholder="'请选择省/市/区'" style="width: 260px" />
+            <!-- <el-icon color="#000000" size="15">
               <ArrowDown />
-            </el-icon>
+            </el-icon> -->
           </div>
           <div class="specs-bos">
-            <div v-for="(item1, index1) in specsList" :key="index1" class="specs-list">
-              <div>{{ item1.title }}</div>
-              <div class="specs-box">
-                <div
-                  v-for="(item2, index2) in item1.list"
-                  :key="index2"
-                  class="specs-item"
-                  :class="item2.id == item1.id ? 'hig' : item2.disabled ? 'disabled' : ''"
-                >
-                  {{ item2.title }}
-                </div>
+            <div class="specs-list">
+              <div>商品编号</div>
+              <div class="specs-item hig">
+                {{ dataInfo.productNo }}
               </div>
+              <div class="specs-box"></div>
+            </div>
+            <div class="specs-list">
+              <div>单位</div>
+              <div class="specs-item hig">
+                {{ dataInfo.unitName }}
+              </div>
+              <div class="specs-box"></div>
+            </div>
+            <div class="specs-list">
+              <div>规格型号</div>
+              <div class="specs-item hig">
+                {{ dataInfo.specification }}
+              </div>
+              <div class="specs-box"></div>
+            </div>
+            <div class="specs-list">
+              <div>UPC(69)条码</div>
+              <div class="specs-item hig">
+                {{ dataInfo.upcBarcode }}
+              </div>
+              <div class="specs-box"></div>
             </div>
           </div>
           <div class="number-bos">
@@ -68,14 +85,51 @@
         </div>
         <div class="bnt-bos flex-row-start">
           <div @click="onCart">加入购物车</div>
-          <div>立即购买</div>
+          <!-- <div>立即购买</div> -->
         </div>
       </div>
     </div>
     <div class="nav-bos flex-row-start">
-      <div v-for="(item, index) in navList" :key="index" :class="index == 0 ? 'hig' : ''">{{ item.title }}</div>
+      <div @click="onNav(index)" v-for="(item, index) in navList" :key="index" :class="navIndex == index ? 'hig' : ''">{{ item.title }}</div>
+    </div>
+    <div class="pcDetail" v-if="navIndex == 0" v-html="dataInfo.pcDetail"></div>
+    <div class="service" v-if="navIndex == 1">
+      <div class="service1">原厂正品保证承诺:</div>
+      <div>(1)所有商品均为符合国家有关商品质量的技术标准、服务标准、环保标准的原厂正品。</div>
+      <div>(2)所有商品保证是全新的货物,且来源于中华人民共和国或与中华人民共和国有正常贸易往来的国家或地区。</div>
+      <div>(3)所有商品均为自营,不涉及任何第三方店铺,充分保证产品来源,保证质量。</div>
+      <div>(4)所有商品均为原厂正品,如有假货,假一罚十。</div>
+      <div>(5)所有产品均严格按照国家三包标准执行。</div>
+      <div>(6)保证所售商品开具机打发票或电子发票。</div>
+      <div class="service1">厂家服务:</div>
+      <div>
+        本商品质保周期均为厂商对外公布的质保期或优易365对客户承诺的质保期为准。在此时间范围内可提交维修申请,具体请以厂家服务为准。
+        如因质量问题或故障,凭厂商维修中心或特约维修点的质量检测证明,享受7日内退货,15日内换货,15日以上在质保期内享受免费保修等三包服务!
+      </div>
+      <div>全国统一售后及服务电话:400-111-0027</div>
+      <div>(注:如优易365在商品介绍中有售后保障的说明,则此商品按照说明执行售后保障服务。)</div>
+      <div class="service1">服务承诺:</div>
+      <div>平台销售并发货的商品,均由平台提供发票和相应的售后服务。请您放心购买!</div>
+      <div>优易365确保客户收到的货物与商城图片、产地、附件说明完全一致。均为原厂正货!并且保证与当时市场上同样主流新品一致。</div>
+      <div class="service1">无忧退货:</div>
+      <div>客户购买商品7日内(含7日,自客户收到商品之日起计算),在保证商品完好的前提下,可无理由退货。(部分商品除外,详情请见各商品细则)</div>
+      <div>• 购买运费如何收取?</div>
+      <div class="service2">
+        单笔订单金额(不含运费)满88元免邮费;不满88元,每单收取10元运费。(港澳台地区需满500元免邮费;不满500元,每单收取30元运费)
+      </div>
+      <div>• 使用什么快递发货?</div>
+      <div class="service2">默认使用顺丰快递发货(个别商品使用其他快递)</div>
+      <div class="service2">配送范围覆盖全国大部分地区(港澳台地区除外)。</div>
+      <div>• 如何申请退货?</div>
+      <div class="service2">1.自收到商品之日起30日内,顾客可申请无忧退货,退款将原路返还,不同的银行处理时间不同,预计1-5个工作日到账;</div>
+      <div class="service2">2.内裤和食品等特殊商品无质量问题不支持退货;</div>
+      <div>3.退货流程:</div>
+      <div class="service2">确认收货-申请退货-客服审核通过-用户寄回商品-仓库签收验货-退款审核-退款完成;</div>
+      <div>
+        4.因优品汇产生的退货,如质量问题,退货邮费由优品汇承担,退款完成后会以现金券的形式报销。因客户个人原因产生的退货,购买和寄回运费由客户个人承担。
+      </div>
     </div>
-    <img class="shop-img" src="@/assets/images/login-background.jpg" alt="" />
+    <!-- <img class="shop-img" src="@/assets/images/login-background.jpg" alt="" /> -->
     <div class="shop-more flex-row-between">
       <div class="flex-row-start">
         <div class="more1">更多推荐</div>
@@ -125,13 +179,8 @@
 </template>
 
 <script setup lang="ts">
-import back1 from '@/assets/images/login-background.jpg';
-import back2 from '@/assets/images/login-background.jpg';
-import back3 from '@/assets/images/login-background.jpg';
-import back4 from '@/assets/images/login-background.jpg';
-import back5 from '@/assets/images/login-background.jpg';
 import { getToken } from '@/utils/auth';
-
+import { regionData } from 'element-china-area-data';
 import {
   getProductDetail,
   addProductShoppingCart,
@@ -141,16 +190,18 @@ import {
   favoritesList,
   cancelProductCollect
 } from '@/api/goods/index';
-import { edit } from '@/api/workflow/definition';
 
 const route = useRoute();
 const id = ref<any>(null);
 const dataInfo = ref<any>({});
-
+const carousel = ref<any>([]);
+const regionCodes = ref<any>([]);
 const radio = ref<any>(null);
 const favorites = ref<any>([]);
 const collection = ref<any>(null);
 const dialogVisible = ref<any>(false);
+const navList = ref<any>([{ title: '商品详情' }, { title: '售后服务说明' }, { title: '品牌信息' }, { title: '商品评价' }]);
+const navIndex = ref<any>(0);
 onMounted(() => {
   id.value = route.query.id;
   getInfo();
@@ -162,10 +213,14 @@ onMounted(() => {
   }
 });
 
-// 商品相信
+// 商品详情
 const getInfo = () => {
   getProductDetail(id.value).then((res) => {
     if (res.code == 200) {
+      carousel.value = [];
+      if (res.data.productImage) {
+        carousel.value = res.data.productImage.split(',');
+      }
       dataInfo.value = res.data;
     }
   });
@@ -196,7 +251,6 @@ const editCollection = () => {
     // 添加
     addProductCollect({ productId: id.value }).then((res) => {
       if (res.code == 200) {
-        dataInfo.value = res.data;
         getCollection();
       }
     });
@@ -213,50 +267,13 @@ const onCancel = () => {
   });
 };
 
+// 切换
+const onNav = (index: any) => {
+  navIndex.value = index;
+};
+
 const num = ref<any>(1);
-const carousel = ref<any>([
-  {
-    img: back1,
-    id: 1
-  },
-  {
-    img: back2,
-    id: 2
-  },
-  {
-    img: back3,
-    id: 3
-  },
-  {
-    img: back4,
-    id: 4
-  },
-  {
-    img: back5,
-    id: 5
-  }
-]);
-const navList = ref<any>([{ title: '商品详情' }, { title: '参数信息' }, { title: '售后服务说明' }, { title: '品牌信息' }, { title: '商品评价' }]);
-const specsList = ref<any>([
-  {
-    title: '规格参数01',
-    id: 1,
-    list: [
-      { title: '极光蓝', id: 1, disabled: false },
-      { title: '极光蓝', id: 2, disabled: false },
-      { title: '极光蓝', id: 3, disabled: false }
-    ]
-  },
-  {
-    title: '规格参数02',
-    id: 1,
-    list: [
-      { title: '极光蓝', id: 1, disabled: false },
-      { title: '极光蓝', id: 2, disabled: false },
-      { title: '极光蓝', id: 3, disabled: true }
-    ]
-  }
-]);
+
 const carouselIndex = ref<any>(0);
 
 const onCarousel = (type: number, index?: any) => {
@@ -391,6 +408,9 @@ const onCart = () => {
           font-size: 14px;
           color: #6a7282;
           cursor: pointer;
+          .icon-star {
+            margin-right: 4px;
+          }
 
           img {
             width: 12px;
@@ -424,36 +444,14 @@ const onCart = () => {
 
       .specs-bos {
         .specs-list {
-          margin-top: 20px;
+          margin-top: 15px;
           font-size: 14px;
           color: #364153;
-        }
-
-        .specs-box {
           display: flex;
-          gap: 8px 10px;
-          padding-top: 8px;
-
+          align-items: center;
           .specs-item {
-            padding: 0 14px;
-            height: 32px;
-            border-radius: 4px 4px 4px 4px;
-            border: 1px solid #e8e8ea;
-            line-height: 32px;
-            cursor: pointer;
-
-            &.hig {
-              border: 1px solid #e7000b;
-              color: #e7000b;
-            }
-
-            &.disabled {
-              opacity: 0.5;
-
-              &:hover {
-                cursor: not-allowed;
-              }
-            }
+            color: #6a7282;
+            margin-left: 10px;
           }
         }
       }
@@ -477,7 +475,8 @@ const onCart = () => {
         overflow: hidden;
 
         div {
-          width: 214px;
+          width: 428px;
+          // width: 214px;
           height: 44px;
           line-height: 44px;
           text-align: center;
@@ -514,6 +513,30 @@ const onCart = () => {
 
     .hig {
       color: #101828;
+      font-weight: 600;
+    }
+  }
+
+  .pcDetail {
+    width: 696px;
+    margin-top: 20px;
+  }
+
+  .service {
+    width: 696px;
+    margin-top: 20px;
+    background: #ffffff;
+    padding: 20px;
+    border-radius: 10px;
+    div {
+      margin-bottom: 20px;
+      font-size: 14px;
+    }
+    .service1 {
+      font-weight: 600;
+    }
+    .service2 {
+      color: #999999;
     }
   }
 

+ 34 - 5
src/views/payc/index.vue

@@ -7,26 +7,29 @@
       </div>
       <div class="pay-bos flex-column-between">
         <div class="pay-box flex-column-center">
-          <img src="@/assets/images/dark.svg" alt="" />
+          <img src="@/assets/images/pay/pay1.png" alt="" />
           <div class="pay-text1">订单提交成功!请尽快完成支付。</div>
           <div class="pay-text2">请在2小时0分内完成支付,超时后将取消订单</div>
         </div>
         <div class="pay-bnt flex-row-center">
           <span class="bnt1">应付总额:</span>
-          <span class="bnt2">¥0.00</span>
+          <span class="bnt2">¥{{ totalAmount }}</span>
         </div>
       </div>
       <div class="pay-head1">选择支付方式</div>
       <div class="pay-for">
         <div v-for="(item, index) in payList" :key="index" class="pay-list flex-row-center" :class="index == 0 ? 'hig' : ''">
-          <img src="@/assets/images/dark.svg" alt="" />
+          <img v-if="index == 0" src="@/assets/images/pay/pay2.png" alt="" />
+          <img v-if="index == 1" src="@/assets/images/pay/pay3.png" alt="" />
+          <img v-if="index == 2" src="@/assets/images/pay/pay4.png" alt="" />
+          <img v-if="index == 3" src="@/assets/images/pay/pay5.png" alt="" />
           <div>{{ item.title }}</div>
         </div>
       </div>
       <div class="pay-head2">选择“暂存订单”,订单将在我的订单中査看,您可以在我的订单中进行完成支付。</div>
       <div class="pay-for">
         <div class="pay-list flex-row-center">
-          <img src="@/assets/images/dark.svg" alt="" />
+          <img src="@/assets/images/pay/pay6.png" alt="" />
           <div>暂存订单</div>
         </div>
       </div>
@@ -34,14 +37,40 @@
     <div class="pay-foot">
       <div class="foot-bos">
         <el-button class="bnt1">返回购物车修改</el-button>
-        <el-button class="bnt2" type="primary">提交订单</el-button>
+        <el-button class="bnt2" type="primary" @click="onSubmit">提交订单</el-button>
       </div>
     </div>
   </div>
 </template>
 
 <script setup lang="ts">
+import { getOrderInfo, orderPay } from '@/api/pc/enterprise/order';
 const payList = ref<any>([{ title: '信用支付' }, { title: '支付宝支付' }, { title: '微信支付' }, { title: '货到付款' }]);
+const route = useRoute();
+const orderId = ref<any>(null);
+const totalAmount = ref<any>(0);
+onMounted(() => {
+  orderId.value = route.query.id;
+  getInfo();
+});
+
+const getInfo = () => {
+  getOrderInfo(orderId.value).then((res) => {
+    if (res.code == 200) {
+      totalAmount.value = res.data.totalAmount;
+    }
+    console.log(res);
+  });
+};
+
+const onSubmit = () => {
+  orderPay({
+    orderId: orderId.value,
+    payType: 0
+  }).then((res) => {
+    console.log(res);
+  });
+};
 </script>
 
 <style lang="scss" scoped>

+ 361 - 0
src/views/plan/guide.vue

@@ -0,0 +1,361 @@
+<template>
+  <div class="solve">
+    <div class="solve-head">
+      <div class="head-bos">
+        <div class="nav-bos flex-row-start">
+          <div
+            @click="onNav(item)"
+            v-for="(item, index) in navList"
+            :key="index"
+            class="nav-list"
+            :class="item.id == httpObj.tweetCategory ? 'hig' : ''"
+          >
+            {{ item.categoryName }}
+          </div>
+        </div>
+        <div class="filter-bos">
+          <div v-for="(item1, index1) in filterListy" :key="index1" class="filter-list flex-row-start">
+            <div class="filter-title">{{ item1.title }}</div>
+            <div
+              @click="onFilter(item1, item2)"
+              v-for="(item2, index2) in item1.list"
+              :key="index2"
+              class="filter-item"
+              :class="item1.id == item2.id ? 'hig' : ''"
+            >
+              {{ item2.title }}
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <!-- 数据 -->
+    <div class="procure-bos">
+      <div v-for="(item, index) in dataList" :key="index" class="procure-list" @click="onPath('/plan_info/guide?id=' + item.id)">
+        <img :src="item.coverImage" alt="" />
+        <div class="procure1">{{ item.title }}</div>
+        <div class="procure2">{{ item.releaseTime }}</div>
+      </div>
+    </div>
+    <!-- 游标分页控制 -->
+    <div class="pagination-bos flex-row-between">
+      <div></div>
+      <pagination
+        v-show="dataList.length > 0"
+        v-model:page="httpObj.pageNum"
+        v-model:limit="httpObj.pageSize"
+        v-model:way="way"
+        :cursor-mode="true"
+        :has-more="hasMore"
+        @pagination="getList"
+      />
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { onPath } from '@/utils/siteConfig';
+import {
+  getPurchaseGuideList,
+  getPurchaseCategoryList,
+  getAdaptSceneList,
+  getCustomerIndustry,
+  getPriceRangeList,
+  getCustomerTag
+} from '@/api/plan/index';
+import Pagination from '@/components/Pagination/index.vue';
+const httpObj = ref<any>({
+  tweetCategory: '',
+  adaptNo: '',
+  adaptIndustry: '',
+  price: '',
+  lable: '',
+  pageSize: 10,
+  pageNum: 1
+});
+const dataList = ref<any>([]);
+const hasMore = ref(true); // 是否还有更多数据
+const way = ref<any>(1);
+
+const navList = ref<any>([
+  { title: '专题分类' },
+  { title: '大中型企业采购' },
+  { title: '政府&公共采购' },
+  { title: '营销福利' },
+  { title: '商用工程' },
+  { title: '中小型企业采购' }
+]);
+const filterListy = ref<any>([
+  {
+    title: '适配场景',
+    key: 'adaptNo',
+    id: '',
+    list: [
+      {
+        id: '',
+        title: '全部'
+      }
+    ]
+  },
+  {
+    title: '适配行业',
+    key: 'adaptIndustry',
+    id: '',
+    list: [
+      {
+        id: '',
+        title: '全部'
+      }
+    ]
+  },
+  {
+    title: '价格区间',
+    key: 'price',
+    id: '',
+    list: [
+      {
+        id: '',
+        title: '全部'
+      }
+    ]
+  },
+  {
+    title: '推荐标签',
+    key: 'lable',
+    id: '',
+    list: [
+      {
+        id: '',
+        title: '全部'
+      }
+    ]
+  }
+]);
+const navIndex = ref(0);
+const router = useRouter();
+
+onMounted(() => {
+  // 采购分类列表
+  getPurchaseCategoryList({}).then((res) => {
+    if (res.code == 200) {
+      res.data.unshift({
+        id: '',
+        categoryName: '全部'
+      });
+      navList.value = res.data;
+      httpObj.value.tweetCategory = '';
+    }
+  });
+
+  // 适配场景列表
+  getAdaptSceneList({}).then((res) => {
+    if (res.code == 200) {
+      res.data.forEach((item: any) => {
+        item.title = item.sceneName;
+        filterListy.value[0].list.push(item);
+      });
+    }
+  });
+
+  //适配行业
+  getCustomerIndustry({}).then((res) => {
+    if (res.code == 200) {
+      res.data.forEach((item: any) => {
+        item.title = item.industryCategoryName;
+        filterListy.value[1].list.push(item);
+      });
+    }
+  });
+
+  // 获取价格区间列表
+  getPriceRangeList({}).then((res) => {
+    if (res.code == 200) {
+      res.data.forEach((item: any) => {
+        item.title = item.minPrice + '-' + item.maxPrice;
+        item.id = item.minPrice + '-' + item.maxPrice;
+        filterListy.value[2].list.push(item);
+      });
+    }
+  });
+
+  // 推荐标签
+  getCustomerTag({}).then((res) => {
+    if (res.code == 200) {
+      res.data.forEach((item: any) => {
+        item.title = item.tagName;
+        filterListy.value[3].list.push(item);
+      });
+    }
+  });
+  getList();
+});
+const getList = () => {
+  getPurchaseGuideList(httpObj.value).then((res) => {
+    if (res.code == 200) {
+      dataList.value = res.rows;
+      // 判断是否还有更多数据
+      hasMore.value = dataList.value.length === httpObj.value.pageSize;
+    }
+  });
+};
+
+const onNav = (item: any) => {
+  httpObj.value.tweetCategory = item.id;
+  getList();
+};
+
+const onFilter = (item1: any, item2: any) => {
+  item1.id = item2.id;
+  httpObj.value[item1.key] = item2.id;
+  getList();
+};
+const handleSizeChange = (val: number) => {
+  console.log(`${val} items per page`);
+};
+const handleCurrentChange = (val: number) => {
+  console.log(`current page: ${val}`);
+};
+</script>
+
+<style lang="scss" scoped>
+.solve {
+  width: 100%;
+
+  .solve-head {
+    width: 100%;
+    background: #ffffff;
+
+    .head-bos {
+      width: 1200px;
+      margin: 0 auto;
+      padding-bottom: 20px;
+    }
+  }
+
+  .nav-bos {
+    border-bottom: 1px solid #e5e7eb;
+    width: 1200px;
+    padding-bottom: 20px;
+
+    .nav-list {
+      height: 32px;
+      padding: 0 12px;
+      background: #f7f8fa;
+      border-radius: 2px 2px 2px 2px;
+      font-size: 14px;
+      color: #4e5969;
+      margin-right: 8px;
+      line-height: 32px;
+      cursor: pointer;
+
+      &.hig {
+        background: #ffe8e8;
+        color: #e7000b;
+      }
+
+      &:hover {
+        color: #e7000b;
+      }
+    }
+  }
+
+  .filter-bos {
+    .filter-list {
+      margin-top: 20px;
+
+      .filter-title {
+        font-size: 14px;
+        color: #101828;
+        margin-right: 40px;
+      }
+
+      .filter-item {
+        font-size: 14px;
+        color: #364153;
+        margin-right: 30px;
+        cursor: pointer;
+
+        &.hig {
+          color: #e7000b;
+        }
+      }
+    }
+  }
+
+  // 采购指南
+  .procure-bos {
+    display: flex;
+    width: 1200px;
+    margin-top: 12px;
+    gap: 15px;
+    flex-wrap: wrap;
+    margin: 0 auto;
+    padding: 22px 0 40px 0;
+    .procure-list {
+      width: 390px;
+      height: 268px;
+      background: #ffffff;
+      cursor: pointer;
+      border-radius: 10px;
+      overflow: hidden;
+      img {
+        width: 390px;
+        height: 200px;
+      }
+      .procure1 {
+        padding: 12px 0 4px 20px;
+        font-weight: 600;
+        font-size: 14px;
+        color: #101828;
+      }
+      .procure2 {
+        padding-left: 20px;
+        font-size: 12px;
+        color: #364153;
+      }
+    }
+  }
+
+  //分页
+  .pagination-bos {
+    width: 1200px;
+    margin: 0 auto;
+    padding-bottom: 60px;
+    :deep(.el-select__wrapper) {
+      background: #f4f4f4;
+      box-shadow: 0 0 0 1px #e5e6eb inset;
+      border-radius: 2px;
+    }
+    :deep(.el-select__placeholder) {
+      color: #1d2129;
+    }
+    :deep(.el-input__wrapper) {
+      background: #f4f4f4;
+      box-shadow: 0 0 0 1px #e5e6eb inset;
+      border-radius: 2px;
+    }
+    :deep(.el-input__inner) {
+      color: #1d2129;
+    }
+
+    :deep(.btn-prev) {
+      background: #f4f4f4;
+      border: 1px solid #e5e6eb;
+      margin-right: 8px;
+    }
+    :deep(.btn-next) {
+      background: #f4f4f4;
+      border: 1px solid #e5e6eb;
+      margin-left: 8px;
+    }
+    :deep(.el-pager) {
+      gap: 0 8px;
+      li {
+        background: #f4f4f4;
+        border: 1px solid #e5e6eb;
+        color: #1d2129;
+      }
+    }
+  }
+}
+</style>

+ 376 - 0
src/views/plan/procure.vue

@@ -0,0 +1,376 @@
+<template>
+  <div class="solve">
+    <div class="solve-head">
+      <div class="head-bos">
+        <div class="nav-bos flex-row-start">
+          <div
+            @click="onNav(item)"
+            v-for="(item, index) in navList"
+            :key="index"
+            class="nav-list"
+            :class="item.id == httpObj.tweetsCategory ? 'hig' : ''"
+          >
+            {{ item.categoryName }}
+          </div>
+        </div>
+        <div class="filter-bos">
+          <div v-for="(item1, index1) in filterListy" :key="index1" class="filter-list flex-row-start">
+            <div class="filter-title">{{ item1.title }}</div>
+            <div
+              @click="onFilter(item1, item2)"
+              v-for="(item2, index2) in item1.list"
+              :key="index2"
+              class="filter-item"
+              :class="item1.id == item2.id ? 'hig' : ''"
+            >
+              {{ item2.title }}
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <!-- 数据 -->
+    <div class="data-bos">
+      <div v-for="(item, index) in dataList" :key="index" class="data-list" @click="onPath('/plan_info/procure?id=' + item.id)">
+        <img class="data-img" :src="item.coverImage" alt="" />
+        <div class="data-box flex-column-between">
+          <div>
+            <div class="title ellipsis">{{ item.tweetsTitle }}</div>
+            <div class="info ellipsis">{{ item.programDescribe }}</div>
+          </div>
+          <div class="text flex-row-start">
+            <div>了解详情</div>
+            <el-icon color="#e7000b" size="14" style="margin: 0 0 0 10px">
+              <ArrowRight />
+            </el-icon>
+          </div>
+        </div>
+      </div>
+    </div>
+    <!-- 游标分页控制 -->
+    <div class="pagination-bos flex-row-between">
+      <div></div>
+      <pagination
+        v-show="dataList.length > 0"
+        v-model:page="httpObj.pageNum"
+        v-model:limit="httpObj.pageSize"
+        v-model:way="way"
+        :cursor-mode="true"
+        :has-more="hasMore"
+        @pagination="getList"
+      />
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { onPath } from '@/utils/siteConfig';
+import {
+  getProcurementProgramList,
+  getPurchaseCategoryList,
+  getAdaptSceneList,
+  getCustomerIndustry,
+  getPriceRangeList,
+  getCustomerTag
+} from '@/api/plan/index';
+import Pagination from '@/components/Pagination/index.vue';
+const httpObj = ref<any>({
+  tweetsCategory: '',
+  adaptNo: '',
+  adaptIndustry: '',
+  price: '',
+  lable: '',
+  pageSize: 10,
+  pageNum: 1
+});
+const dataList = ref<any>([]);
+const hasMore = ref(true); // 是否还有更多数据
+const way = ref<any>(1);
+const navList = ref<any>([]);
+
+const filterListy = ref<any>([
+  {
+    title: '适配场景',
+    key: 'adaptNo',
+    id: '',
+    list: [
+      {
+        id: '',
+        title: '全部'
+      }
+    ]
+  },
+  {
+    title: '适配行业',
+    key: 'adaptIndustry',
+    id: '',
+    list: [
+      {
+        id: '',
+        title: '全部'
+      }
+    ]
+  },
+  {
+    title: '价格区间',
+    key: 'price',
+    id: '',
+    list: [
+      {
+        id: '',
+        title: '全部'
+      }
+    ]
+  },
+  {
+    title: '推荐标签',
+    key: 'lable',
+    id: '',
+    list: [
+      {
+        id: '',
+        title: '全部'
+      }
+    ]
+  }
+]);
+
+onMounted(() => {
+  // 采购分类列表
+  getPurchaseCategoryList({}).then((res) => {
+    if (res.code == 200) {
+      res.data.unshift({
+        id: '',
+        categoryName: '全部'
+      });
+      navList.value = res.data;
+      httpObj.value.tweetsCategory = '';
+    }
+  });
+
+  // 适配场景列表
+  getAdaptSceneList({}).then((res) => {
+    if (res.code == 200) {
+      res.data.forEach((item: any) => {
+        item.title = item.sceneName;
+        filterListy.value[0].list.push(item);
+      });
+    }
+  });
+
+  //适配行业
+  getCustomerIndustry({}).then((res) => {
+    if (res.code == 200) {
+      res.data.forEach((item: any) => {
+        item.title = item.industryCategoryName;
+        filterListy.value[1].list.push(item);
+      });
+    }
+  });
+
+  // 获取价格区间列表
+  getPriceRangeList({}).then((res) => {
+    if (res.code == 200) {
+      res.data.forEach((item: any) => {
+        item.title = item.minPrice + '-' + item.maxPrice;
+        item.id = item.minPrice + '-' + item.maxPrice;
+        filterListy.value[2].list.push(item);
+      });
+    }
+  });
+
+  // 推荐标签
+  getCustomerTag({}).then((res) => {
+    if (res.code == 200) {
+      res.data.forEach((item: any) => {
+        item.title = item.tagName;
+        filterListy.value[3].list.push(item);
+      });
+    }
+  });
+
+  getList();
+});
+const getList = () => {
+  getProcurementProgramList(httpObj.value).then((res) => {
+    if (res.code == 200) {
+      dataList.value = res.rows;
+      // 判断是否还有更多数据
+      hasMore.value = dataList.value.length === httpObj.value.pageSize;
+    }
+  });
+};
+
+const onNav = (item: any) => {
+  httpObj.value.tweetsCategory = item.id;
+  getList();
+};
+
+const onFilter = (item1: any, item2: any) => {
+  item1.id = item2.id;
+  httpObj.value[item1.key] = item2.id;
+  getList();
+};
+const handleSizeChange = (val: number) => {
+  console.log(`${val} items per page`);
+};
+const handleCurrentChange = (val: number) => {
+  console.log(`current page: ${val}`);
+};
+</script>
+
+<style lang="scss" scoped>
+.solve {
+  width: 100%;
+
+  .solve-head {
+    width: 100%;
+    background: #ffffff;
+
+    .head-bos {
+      width: 1200px;
+      margin: 0 auto;
+      padding-bottom: 20px;
+    }
+  }
+
+  .nav-bos {
+    border-bottom: 1px solid #e5e7eb;
+    width: 1200px;
+    padding-bottom: 20px;
+
+    .nav-list {
+      height: 32px;
+      padding: 0 12px;
+      background: #f7f8fa;
+      border-radius: 2px 2px 2px 2px;
+      font-size: 14px;
+      color: #4e5969;
+      margin-right: 8px;
+      line-height: 32px;
+      cursor: pointer;
+
+      &.hig {
+        background: #ffe8e8;
+        color: #e7000b;
+      }
+
+      &:hover {
+        color: #e7000b;
+      }
+    }
+  }
+
+  .filter-bos {
+    .filter-list {
+      margin-top: 20px;
+
+      .filter-title {
+        font-size: 14px;
+        color: #101828;
+        margin-right: 40px;
+      }
+
+      .filter-item {
+        font-size: 14px;
+        color: #364153;
+        margin-right: 30px;
+        cursor: pointer;
+
+        &.hig {
+          color: #e7000b;
+        }
+      }
+    }
+  }
+
+  // 数据
+  .data-bos {
+    width: 1200px;
+    margin: 0 auto;
+    display: flex;
+    gap: 20px;
+    flex-wrap: wrap;
+    padding: 22px 0 40px 0;
+
+    .data-list {
+      width: 386px;
+      height: 302px;
+      background: #ffffff;
+      border-radius: 10px;
+      overflow: hidden;
+      cursor: pointer;
+
+      .data-img {
+        height: 200px;
+        width: 386px;
+      }
+
+      .data-box {
+        height: 102px;
+        width: 386px;
+        padding: 12px 20px;
+
+        .title {
+          font-weight: 600;
+          font-size: 14px;
+          color: #101828;
+        }
+
+        .info {
+          font-size: 12px;
+          color: #364153;
+          margin-top: 4px;
+        }
+
+        .text {
+          font-size: 14px;
+          color: #e7000b;
+        }
+      }
+    }
+  }
+
+  //分页
+  .pagination-bos {
+    width: 1200px;
+    margin: 0 auto;
+    padding-bottom: 60px;
+    :deep(.el-select__wrapper) {
+      background: #f4f4f4;
+      box-shadow: 0 0 0 1px #e5e6eb inset;
+      border-radius: 2px;
+    }
+    :deep(.el-select__placeholder) {
+      color: #1d2129;
+    }
+    :deep(.el-input__wrapper) {
+      background: #f4f4f4;
+      box-shadow: 0 0 0 1px #e5e6eb inset;
+      border-radius: 2px;
+    }
+    :deep(.el-input__inner) {
+      color: #1d2129;
+    }
+
+    :deep(.btn-prev) {
+      background: #f4f4f4;
+      border: 1px solid #e5e6eb;
+      margin-right: 8px;
+    }
+    :deep(.btn-next) {
+      background: #f4f4f4;
+      border: 1px solid #e5e6eb;
+      margin-left: 8px;
+    }
+    :deep(.el-pager) {
+      gap: 0 8px;
+      li {
+        background: #f4f4f4;
+        border: 1px solid #e5e6eb;
+        color: #1d2129;
+      }
+    }
+  }
+}
+</style>

+ 371 - 0
src/views/plan/project.vue

@@ -0,0 +1,371 @@
+<template>
+  <div class="project">
+    <div class="project-pages">
+      <img class="solve-img" src="@/assets/images/login-background.jpg" alt="" />
+      <div class="filter-bos">
+        <div v-for="(item1, index1) in filterListy" :key="index1" class="filter-list flex-row-start">
+          <div class="filter-title">{{ item1.title }}</div>
+          <div
+            @click="onFilter(item1, item2)"
+            v-for="(item2, index2) in item1.list"
+            :key="index2"
+            class="filter-item"
+            :class="item1.id == item2.id ? 'hig' : ''"
+          >
+            {{ item2.title }}
+          </div>
+        </div>
+      </div>
+      <!-- 数据 -->
+      <div class="project-bos">
+        <div v-for="(item, index) in dataList" :key="index" class="project-list" @click="onPath('/plan_info/project?id=' + item.id)">
+          <img :src="item.uploadProgram" alt="" />
+          <div class="project-box">
+            <div class="project1">{{ item.caseTitle || '' }}</div>
+            <div class="project2">
+              {{ item.projectBrief || '' }}
+            </div>
+            <div class="project-more flex-row-between">
+              <div></div>
+              <div class="flex-row-start">
+                <div style="margin-right: 5px">了解详情</div>
+                <el-icon :size="14" color="#E7000B"><ArrowRight /></el-icon>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 游标分页控制 -->
+    <div class="pagination-bos flex-row-between">
+      <div></div>
+      <pagination
+        v-show="dataList.length > 0"
+        v-model:page="httpObj.pageNum"
+        v-model:limit="httpObj.pageSize"
+        v-model:way="way"
+        :cursor-mode="true"
+        :has-more="hasMore"
+        @pagination="getList"
+      />
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { onPath } from '@/utils/siteConfig';
+import { getProjectCaseAllList, getCustomerIndustry, getProjectTypeList } from '@/api/plan/index';
+import Pagination from '@/components/Pagination/index.vue';
+const httpObj = ref<any>({
+  topCategoryId: '',
+  brandId: '',
+  priceRange: '',
+  sortField: '',
+  sortOrder: '',
+  isCustomize: '',
+  pageSize: 10,
+  pageNum: 1
+});
+const dataList = ref<any>([]);
+const hasMore = ref(true); // 是否还有更多数据
+const way = ref<any>(1);
+
+const navList = ref<any>([
+  { title: '专题分类' },
+  { title: '大中型企业采购' },
+  { title: '政府&公共采购' },
+  { title: '营销福利' },
+  { title: '商用工程' },
+  { title: '中小型企业采购' }
+]);
+const filterListy = ref<any>([
+  {
+    title: '客户行业',
+    key: 'clientIndustry',
+    id: '',
+    list: [
+      {
+        id: '',
+        title: '全部'
+      }
+    ]
+  },
+  {
+    title: '项目类型',
+    key: 'projectType',
+    id: '',
+    list: [
+      {
+        id: '',
+        title: '全部'
+      }
+    ]
+  }
+]);
+
+onMounted(() => {
+  //适配行业
+  getCustomerIndustry({}).then((res) => {
+    if (res.code == 200) {
+      res.data.forEach((item: any) => {
+        item.title = item.industryCategoryName;
+        filterListy.value[0].list.push(item);
+      });
+    }
+  });
+
+  //项目类型
+  getProjectTypeList({}).then((res) => {
+    if (res.code == 200) {
+      res.data.forEach((item: any) => {
+        item.title = item.typeName;
+        filterListy.value[1].list.push(item);
+      });
+    }
+  });
+  getList();
+});
+const getList = () => {
+  getProjectCaseAllList(httpObj.value).then((res) => {
+    if (res.code == 200) {
+      dataList.value = res.rows;
+      // 判断是否还有更多数据
+      hasMore.value = dataList.value.length === httpObj.value.pageSize;
+    }
+  });
+};
+
+const onFilter = (item1: any, item2: any) => {
+  item1.id = item2.id;
+  httpObj.value[item1.key] = item2.id;
+  getList();
+};
+const handleSizeChange = (val: number) => {
+  console.log(`${val} items per page`);
+};
+const handleCurrentChange = (val: number) => {
+  console.log(`current page: ${val}`);
+};
+</script>
+
+<style lang="scss" scoped>
+.project {
+  width: 100%;
+  background-color: #ffffff;
+  .project-pages {
+    width: 1200px;
+    margin: 0 auto;
+    .solve-img {
+      width: 1200px;
+      height: 380px;
+      border-radius: 10px;
+    }
+    .filter-bos {
+      .filter-list {
+        margin-top: 20px;
+
+        .filter-title {
+          font-size: 14px;
+          color: #101828;
+          margin-right: 40px;
+        }
+
+        .filter-item {
+          font-size: 14px;
+          color: #364153;
+          margin-right: 30px;
+          cursor: pointer;
+
+          &.hig {
+            color: #e7000b;
+          }
+        }
+      }
+    }
+    //项目案例
+    .project-bos {
+      display: flex;
+      width: 1200px;
+      margin-top: 25px;
+      gap: 15px;
+      flex-wrap: wrap;
+      .project-list {
+        width: 390px;
+        height: 350px;
+        cursor: pointer;
+        border-radius: 10px;
+        overflow: hidden;
+
+        .project-box {
+          width: 390px;
+          height: 156px;
+          background: #ffffff;
+          border-radius: 10px;
+          margin-top: -20px;
+          z-index: 2;
+          position: absolute;
+          padding: 20px;
+          border: 1px solid #e5e7eb;
+        }
+        img {
+          width: 390px;
+          height: 180px;
+        }
+        .project1 {
+          font-weight: 600;
+          font-size: 16px;
+          color: #101828;
+          margin-bottom: 14px;
+        }
+        .project2 {
+          font-size: 14px;
+          color: #364153;
+          display: -webkit-box;
+          -webkit-line-clamp: 2;
+          line-clamp: 2; /* 添加标准属性 */
+          -webkit-box-orient: vertical;
+          overflow: hidden;
+          text-overflow: ellipsis;
+        }
+        .project-more {
+          text-align: right;
+          font-size: 14px;
+          color: var(--el-color-primary);
+          margin-top: 18px;
+        }
+      }
+    }
+  }
+}
+.solve {
+  width: 100%;
+
+  .solve-head {
+    width: 100%;
+    background: #ffffff;
+
+    .head-bos {
+      width: 1200px;
+      margin: 0 auto;
+      padding-bottom: 20px;
+    }
+  }
+
+  .nav-bos {
+    border-bottom: 1px solid #e5e7eb;
+    width: 1200px;
+    padding-bottom: 20px;
+
+    .nav-list {
+      height: 32px;
+      padding: 0 12px;
+      background: #f7f8fa;
+      border-radius: 2px 2px 2px 2px;
+      font-size: 14px;
+      color: #4e5969;
+      margin-right: 8px;
+      line-height: 32px;
+      cursor: pointer;
+
+      &.hig {
+        background: #ffe8e8;
+        color: #e7000b;
+      }
+
+      &:hover {
+        color: #e7000b;
+      }
+    }
+  }
+
+  // 数据
+  .data-bos {
+    width: 1200px;
+    margin: 0 auto;
+    display: flex;
+    gap: 20px;
+    flex-wrap: wrap;
+    padding: 22px 0 40px 0;
+
+    .data-list {
+      width: 386px;
+      height: 302px;
+      background: #ffffff;
+      border-radius: 10px;
+      overflow: hidden;
+      cursor: pointer;
+
+      .data-img {
+        height: 200px;
+        width: 386px;
+      }
+
+      .data-box {
+        height: 102px;
+        width: 386px;
+        padding: 12px 20px;
+
+        .title {
+          font-weight: 600;
+          font-size: 14px;
+          color: #101828;
+        }
+
+        .info {
+          font-size: 12px;
+          color: #364153;
+          margin-top: 4px;
+        }
+
+        .text {
+          font-size: 14px;
+          color: #e7000b;
+        }
+      }
+    }
+  }
+
+  //分页
+  .pagination-bos {
+    width: 1200px;
+    margin: 0 auto;
+    padding-bottom: 60px;
+    :deep(.el-select__wrapper) {
+      background: #f4f4f4;
+      box-shadow: 0 0 0 1px #e5e6eb inset;
+      border-radius: 2px;
+    }
+    :deep(.el-select__placeholder) {
+      color: #1d2129;
+    }
+    :deep(.el-input__wrapper) {
+      background: #f4f4f4;
+      box-shadow: 0 0 0 1px #e5e6eb inset;
+      border-radius: 2px;
+    }
+    :deep(.el-input__inner) {
+      color: #1d2129;
+    }
+
+    :deep(.btn-prev) {
+      background: #f4f4f4;
+      border: 1px solid #e5e6eb;
+      margin-right: 8px;
+    }
+    :deep(.btn-next) {
+      background: #f4f4f4;
+      border: 1px solid #e5e6eb;
+      margin-left: 8px;
+    }
+    :deep(.el-pager) {
+      gap: 0 8px;
+      li {
+        background: #f4f4f4;
+        border: 1px solid #e5e6eb;
+        color: #1d2129;
+      }
+    }
+  }
+}
+</style>

+ 184 - 0
src/views/plan_info/guide.vue

@@ -0,0 +1,184 @@
+<template>
+  <div class="real-pages">
+    <div>
+      <div class="real-info">
+        <div class="title">{{ dataInfo.title }}</div>
+        <div class="time">{{ dataInfo.releaseTime }}</div>
+        <div class="real-html" v-html="dataInfo.content"></div>
+      </div>
+    </div>
+    <div class="related-bos">
+      <div class="related-box">
+        <div class="flex-row-between related-title">
+          <div>相关专题</div>
+          <div class="flex-row-start related-huan" @click="getList">
+            <el-icon><Sort /></el-icon>
+            <div style="margin-left: 4px">换一换</div>
+          </div>
+        </div>
+        <div class="procure-bos">
+          <div v-for="(item, index) in dataList" :key="index" class="procure-list" @click="onPath('/plan_info/guide?id=' + item.id)">
+            <img :src="item.coverImage" alt="" />
+            <div class="procure1">{{ item.title }}</div>
+            <div class="procure2">{{ item.releaseTime }}</div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { onPath } from '@/utils/siteConfig';
+import { getPurchaseGuideDetail, getPurchaseGuideList } from '@/api/plan/index';
+const id = ref<any>(null);
+const dataInfo = ref<any>({});
+const dataList = ref<any>([]);
+const route = useRoute();
+
+onMounted(() => {
+  id.value = route.query.id;
+  getInfo();
+  getList();
+});
+
+const getInfo = () => {
+  getPurchaseGuideDetail(id.value).then((res) => {
+    if (res.code == 200) {
+      dataInfo.value = res.data;
+    }
+  });
+};
+
+const getList = () => {
+  getPurchaseGuideList({
+    pageSize: 10,
+    pageNum: 1
+  }).then((res) => {
+    if (res.code == 200) {
+      if (res.rows && res.rows.length > 0) {
+        if (res.rows.length == 1 || res.rows.length == 2) {
+          dataList.value = res.rows;
+        } else if (res.rows.length > 2) {
+          dataList.value = getRandomElements(res.rows, 3);
+        }
+      }
+    }
+  });
+};
+
+function getRandomElements(arr: any, count: any) {
+  if (count > arr.length) {
+    throw new Error('要取的数量不能超过数组长度');
+  }
+
+  const copy = [...arr];
+  const result = [];
+
+  for (let i = 0; i < count; i++) {
+    const randomIndex = Math.floor(Math.random() * copy.length);
+    result.push(copy.splice(randomIndex, 1)[0]);
+  }
+
+  return result;
+}
+</script>
+
+<style lang="scss" scoped>
+.real-pages {
+  width: 1200px;
+  margin: 0 auto;
+  display: flex;
+  gap: 0 20px;
+  padding-bottom: 50px;
+  .real-info {
+    width: 715px;
+    background: #ffffff;
+    border-radius: 10px;
+    padding: 20px;
+    .title {
+      font-size: 20px;
+      color: #666666;
+    }
+    .time {
+      font-size: 14px;
+      color: #999999;
+      margin: 10px 0 18px 0;
+    }
+    .real-html {
+      width: 679px;
+      :deep(img) {
+        max-width: 100%;
+        height: auto;
+      }
+    }
+    .img {
+      width: 679px;
+      height: 351px;
+      border-radius: 10px;
+    }
+    .head {
+      font-weight: 600;
+      font-size: 14px;
+      color: #101828;
+      margin: 10px 0 18px 0;
+    }
+    .info {
+      font-size: 14px;
+      color: #364153;
+      margin-bottom: 15px;
+    }
+  }
+
+  .related-bos {
+    flex: 1;
+    .related-box {
+      width: 100%;
+      background-color: #ffffff;
+      border-radius: 10px;
+      padding: 20px;
+      .related-title {
+        font-size: 16px;
+        color: #666666;
+        .related-huan {
+          font-size: 14px;
+          cursor: pointer;
+        }
+      }
+      // 采购指南
+      .procure-bos {
+        width: 100%;
+        display: flex;
+        flex-direction: column;
+        margin-top: 12px;
+        gap: 12px 0px;
+        .procure-list {
+          width: 100%;
+          height: 268px;
+          background: #ffffff;
+          cursor: pointer;
+          border-radius: 10px;
+          overflow: hidden;
+          border: 1px solid #d0d5dd;
+          img {
+            width: 100%;
+            height: 200px;
+            border-bottom: 1px solid #d0d5dd;
+          }
+          .procure1 {
+            padding: 12px 0 4px 20px;
+            font-weight: 600;
+            font-size: 14px;
+            color: #101828;
+          }
+          .procure2 {
+            padding-left: 20px;
+            font-size: 12px;
+            color: #364153;
+          }
+        }
+      }
+    }
+  }
+}
+</style>

+ 273 - 0
src/views/plan_info/procure.vue

@@ -0,0 +1,273 @@
+<template>
+  <div class="solve-page">
+    <div class="solve-bos">
+      <img class="solve-img" :src="dataInfo.coverImage" alt="" />
+      <div v-for="(item, index) in dataList" :key="index">
+        <!-- 标题 -->
+        <div class="solve-title flex-row-between">
+          <div class="title1">{{ item.title }}</div>
+          <div class="title2">{{ item.subtitle }}</div>
+        </div>
+        <!-- 数据 -->
+        <div class="data-bos">
+          <div class="data-box">
+            <div v-for="(item1, index1) in item.list" :key="index1" class="data-list" @click="onPath('/item?id=' + item1.id)">
+              <img class="data-img" :src="item1.productImage" alt="" />
+              <div class="data-title">{{ item1.itemName }}</div>
+              <div class="money">
+                <span class="money1">¥{{ item1.memberPrice }}</span>
+                <span class="money2">¥{{ item1.marketPrice }}</span>
+              </div>
+              <div class="data-cat" @click.stop="onCart(item1)">加入购物车</div>
+            </div>
+          </div>
+          <!-- 游标分页控制 -->
+          <pagination
+            v-show="item.list.length > 0"
+            v-model:page="item.pageNum"
+            v-model:limit="item.pageSize"
+            :cursor-mode="true"
+            :has-more="item.hasMore"
+            @pagination="getList(item)"
+          />
+          <!-- -->
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { onPath } from '@/utils/siteConfig';
+import { getProcurementProgramDetail, getProcurementProgramGroupList, getProcurementProgramGroupProductList } from '@/api/plan/index';
+import { addProductShoppingCart } from '@/api/goods/index';
+const id = ref<any>(null);
+const dataInfo = ref<any>({});
+const dataList = ref<any>({});
+const route = useRoute();
+
+onMounted(() => {
+  id.value = route.query.id;
+  getInfo();
+});
+
+const getInfo = async () => {
+  try {
+    // 获取采购计划详情
+    const detailRes = await getProcurementProgramDetail(id.value);
+    if (detailRes.code === 200) {
+      dataInfo.value = detailRes.data;
+    }
+
+    // 获取采购计划分组列表
+    const groupRes = await getProcurementProgramGroupList(id.value);
+    if (groupRes.code === 200) {
+      // 使用 Promise.all 等待所有 onGoods 异步操作完成
+      const updatedData = await Promise.all(
+        groupRes.data.map(async (item: any) => {
+          item.pageSize = 10;
+          item.pageNum = 1;
+          item.hasMore = false;
+          const productList = await onGoods(item); // 等待每个分组的商品列表加载完成
+          item.hasMore = productList.length === item.pageSize;
+          return {
+            ...item,
+            list: productList // 将商品列表赋值给 item.List
+          };
+        })
+      );
+      dataList.value = updatedData; // 更新 dataList
+      console.log(dataList.value);
+    }
+  } catch (error) {
+    console.error('获取数据失败:', error);
+  }
+};
+
+// 修改 onGoods 返回 Promise
+const onGoods = async (item: any) => {
+  try {
+    const res = await getProcurementProgramGroupProductList({ groupId: item.id, pageSize: item.pageSize, pageNum: item.pageNum });
+    if (res.code === 200) {
+      return res.rows; // 返回商品列表
+    }
+    return []; // 如果请求失败,返回空数组
+  } catch (error) {
+    console.error('获取商品列表失败:', error);
+    return []; // 异常情况下也返回空数组
+  }
+};
+
+const getList = (row: any) => {
+  getProcurementProgramGroupProductList({ groupId: row.id, pageSize: row.pageSize, pageNum: row.pageNum }).then((res) => {
+    if (res.code == 200) {
+      row.list = res.rows;
+      // 判断是否还有更多数据
+      row.hasMore = res.rows.length === row.pageSize;
+    }
+  });
+};
+
+//加入购物车
+const onCart = (row: any) => {
+  addProductShoppingCart({
+    productId: row.id,
+    productNum: 1
+  }).then((res) => {
+    if (res.code == 200) {
+      ElMessage.success('加入购物车成功');
+    }
+  });
+};
+</script>
+
+<style lang="scss" scoped>
+.solve-page {
+  width: 100%;
+
+  .solve-bos {
+    width: 1200px;
+    margin: 0 auto;
+    padding-bottom: 30px;
+    .solve-img {
+      width: 1200px;
+      height: 380px;
+      border-radius: 10px;
+      margin-top: 20px;
+    }
+
+    .solve-title {
+      width: 1200px;
+      padding: 10px 20px;
+      background-color: #ffffff;
+      border-radius: 10px;
+      margin-top: 20px;
+      .title1 {
+        font-size: 16px;
+      }
+      .title2 {
+        font-size: 14px;
+        color: #666666;
+      }
+    }
+
+    //数据
+    .data-bos {
+      background-color: #ffffff;
+      padding: 20px 20px;
+      margin-top: 20px;
+      border-radius: 10px;
+      .data-box {
+        display: flex;
+        flex-wrap: wrap;
+        gap: 20px;
+        .data-list {
+          width: 20%;
+          background: #f4f4f4;
+          border-radius: 10px;
+          padding: 20px 20px 22px 20px;
+          cursor: pointer;
+          .data-img {
+            width: 184px;
+            height: 184px;
+            border-radius: 10px;
+          }
+          .data-title {
+            margin-top: 4px;
+            font-size: 14px;
+            color: #101828;
+            height: 40px;
+          }
+          .money {
+            margin-top: 4px;
+            .money1 {
+              font-size: 16px;
+              color: #e7000b;
+            }
+            .money2 {
+              font-size: 12px;
+              color: #99a1af;
+              text-decoration: line-through;
+              padding-left: 6px;
+            }
+          }
+          .data-cat {
+            width: 86px;
+            height: 26px;
+            background: #e7000b;
+            border-radius: 2px;
+            font-size: 14px;
+            color: #ffffff;
+            line-height: 26px;
+            text-align: center;
+            margin-top: 16px;
+          }
+        }
+      }
+    }
+
+    .title {
+      font-weight: 600;
+      font-size: 20px;
+      color: #101828;
+      margin-top: 20px;
+    }
+    .info {
+      font-size: 14px;
+      color: #364153;
+      margin-top: 8px;
+      border-bottom: 1px solid #e5e7eb;
+      padding-bottom: 20px;
+    }
+    .filter-bos {
+      padding-bottom: 20px;
+      border-bottom: 1px solid #e5e7eb;
+      .filter-list {
+        margin-top: 20px;
+
+        .filter-title {
+          font-size: 14px;
+          color: #101828;
+          margin-right: 40px;
+        }
+
+        .filter-item {
+          font-size: 14px;
+          color: #364153;
+          margin-right: 30px;
+          cursor: pointer;
+
+          &.hig {
+            color: #e7000b;
+          }
+        }
+      }
+    }
+    .nav-bos {
+      width: 1200px;
+      padding: 20px 0;
+
+      .nav-list {
+        height: 32px;
+        padding: 0 12px;
+        background: #f7f8fa;
+        border-radius: 2px 2px 2px 2px;
+        font-size: 14px;
+        color: #4e5969;
+        margin-right: 8px;
+        line-height: 32px;
+        cursor: pointer;
+
+        &.hig {
+          background: #ffe8e8;
+          color: #e7000b;
+        }
+
+        &:hover {
+          color: #e7000b;
+        }
+      }
+    }
+  }
+}
+</style>

+ 149 - 0
src/views/plan_info/project.vue

@@ -0,0 +1,149 @@
+<template>
+  <div class="real-pages">
+    <div>
+      <div class="real-info">
+        <div class="title">{{ dataInfo.caseTitle }}</div>
+        <div class="time">{{ dataInfo.projectBrief }}</div>
+        <div class="real-html" v-html="dataInfo.projectDetails"></div>
+      </div>
+    </div>
+    <div class="related-bos">
+      <div class="flex-row-between related-title">
+        <div>其他客户案例</div>
+        <div class="flex-row-start related-huan" @click="onPath('/plan/project')">
+          <div>更多</div>
+          <el-icon style="margin-left: 4px"><ArrowRight /></el-icon>
+        </div>
+      </div>
+      <div class="related-box">
+        <div v-for="(item, index) in dataList" :key="index" class="procure-list ellipsis" @click="onPath('/plan_info/project?id=' + item.id)">
+          {{ item.caseTitle }}
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { onPath } from '@/utils/siteConfig';
+import { getProjectCaseDetail, getProjectCaseAllList } from '@/api/plan/index';
+const id = ref<any>(null);
+const dataInfo = ref<any>({});
+const dataList = ref<any>([]);
+const route = useRoute();
+
+onMounted(() => {
+  id.value = route.query.id;
+  getInfo();
+  getList();
+});
+
+const getInfo = () => {
+  getProjectCaseDetail(id.value).then((res) => {
+    if (res.code == 200) {
+      dataInfo.value = res.data;
+    }
+  });
+};
+
+const getList = () => {
+  getProjectCaseAllList({
+    pageSize: 10,
+    pageNum: 1
+  }).then((res) => {
+    if (res.code == 200) {
+      dataList.value = res.rows;
+    }
+  });
+};
+</script>
+
+<style lang="scss" scoped>
+.real-pages {
+  width: 1200px;
+  margin: 0 auto;
+  display: flex;
+  gap: 0 20px;
+  padding-bottom: 50px;
+  .real-info {
+    width: 715px;
+    background: #ffffff;
+    border-radius: 10px;
+    padding: 20px;
+    .title {
+      font-size: 20px;
+      color: #666666;
+    }
+    .time {
+      font-size: 14px;
+      color: #999999;
+      margin: 10px 0 18px 0;
+    }
+    .real-html {
+      width: 679px;
+      :deep(img) {
+        max-width: 100%;
+        height: auto;
+      }
+    }
+    .img {
+      width: 679px;
+      height: 351px;
+      border-radius: 10px;
+    }
+    .head {
+      font-weight: 600;
+      font-size: 14px;
+      color: #101828;
+      margin: 10px 0 18px 0;
+    }
+    .info {
+      font-size: 14px;
+      color: #364153;
+      margin-bottom: 15px;
+    }
+  }
+
+  .related-bos {
+    flex: 1;
+    .related-title {
+      font-size: 16px;
+      color: #323232;
+      width: 100%;
+      background-color: #ffffff;
+      border-radius: 10px;
+      padding: 10px 20px;
+      .related-huan {
+        font-size: 14px;
+        cursor: pointer;
+        color: #969696;
+        &:hover {
+          color: var(--el-color-primary);
+        }
+      }
+    }
+    .related-box {
+      width: 100%;
+      background-color: #ffffff;
+      border-radius: 10px;
+      padding: 10px 20px;
+      margin-top: 20px;
+      display: flex;
+      flex-direction: column;
+      gap: 15px;
+
+      .procure-list {
+        width: 100%;
+        background: #ffffff;
+        cursor: pointer;
+        border-radius: 10px;
+        font-size: 14px;
+        color: #333333;
+        &:hover {
+          color: var(--el-color-primary);
+        }
+      }
+    }
+  }
+}
+</style>

+ 296 - 0
src/views/search/brand.vue

@@ -0,0 +1,296 @@
+<template>
+  <div class="search-pages">
+    <!-- 筛选 -->
+    <div class="search-head">
+      <div class="head-bos">
+        <div class="head-title">分类:</div>
+        <div class="head-box">
+          <div
+            @click="onHead(item, 'categoryId')"
+            class="classify-list"
+            v-for="(item, index) in classifyList"
+            :key="index"
+            :class="item.id == httpObj.categoryId ? 'hig' : ''"
+          >
+            {{ item.label }}
+          </div>
+        </div>
+      </div>
+      <div class="head-bos head-bos1">
+        <div class="head-title">字母:</div>
+        <div class="head-box">
+          <div
+            @click="onHead(item, 'initial')"
+            class="classify-list"
+            v-for="(item, index) in initialList"
+            :key="index"
+            :class="item.id == httpObj.initial ? 'hig' : ''"
+          >
+            {{ item.label }}
+          </div>
+        </div>
+      </div>
+      <div class="head-bos head-bos1">
+        <div class="head-title">品牌名称:</div>
+        <div class="head-box">
+          <el-input @input="getList" v-model="httpObj.name" style="width: 240px" placeholder="请输入品牌名称" />
+        </div>
+      </div>
+    </div>
+    <!-- 商品 -->
+    <div class="expert-bos">
+      <div v-for="(item, index) in dataList" :key="index" class="expert-list" @click="onPath('/item?id=' + item.id)">
+        <img :src="item.brandBigImage" alt="" />
+        <div class="itemName ellipsis">{{ item.brandRegistrant || 'dffddsfsdf' }}</div>
+      </div>
+    </div>
+    <!-- 游标分页控制 -->
+    <pagination
+      v-show="dataList.length > 0"
+      v-model:page="httpObj.pageNum"
+      v-model:limit="httpObj.pageSize"
+      v-model:way="way"
+      :cursor-mode="true"
+      :has-more="hasMore"
+      @pagination="getList"
+    />
+  </div>
+</template>
+
+<script setup lang="ts">
+import { getBrandByCategoryList, getBrandPage } from '@/api/search/index';
+import { getProductCategoryTree } from '@/api/home/index';
+import { onPath } from '@/utils/siteConfig';
+import Pagination from '@/components/Pagination/index.vue';
+const route = useRoute();
+const type = ref<any>(1);
+const dataList = ref<any>([]);
+const checkList = ref<any>([]);
+const classifyList = ref<any>([]);
+const brandList = ref<any>([]);
+const categoryName = ref<any>('');
+const hasMore = ref(true); // 是否还有更多数据
+const way = ref<any>(1);
+const httpObj = ref<any>({
+  categoryId: '',
+  initial: '',
+  name: '',
+  pageSize: 10,
+  pageNum: 1
+});
+const initialList = ref<any>([
+  { label: '全部', id: '' },
+  { label: 'A', id: 'A' },
+  { label: 'B', id: 'B' },
+  { label: 'C', id: 'C' },
+  { label: 'D', id: 'D' },
+  { label: 'E', id: 'E' },
+  { label: 'F', id: 'F' },
+  { label: 'G', id: 'G' },
+  { label: 'H', id: 'H' },
+  { label: 'I', id: 'I' },
+  { label: 'J', id: 'J' },
+  { label: 'K', id: 'K' },
+  { label: 'L', id: 'L' },
+  { label: 'M', id: 'M' },
+  { label: 'N', id: 'N' },
+  { label: 'O', id: 'O' },
+  { label: 'P', id: 'P' },
+  { label: 'Q', id: 'Q' },
+  { label: 'R', id: 'R' },
+  { label: 'S', id: 'S' },
+  { label: 'T', id: 'T' },
+  { label: 'U', id: 'U' },
+  { label: 'V', id: 'V' },
+  { label: 'W', id: 'W' },
+  { label: 'X', id: 'X' },
+  { label: 'Y', id: 'Y' },
+  { label: 'Z', id: 'Z' }
+]);
+const sortField1 = ref<any>('');
+const sortField2 = ref<any>('');
+const sortField3 = ref<any>('');
+
+const getList = () => {
+  if (sortField1.value) {
+    httpObj.value.sortField = '1';
+    httpObj.value.sortOrder = sortField1.value;
+  }
+  if (sortField2.value) {
+    httpObj.value.sortField = httpObj.value.sortField + (httpObj.value.sortField ? ',2' : '2');
+    httpObj.value.sortOrder = httpObj.value.sortOrder + (httpObj.value.sortOrder ? ',' + sortField2.value : sortField2.value);
+  }
+  if (sortField3.value) {
+    httpObj.value.sortField = httpObj.value.sortField + (httpObj.value.sortField ? ',3' : '3');
+    httpObj.value.sortOrder = httpObj.value.sortOrder + (httpObj.value.sortOrder ? ',' + sortField3.value : sortField3.value);
+  }
+  if (checkList.value.length > 0) {
+    httpObj.value.isCustomize = 1;
+  } else {
+    httpObj.value.isCustomize = '';
+  }
+  getBrandByCategoryList(httpObj.value).then((res) => {
+    if (res.code == 200) {
+      dataList.value = res.rows;
+      // 判断是否还有更多数据
+      hasMore.value = dataList.value.length === httpObj.value.pageSize;
+    }
+  });
+};
+
+//头部分类
+
+const onHead = (item: any, type: string) => {
+  if (type == 'topCategoryId') {
+    if (item.id) {
+      getBrand();
+    } else {
+    }
+  }
+  httpObj.value[type] = item.id;
+};
+
+//查询品牌
+const getBrand = () => {
+  getBrandPage({
+    categoryName: categoryName.value,
+    categoryId: httpObj.value.topCategoryId,
+    pageSize: 100,
+    pageNum: 1
+  }).then((res) => {
+    if (res.code == 200) {
+      brandList.value = res.rows;
+    }
+  });
+};
+
+//筛选品牌
+const remoteMethod = (res: any) => {
+  if (res) {
+    categoryName.value = res;
+  } else {
+    categoryName.value = '';
+  }
+  getBrand();
+};
+
+// 筛选条件
+const onSort = (type: number) => {
+  if (type == 1) {
+    if (sortField1.value == '' || sortField1.value == 'Desc') {
+      sortField1.value = 'Asc';
+    } else if (sortField1.value == 'Asc') {
+      sortField1.value = 'Desc';
+    }
+  }
+  if (type == 2) {
+    if (sortField2.value == '' || sortField2.value == 'Desc') {
+      sortField2.value = 'Asc';
+    } else if (sortField2.value == 'Asc') {
+      sortField2.value = 'Desc';
+    }
+  }
+  if (type == 3) {
+    if (sortField3.value == '' || sortField3.value == 'Desc') {
+      sortField3.value = 'Asc';
+    } else if (sortField3.value == 'Asc') {
+      sortField3.value = 'Desc';
+    }
+  }
+  getList();
+};
+
+onMounted(() => {
+  getProductCategoryTree({}).then((res) => {
+    if (res.code == 200) {
+      res.data.unshift({
+        label: '全部',
+        id: ''
+      });
+      classifyList.value = res.data;
+    }
+  });
+
+  getList();
+});
+</script>
+
+<style lang="scss" scoped>
+.search-pages {
+  width: 1200px;
+  margin: 0 auto;
+
+  // 筛选
+  .search-head {
+    width: 1200px;
+    background: #ffffff;
+    border-radius: 10px;
+    padding: 0 15px 15px 15px;
+    font-size: 14px;
+    color: #101828;
+
+    .head-bos {
+      display: flex;
+
+      &.head-bos1 {
+        // align-items: center;
+      }
+
+      .head-title {
+        width: 70px;
+        padding-top: 15px;
+      }
+
+      .head-box {
+        display: flex;
+        flex-wrap: wrap;
+        flex: 1;
+        width: 0;
+        gap: 10px 15px;
+        border-bottom: 1px solid #e5e7eb;
+        padding: 15px 0;
+
+        .classify-list {
+          cursor: pointer;
+
+          &.hig {
+            color: var(--el-color-primary);
+          }
+        }
+      }
+    }
+  }
+
+  // 商品
+  // 行家精选
+  .expert-bos {
+    width: 1200px;
+    display: flex;
+    flex-wrap: wrap;
+    margin-top: 12px;
+    gap: 15px;
+
+    .expert-list {
+      width: 228px;
+      height: 140px;
+      background: #ffffff;
+      border-radius: 10px;
+      padding: 20px;
+      cursor: pointer;
+
+      img {
+        width: 100%;
+        height: 70px;
+      }
+
+      .itemName {
+        font-weight: 400;
+        font-size: 14px;
+        color: #999999;
+        margin-top: 10px;
+        text-align: center;
+      }
+    }
+  }
+}
+</style>

+ 162 - 29
src/views/search/index.vue

@@ -1,29 +1,58 @@
 <template>
   <div class="search-pages">
+    <div v-if="search && type == 1" class="breadcrumb flex-row-center">
+      <div class="breadcrumb-bos flex-row-start">
+        <div class="home" @click="onPath('/index')">首页</div>
+        <div class="nav-list">
+          <el-icon style="margin: 0 4px"><ArrowRight /></el-icon>
+          <div class="like">搜索结果</div>
+        </div>
+        <el-icon style="margin: 0 4px"><ArrowRight /></el-icon>
+        <div>{{ search || '' }}</div>
+      </div>
+    </div>
+    <div v-else style="height: 15px"></div>
     <!-- 筛选 -->
     <div class="search-head">
       <div class="head-bos">
         <div class="head-title">分类:</div>
         <div class="head-box">
           <div
-            @click="onHead(item, 'topCategoryId')"
+            @click="onHead(item, type == 1 ? 'topCategoryId' : type == 2 ? 'middleCategoryId' : 'bottomCategoryId')"
             class="classify-list"
             v-for="(item, index) in classifyList"
             :key="index"
-            :class="item.id == httpObj.topCategoryId ? 'hig' : ''"
+            :class="{
+              hig:
+                type == 1 ? item.id == httpObj.topCategoryId : type == 2 ? item.id == httpObj.middleCategoryId : item.id == httpObj.bottomCategoryId
+            }"
           >
             {{ item.label }}
           </div>
         </div>
       </div>
-      <div class="head-bos">
+      <div class="head-bos" v-if="type == 1">
         <div class="head-title">品牌:</div>
-        <div class="head-box" v-if="type == 1">
+        <div class="head-box">
           <el-select v-model="httpObj.brandId" filterable remote :remote-method="remoteMethod" placeholder="请输入名牌名称" style="width: 240px">
             <el-option v-for="item in brandList" :key="item.id" :label="item.brandName" :value="item.id" />
           </el-select>
         </div>
       </div>
+      <div class="head-bos" v-else>
+        <div class="head-title">品牌:</div>
+        <div class="head-box">
+          <div
+            @click="onHead(item, 'brandId')"
+            class="classify-list"
+            v-for="(item, index) in brandList"
+            :key="index"
+            :class="item.id == httpObj.brandId ? 'hig' : ''"
+          >
+            {{ item.brandName }}
+          </div>
+        </div>
+      </div>
       <div class="head-bos">
         <div class="head-title">价格:</div>
         <div class="head-box">
@@ -38,6 +67,7 @@
           </div>
         </div>
       </div>
+
       <div class="head-bos">
         <div class="head-sort flex-row-center" @click="onSort(1)" :class="sortField1 != '' ? 'hig' : ''">
           <div>智能匹配</div>
@@ -75,6 +105,9 @@
           <span class="marketPrice">¥{{ item.marketPrice }}</span>
         </div>
       </div>
+      <div class="empty-bos">
+        <el-empty v-if="dataList.length === 0" description="暂无数据" />
+      </div>
     </div>
     <!-- 游标分页控制 -->
     <pagination
@@ -90,10 +123,11 @@
 </template>
 
 <script setup lang="ts">
-import { getPcProductPage, getBrandPage } from '@/api/search/index';
+import { getPcProductPage, getBrandPage, getBrandByCategoryList } from '@/api/search/index';
 import { getProductCategoryTree } from '@/api/home/index';
 import { onPath } from '@/utils/siteConfig';
 import Pagination from '@/components/Pagination/index.vue';
+import { get } from 'http';
 const route = useRoute();
 const type = ref<any>(1);
 const dataList = ref<any>([]);
@@ -103,14 +137,17 @@ const brandList = ref<any>([]);
 const categoryName = ref<any>('');
 const hasMore = ref(true); // 是否还有更多数据
 const way = ref<any>(1);
+const search = ref<any>('');
 const httpObj = ref<any>({
   topCategoryId: '',
+  middleCategoryId: '',
+  bottomCategoryId: '',
   brandId: '',
   priceRange: '',
   sortField: '',
   sortOrder: '',
   isCustomize: '',
-  pageSize: 10,
+  pageSize: 20,
   pageNum: 1
 });
 const priceList = ref<any>([
@@ -144,36 +181,72 @@ const getList = () => {
   }
   getPcProductPage(httpObj.value).then((res) => {
     if (res.code == 200) {
-      dataList.value = res.rows;
+      dataList.value = res.rows ? res.rows : [];
       // 判断是否还有更多数据
       hasMore.value = dataList.value.length === httpObj.value.pageSize;
     }
   });
 };
 
-//头部分类
-getProductCategoryTree({}).then((res) => {
-  if (res.code == 200) {
-    res.data.unshift({
-      label: '全部',
-      id: ''
-    });
-    classifyList.value = res.data;
-  }
-});
+// 获取分类
+const getClassify = () => {
+  getProductCategoryTree({}).then((res) => {
+    if (res.code == 200) {
+      if (type.value == 2 && httpObj.value.middleCategoryId) {
+        res.data.forEach((item1: any) => {
+          item1.children.unshift({
+            label: '全部',
+            id: ''
+          });
+          item1.children.forEach((item2: any) => {
+            if (item2.id == httpObj.value.middleCategoryId) {
+              httpObj.value.topCategoryId = item1.id;
+              classifyList.value = item1.children;
+            }
+          });
+        });
+        getList();
+        //获取当前分类下得品牌
+        getBrand2();
+      } else if (type.value == 3 && httpObj.value.bottomCategoryId) {
+        res.data.forEach((item1: any) => {
+          item1.children.forEach((item2: any) => {
+            if (item2.children && item2.children.length > 0) {
+              item2.children.unshift({
+                label: '全部',
+                id: ''
+              });
+              item2.children.forEach((item3: any) => {
+                if (item3.id == httpObj.value.bottomCategoryId) {
+                  httpObj.value.topCategoryId = item1.id;
+                  httpObj.value.middleCategoryId = item2.id;
+                  classifyList.value = item2.children;
+                }
+              });
+            }
+          });
+        });
+        getList();
+        //获取当前分类下得品牌
+        getBrand2();
+      } else {
+        res.data.unshift({
+          label: '全部',
+          id: ''
+        });
+        classifyList.value = res.data;
+      }
+    }
+  });
+};
 
 const onHead = (item: any, type: string) => {
-  if (type == 'topCategoryId') {
-    if (item.id) {
-      getBrand();
-    } else {
-    }
-  }
   httpObj.value[type] = item.id;
+  getList();
 };
 
 //查询品牌
-const getBrand = () => {
+const getBrand1 = () => {
   getBrandPage({
     categoryName: categoryName.value,
     categoryId: httpObj.value.topCategoryId,
@@ -186,6 +259,23 @@ const getBrand = () => {
   });
 };
 
+//查询分类下得品牌
+const getBrand2 = () => {
+  getBrandByCategoryList({
+    categoryId: httpObj.value.topCategoryId,
+    pageSize: 100,
+    pageNum: 1
+  }).then((res) => {
+    if (res.code == 200) {
+      res.rows.unshift({
+        brandName: '全部',
+        id: ''
+      });
+      brandList.value = res.rows;
+    }
+  });
+};
+
 //筛选品牌
 const remoteMethod = (res: any) => {
   if (res) {
@@ -193,7 +283,7 @@ const remoteMethod = (res: any) => {
   } else {
     categoryName.value = '';
   }
-  getBrand();
+  getBrand1();
 };
 
 // 筛选条件
@@ -223,19 +313,32 @@ const onSort = (type: number) => {
 };
 
 onMounted(() => {
+  httpObj.value.topCategoryId = '';
   type.value = route.query.type;
   if (type.value == 1) {
-    httpObj.value.topCategoryId = '';
+    getBrand1();
+    if (route.query.input) {
+      search.value = route.query.input;
+    }
+    if (route.query.topCategoryId) {
+      httpObj.value.topCategoryId = route.query.topCategoryId;
+    }
+    getList();
   }
-  getList();
-  getBrand();
+  if (type.value == 2 && route.query.middleCategoryId) {
+    httpObj.value.middleCategoryId = route.query.middleCategoryId;
+  }
+  if (type.value == 3 && route.query.bottomCategoryId) {
+    httpObj.value.bottomCategoryId = route.query.bottomCategoryId;
+  }
+  getClassify();
 });
 </script>
 
 <style lang="scss" scoped>
 .search-pages {
   width: 1200px;
-  margin: 0 auto;
+  margin: 0px auto 0 auto;
   // 筛选
   .search-head {
     width: 1200px;
@@ -332,6 +435,36 @@ onMounted(() => {
         }
       }
     }
+
+    .empty-bos {
+      width: 100%;
+      background-color: #ffffff;
+      border-radius: 10px;
+      margin-bottom: 20px;
+    }
+  }
+
+  //面包屑
+  .breadcrumb {
+    width: 100%;
+    height: 44px;
+    padding-left: 20px;
+    .breadcrumb-bos {
+      width: 1200px;
+      font-size: 14px;
+      color: #101828;
+      .nav-list {
+        height: 44px;
+        display: flex;
+        align-items: center;
+      }
+      .home {
+        cursor: pointer;
+        &:hover {
+          color: var(--el-color-primary);
+        }
+      }
+    }
   }
 }
 </style>

+ 320 - 0
src/views/search/special.vue

@@ -0,0 +1,320 @@
+<template>
+  <div class="search-pages">
+    <!-- 筛选 -->
+    <div class="search-head">
+      <div class="head-bos">
+        <div class="head-title">分类:</div>
+        <div class="head-box">
+          <div
+            @click="onHead(item, 'topCategoryId')"
+            class="classify-list"
+            v-for="(item, index) in classifyList"
+            :key="index"
+            :class="item.id == httpObj.topCategoryId ? 'hig' : ''"
+          >
+            {{ item.categoryName }}
+          </div>
+        </div>
+      </div>
+      <div class="head-bos">
+        <div class="head-title">品牌:</div>
+        <div class="head-box">
+          <div
+            @click="onHead(item, 'brandId')"
+            class="classify-list"
+            v-for="(item, index) in brandList"
+            :key="index"
+            :class="item.id == httpObj.brandId ? 'hig' : ''"
+          >
+            {{ item.brandName }}
+          </div>
+        </div>
+      </div>
+      <div class="head-bos">
+        <div class="head-title">价格:</div>
+        <div class="head-box">
+          <div
+            @click="onHead(item, 'priceRange')"
+            class="classify-list"
+            v-for="(item, index) in priceList"
+            :key="index"
+            :class="item.id == httpObj.priceRange ? 'hig' : ''"
+          >
+            {{ item.label }}
+          </div>
+        </div>
+      </div>
+      <div class="head-bos">
+        <div class="head-sort flex-row-center" @click="onSort(1)" :class="sortField1 != '' ? 'hig' : ''">
+          <div>智能匹配</div>
+          <div class="sort-box">
+            <el-icon :color="sortField1 == 'Asc' ? '#E7000B' : '#333333'" class="icon1" :size="12"><CaretTop /></el-icon>
+            <el-icon :color="sortField1 == 'Desc' ? '#E7000B' : '#333333'" class="icon2" :size="12"><CaretBottom /></el-icon>
+          </div>
+        </div>
+        <div class="head-sort flex-row-center" @click="onSort(2)" :class="sortField2 != '' ? 'hig' : ''">
+          <div>库存排序</div>
+          <div class="sort-box">
+            <el-icon :color="sortField2 == 'Asc' ? '#E7000B' : '#333333'" class="icon1" :size="12"><CaretTop /></el-icon>
+            <el-icon :color="sortField2 == 'Desc' ? '#E7000B' : '#333333'" class="icon2" :size="12"><CaretBottom /></el-icon>
+          </div>
+        </div>
+        <div class="head-sort flex-row-center" @click="onSort(3)" :class="sortField3 != '' ? 'hig' : ''">
+          <div>价格排序</div>
+          <div class="sort-box">
+            <el-icon :color="sortField3 == 'Asc' ? '#E7000B' : '#333333'" class="icon1" :size="12"><CaretTop /></el-icon>
+            <el-icon :color="sortField3 == 'Desc' ? '#E7000B' : '#333333'" class="icon2" :size="12"><CaretBottom /></el-icon>
+          </div>
+        </div>
+        <el-checkbox-group v-model="checkList" style="margin-top: 15px" @change="getList">
+          <el-checkbox label="可定制" value="isCustomize" />
+        </el-checkbox-group>
+      </div>
+    </div>
+    <!-- 商品 -->
+    <div class="expert-bos">
+      <div v-for="(item, index) in dataList" :key="index" class="expert-list" @click="onPath('/item?id=' + item.id)">
+        <img :src="item.productImage" alt="" />
+        <div class="itemName ellipsis">{{ item.itemName || '' }}</div>
+        <div class="price">
+          <span class="memberPrice">¥{{ item.memberPrice }}</span>
+          <span class="marketPrice">¥{{ item.marketPrice }}</span>
+        </div>
+      </div>
+    </div>
+    <!-- 游标分页控制 -->
+    <pagination
+      v-show="dataList.length > 0"
+      v-model:page="httpObj.pageNum"
+      v-model:limit="httpObj.pageSize"
+      v-model:way="way"
+      :cursor-mode="true"
+      :has-more="hasMore"
+      @pagination="getList"
+    />
+  </div>
+</template>
+
+<script setup lang="ts">
+import { getSpecialProductList, getBrandPage, getSpecialCategoryList, getSpecialBrandList } from '@/api/search/index';
+import { onPath } from '@/utils/siteConfig';
+import Pagination from '@/components/Pagination/index.vue';
+const route = useRoute();
+const type = ref<any>(1);
+const dataList = ref<any>([]);
+const checkList = ref<any>([]);
+const classifyList = ref<any>([]);
+const brandList = ref<any>([]);
+const categoryName = ref<any>('');
+const hasMore = ref(true); // 是否还有更多数据
+const way = ref<any>(1);
+const httpObj = ref<any>({
+  topCategoryId: '',
+  brandId: '',
+  priceRange: '',
+  sortField: '',
+  sortOrder: '',
+  isCustomize: '',
+  pageSize: 10,
+  pageNum: 1
+});
+const priceList = ref<any>([
+  { label: '全部', id: '' },
+  { label: '1-100', id: 1 },
+  { label: '100-500', id: 2 },
+  { label: '500-1000', id: 3 },
+  { label: '1000以上', id: 4 }
+]);
+const sortField1 = ref<any>('');
+const sortField2 = ref<any>('');
+const sortField3 = ref<any>('');
+
+const getList = () => {
+  if (sortField1.value) {
+    httpObj.value.sortField = '1';
+    httpObj.value.sortOrder = sortField1.value;
+  }
+  if (sortField2.value) {
+    httpObj.value.sortField = httpObj.value.sortField + (httpObj.value.sortField ? ',2' : '2');
+    httpObj.value.sortOrder = httpObj.value.sortOrder + (httpObj.value.sortOrder ? ',' + sortField2.value : sortField2.value);
+  }
+  if (sortField3.value) {
+    httpObj.value.sortField = httpObj.value.sortField + (httpObj.value.sortField ? ',3' : '3');
+    httpObj.value.sortOrder = httpObj.value.sortOrder + (httpObj.value.sortOrder ? ',' + sortField3.value : sortField3.value);
+  }
+  if (checkList.value.length > 0) {
+    httpObj.value.isCustomize = 1;
+  } else {
+    httpObj.value.isCustomize = '';
+  }
+  getSpecialProductList(httpObj.value).then((res) => {
+    if (res.code == 200) {
+      dataList.value = res.rows;
+      // 判断是否还有更多数据
+      hasMore.value = dataList.value.length === httpObj.value.pageSize;
+    }
+  });
+};
+
+//头部分类
+
+const onHead = (item: any, type: string) => {
+  httpObj.value[type] = item.id;
+  getList();
+};
+
+// 筛选条件
+const onSort = (type: number) => {
+  if (type == 1) {
+    if (sortField1.value == '' || sortField1.value == 'Desc') {
+      sortField1.value = 'Asc';
+    } else if (sortField1.value == 'Asc') {
+      sortField1.value = 'Desc';
+    }
+  }
+  if (type == 2) {
+    if (sortField2.value == '' || sortField2.value == 'Desc') {
+      sortField2.value = 'Asc';
+    } else if (sortField2.value == 'Asc') {
+      sortField2.value = 'Desc';
+    }
+  }
+  if (type == 3) {
+    if (sortField3.value == '' || sortField3.value == 'Desc') {
+      sortField3.value = 'Asc';
+    } else if (sortField3.value == 'Asc') {
+      sortField3.value = 'Desc';
+    }
+  }
+  getList();
+};
+
+onMounted(() => {
+  //特价商品品牌
+  getSpecialBrandList({}).then((res) => {
+    if (res.code == 200) {
+      res.data.unshift({
+        brandName: '全部',
+        id: ''
+      });
+      brandList.value = res.data;
+    }
+  });
+
+  //特价商品分类
+  getSpecialCategoryList({}).then((res) => {
+    if (res.code == 200) {
+      res.data.unshift({
+        categoryName: '全部',
+        id: ''
+      });
+      classifyList.value = res.data;
+    }
+  });
+  getList();
+});
+</script>
+
+<style lang="scss" scoped>
+.search-pages {
+  width: 1200px;
+  margin: 0 auto;
+  // 筛选
+  .search-head {
+    width: 1200px;
+    background: #ffffff;
+    border-radius: 10px;
+    padding: 0 15px 15px 15px;
+    font-size: 14px;
+    color: #101828;
+    .head-bos {
+      display: flex;
+      .head-title {
+        width: 70px;
+        padding-top: 15px;
+      }
+      .head-box {
+        display: flex;
+        flex-wrap: wrap;
+        flex: 1;
+        width: 0;
+        gap: 10px 15px;
+        border-bottom: 1px solid #e5e7eb;
+        padding: 15px 0;
+        .classify-list {
+          cursor: pointer;
+          &.hig {
+            color: var(--el-color-primary);
+          }
+        }
+      }
+      .head-sort {
+        margin: 15px 15px 0 0;
+        width: 108px;
+        height: 32px;
+        border: 1px solid #e5e7eb;
+        border-radius: 2px 2px 2px 2px;
+        cursor: pointer;
+        &.hig {
+          border: 1px solid var(--el-color-primary);
+        }
+        .sort-box {
+          margin-left: 10px;
+          position: relative;
+          height: 32px;
+          .icon1 {
+            position: absolute;
+            top: 6px;
+          }
+          .icon2 {
+            position: absolute;
+            bottom: 6px;
+          }
+        }
+      }
+    }
+  }
+  // 商品
+  // 行家精选
+  .expert-bos {
+    width: 1200px;
+    display: flex;
+    flex-wrap: wrap;
+    margin-top: 12px;
+    gap: 20px 12.5px;
+    .expert-list {
+      width: 230px;
+      height: 306px;
+      background: #ffffff;
+
+      padding: 20px;
+      cursor: pointer;
+      img {
+        width: 100%;
+        height: 190px;
+      }
+      .itemName {
+        font-weight: 400;
+        font-size: 14px;
+        color: #101828;
+        margin: 27px 0 2px 0;
+      }
+      .price {
+        .memberPrice {
+          color: var(--el-color-primary);
+          font-size: 16px;
+          color: #e7000b;
+        }
+        .marketPrice {
+          font-size: 12px;
+          color: #99a1af;
+          line-height: 20px;
+          text-decoration-line: line-through;
+          text-transform: none;
+          margin-left: 6px;
+        }
+      }
+    }
+  }
+}
+</style>

+ 29 - 13
src/views/solve/real.vue

@@ -2,18 +2,9 @@
   <div class="real-pages">
     <div>
       <div class="real-info">
-        <div class="title">喜讯|优易365中标“吉林大学通用办公用品、电子耗材采购项目</div>
-        <div class="time">2025/09/22</div>
-        <img class="img" src="@/assets/images/login-background.jpg" alt="" />
-        <div class="head">项目介绍</div>
-        <div class="info">
-          吉林大学是教育部直属全国重点综合性大学,位于吉林长春。学校始建于 1946 年,是国家 “211 工程”“985 工程” 和首批 “双一流”
-          建设高校。学科门类齐全,涵盖 13 大学科门类,下设 40 多个教学单位。有专任教师 6000
-          余人,其中国家级人才众多。校园占地面积广阔,图书馆藏书丰富。学校聚焦世界名校合作,与 300 多所高校和科研机构建立合作关系。
-          2025年吉林大学启动通用办公用品及电子耗材采购项目(项目编号:JLU-XC25055-0618)的招标,优易达(武汉)有限公司凭借全国性服务网络、数字化供应链管理体系及政企集采标杆案例,从全国竞争者中脱颖而出,成为吉林大学通用办公用品及电子耗材采购项目入围供应商!
-          此次同吉林大学的合作,优易365将坚守“全国资源+本地服务”理念,以数字化采购解决方案赋能高校行政效率提升。携手共创智慧校园新生态
-        </div>
-        <img class="img" src="@/assets/images/login-background.jpg" alt="" />
+        <div class="title">{{ dataInfo.announcementTitle }}</div>
+        <div class="time">{{ dataInfo.createTime }}</div>
+        <div class="real-html" v-html="dataInfo.announcementContent"></div>
       </div>
     </div>
 
@@ -36,7 +27,25 @@
   </div>
 </template>
 
-<script setup lang="ts"></script>
+<script setup lang="ts">
+import { onPath } from '@/utils/siteConfig';
+import { getYouYzXunInfo } from '@/api/plan/index';
+const id = ref<any>(null);
+const dataInfo = ref<any>({});
+const route = useRoute();
+onMounted(() => {
+  id.value = route.query.id;
+  getInfo();
+});
+
+const getInfo = () => {
+  getYouYzXunInfo(id.value).then((res) => {
+    if (res.code == 200) {
+      dataInfo.value = res.data;
+    }
+  });
+};
+</script>
 
 <style lang="scss" scoped>
 .real-pages {
@@ -59,6 +68,13 @@
       color: #364153;
       margin: 10px 0 18px 0;
     }
+    .real-html {
+      width: 679px;
+      :deep(img) {
+        max-width: 100%;
+        height: auto;
+      }
+    }
     .img {
       width: 679px;
       height: 351px;

+ 116 - 60
src/views/trad/index.vue

@@ -12,29 +12,42 @@
       </div>
       <div class="address-title">收货地址</div>
       <div class="address-bos">
-        <div v-for="(item, index) in 4" :key="index" class="address-list flex-column-between" :class="index == 0 ? 'hig' : ''">
-          <div class="address1">广东省 广州市 萝岗区科学城11号</div>
-          <div class="address2">中国南方电网有限公司</div>
-          <div class="address3">18062697722</div>
+        <div
+          @click="onAddress(item)"
+          v-for="(item, index) in addressList"
+          :key="index"
+          class="address-list flex-column-between"
+          :class="item.id == form.shippingAddressId ? 'hig' : ''"
+        >
+          <div class="address1">{{ item.provincialCityCountry }}{{ item.address }}</div>
+          <div class="address2">{{ item.consignee }}</div>
+          <div class="address3">{{ item.phone }}</div>
         </div>
       </div>
       <div class="address-more flex-row-start">
-        <div>展开全部地址</div>
-        <el-icon style="margin-left: 6px" color="#6A7282" size="14"><ArrowDown /></el-icon>
+        <!-- <div>展开全部地址</div>
+        <el-icon style="margin-left: 6px" color="#6A7282" size="14"><ArrowDown /></el-icon> -->
       </div>
       <div class="form-bos">
         <div class="form-title flex-row-start">
           <div class="asterisk">*</div>
           <div>配送时间</div>
         </div>
-        <el-date-picker style="width: 340px" v-model="form.value1" type="date" placeholder="选择日期" />
+        <el-date-picker
+          format="YYYY-MM-DD"
+          value-format="YYYY-MM-DD"
+          style="width: 340px"
+          v-model="form.deliveryDate"
+          type="date"
+          placeholder="选择日期"
+        />
       </div>
       <div class="form-bos">
         <div class="form-title flex-row-start">
           <div class="asterisk">*</div>
           <div>费用类型</div>
         </div>
-        <el-select v-model="form.value2" placeholder="请选择费用类型" style="width: 340px">
+        <el-select v-model="form.expenseType" placeholder="请选择费用类型" style="width: 340px">
           <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
         </el-select>
       </div>
@@ -45,7 +58,7 @@
         </div>
         <el-input
           :maxlength="50"
-          v-model="form.value3"
+          v-model="form.purchaseReason"
           style="width: 340px"
           :autosize="{ minRows: 2, maxRows: 4 }"
           type="textarea"
@@ -60,7 +73,7 @@
         </div>
         <el-input
           :maxlength="50"
-          v-model="form.value3"
+          v-model="form.remark"
           style="width: 340px"
           :autosize="{ minRows: 2, maxRows: 4 }"
           type="textarea"
@@ -77,38 +90,27 @@
           fontWeight: 'normal'
         }"
       >
-        <el-table-column label="商品信息" width="490">
+        <el-table-column label="商品信息" minWidth="650">
           <template #default="scope">
             <div class="cart-info">
-              <img class="cart-img" src="@/assets/images/login-background.jpg" alt="" />
+              <img class="cart-img" :src="scope.row.productImage" alt="" />
               <div class="cart-text">
-                <div class="text1">清华同方超越E500台式机电脑超越E500台式机电脑(i3-6100/4G/1T/19.5寸)</div>
+                <div class="text1">{{ scope.row.itemName }}</div>
                 <div class="text2">
-                  <span>规格01</span>
-                  <span>规格02</span>
+                  <span>单位:{{ scope.row.unitName }}</span>
                 </div>
               </div>
             </div>
           </template>
         </el-table-column>
-        <el-table-column label="单价" width="150">
-          <template #default="scope"> ¥1,299 </template>
-        </el-table-column>
-        <el-table-column label="数量" width="160">
-          <template #default="scope"> 1 </template>
+        <el-table-column label="单价" minWidth="150">
+          <template #default="scope"> ¥{{ scope.row.memberPrice }} </template>
         </el-table-column>
-        <el-table-column label="小计" width="160">
-          <template #default="scope"> ¥1,299 </template>
+        <el-table-column label="数量" minWidth="150">
+          <template #default="scope"> {{ scope.row.productNum }} </template>
         </el-table-column>
-        <el-table-column label="操作">
-          <template #default="scope">
-            <div>
-              <el-button link> 移入收藏 </el-button>
-            </div>
-            <div>
-              <el-button link> 删除 </el-button>
-            </div>
-          </template>
+        <el-table-column label="小计" minWidth="150">
+          <template #default="scope"> ¥{{ (scope.row.memberPrice * scope.row.productNum).toFixed(2) }} </template>
         </el-table-column>
       </el-table>
     </div>
@@ -118,25 +120,25 @@
         <div class="foot-box flex-column-between">
           <div class="flex-row-between" style="width: 100%">
             <div>商品件数</div>
-            <div>6</div>
+            <div>{{ allNum }}</div>
           </div>
           <div class="flex-row-between" style="width: 100%">
             <div>商品总额</div>
-            <div>¥1,299</div>
+            <div>¥{{ allMoney }}</div>
           </div>
           <div class="foot-yun flex-row-between">
             <div>运费</div>
-            <div>¥48</div>
+            <div>¥0.00</div>
           </div>
           <div class="flex-row-between" style="width: 100%">
             <div>共计</div>
-            <div class="zhu">¥1,299</div>
+            <div class="zhu">¥{{ allMoney }}</div>
           </div>
           <div class="flex-row-between" style="width: 100%">
             <div></div>
             <div class="bnt-bos">
               <el-button class="bnt1">返回购物车修改</el-button>
-              <el-button class="bnt2" type="primary">提交订单</el-button>
+              <el-button @click="onSubmit" class="bnt2" type="primary">提交订单</el-button>
             </div>
           </div>
         </div>
@@ -146,35 +148,89 @@
 </template>
 
 <script setup lang="ts">
+import { getAddressList } from '@/api/pc/enterprise';
+import { shoppingCartList, pcOrdersubmit } from '@/api/goods/index';
+import { onPath } from '@/utils/siteConfig';
+const route = useRoute();
+const ids = ref<any>('');
+const tableData = ref<any>([]);
+const addressList = ref([]);
+const allNum = ref(0);
+const allMoney = ref<any>(0);
 const form = ref<any>({
-  value1: '',
-  value2: '',
-  value3: '',
-  value4: ''
+  shippingAddressId: '',
+  deliveryDate: '',
+  expenseType: '0',
+  purchaseReason: '',
+  remark: '',
+  shippingFee: 0,
+  productShoppingCartId: []
 });
-const tableData = ref<any>([{}, {}, {}, {}]);
 const options = [
   {
-    value: 'Option1',
-    label: 'Option1'
-  },
-  {
-    value: 'Option2',
-    label: 'Option2'
-  },
-  {
-    value: 'Option3',
-    label: 'Option3'
-  },
-  {
-    value: 'Option4',
-    label: 'Option4'
-  },
-  {
-    value: 'Option5',
-    label: 'Option5'
+    value: '0',
+    label: '日常物资采购'
   }
 ];
+
+onMounted(() => {
+  ids.value = route.query.ids;
+  form.value.productShoppingCartId = ids.value.split(',');
+  loadAddressList();
+  getCartList();
+});
+// 加载地址列表
+const loadAddressList = async () => {
+  try {
+    const res = await getAddressList();
+    if (res.code === 200) {
+      addressList.value = res.rows || [];
+      if (res.rows.length > 0) {
+        form.value.shippingAddressId = res.rows[0].id;
+      }
+    }
+  } catch (error) {
+    console.error('加载地址列表失败:', error);
+    ElMessage.error('加载地址列表失败');
+  }
+};
+
+//选择地址
+const onAddress = (res: any) => {
+  form.value.shippingAddressId = res.id;
+};
+
+//购物车
+const getCartList = () => {
+  const datas = { id: ids.value };
+  shoppingCartList(datas).then((res) => {
+    if (res.code == 200) {
+      tableData.value = res.rows;
+      res.rows.forEach((item: any) => {
+        allNum.value = allNum.value + Number(item.productNum);
+        allMoney.value = allMoney.value + Number(item.memberPrice * item.productNum);
+      });
+      allMoney.value = allMoney.value.toFixed(2);
+    }
+  });
+};
+
+const onSubmit = () => {
+  if (!form.value.deliveryDate) {
+    ElMessage.error('请选择配送时间');
+    return;
+  }
+  if (!form.value.purchaseReason) {
+    ElMessage.error('请输入采购事由');
+    return;
+  }
+  pcOrdersubmit(form.value).then((res) => {
+    if (res.code == 200) {
+      onPath('/payc?id=' + res.data);
+    }
+  });
+  console.log(form.value);
+};
 </script>
 
 <style lang="scss" scoped>
@@ -282,7 +338,7 @@ const options = [
       }
     }
     .cart-info {
-      width: 490px;
+      // width: 490px;
       height: 94px;
       display: flex;
       .cart-img {