ソースを参照

Merge remote-tracking branch 'origin/master' into master

# Conflicts:
#	src/api/goods/index.ts
肖路 3 ヶ月 前
コミット
49db3c86df

+ 3 - 0
.env.development

@@ -34,3 +34,6 @@ VITE_APP_WEBSOCKET = false
 
 # sse 开关
 VITE_APP_SSE = true
+
+# 是否开启多域名
+VITE_DOMAIN_NAME = false

+ 3 - 0
.env.production

@@ -37,3 +37,6 @@ VITE_APP_WEBSOCKET = false
 
 # sse 开关
 VITE_APP_SSE = true
+
+# 是否开启多域名
+VITE_DOMAIN_NAME = false

+ 1 - 18
package.json

@@ -7,24 +7,7 @@
   "license": "MIT",
   "type": "module",
   "scripts": {
-    "dev:www": "vite --port 5101",
-    "dev:b": "vite --port 5102",
-    "dev:mro": "vite --port 5103",
-    "dev:fuli": "vite --port 5104",
-    "dev:reg": "vite --port 5105",
-    "dev:breg": "vite --port 5106",
-    "dev:greg": "vite --port 5107",
-    "dev:passport": "vite --port 5108",
-    "dev:search": "vite --port 5109",
-    "dev:item": "vite --port 5110",
-    "dev:cart": "vite --port 5111",
-    "dev:trad": "vite --port 5112",
-    "dev:payc": "vite --port 5113",
-    "dev:order": "vite --port 5114",
-    "dev:plan": "vite --port 5115",
-    "dev:plan_info": "vite --port 5116",
-    "dev:i": "vite --port 5117",
-    "dev:easybuv": "vite --port 5118",
+    "dev": "vite serve --mode development",
     "build:prod": "vite build --mode production",
     "build:dev": "vite build --mode development",
     "preview": "vite preview",

+ 8 - 0
src/api/goods/index.ts

@@ -142,3 +142,11 @@ export function addProcurementProgramCollect(data: any) {
     data: data
   });
 }
+//购物车
+export const getProductShoppingCartCount = (query: any) => {
+  return request({
+    url: '/product/myProduct/getProductShoppingCartCount',
+    method: 'get',
+    params: query
+  });
+};

+ 11 - 0
src/api/pc/enterprise/index.ts

@@ -24,6 +24,17 @@ export function updateEnterpriseInfo(data: EnterpriseInfo) {
   });
 }
 
+/**
+ * 修改密码
+ */
+export function changePwd(data: any) {
+  return request({
+    url: '/system/psSysUser/changePwd', // 密码修改
+    method: 'put',
+    data: data
+  });
+}
+
 // ==================== 收货地址管理 ====================
 
 /**

+ 7 - 0
src/api/pc/enterprise/order.ts

@@ -143,6 +143,13 @@ export function addOrderEvaluation(data: any) {
   });
 }
 
+export function getOrderEvaluation(id: number) {
+  return request({
+    url: `/order/pcOrderEvaluation/${id}`,
+    method: 'get'
+  });
+}
+
 // ==================== 订单流程管理 ====================
 
 /**

+ 9 - 4
src/layout/components/search.vue

@@ -13,10 +13,12 @@
               </el-icon>
             </div>
           </div>
-          <div class="cat-bos flex-row-center" @click="onPath('/cart')">
-            <img src="@/assets/images/layout/layout4.png" alt="" />
-            <span>我的购物车</span>
-          </div>
+          <el-badge :value="cartCount">
+            <div class="cat-bos flex-row-center" @click="onPath('/cart')">
+              <img src="@/assets/images/layout/layout4.png" alt="" />
+              <span>我的购物车</span>
+            </div>
+          </el-badge>
         </div>
         <div class="search-text">
           <div>家纺</div>
@@ -35,6 +37,9 @@
 
 <script setup lang="ts">
 import { onPath } from '@/utils/siteConfig';
+import { cartStore } from '@/store/modules/cart';
+const cartStoreData = cartStore();
+const cartCount = computed(() => cartStoreData.cartCount);
 const input = ref<any>('');
 const route = useRoute();
 const meta = ref<any>({});

+ 48 - 18
src/permission.ts

@@ -7,20 +7,38 @@ import { isPathMatch } from '@/utils/validate';
 import { useUserStore } from '@/store/modules/user';
 import { ElMessage } from 'element-plus/es';
 import { getCurrentSite, SITE_ROUTES } from '@/utils/siteConfig';
+import { cartStore } from '@/store/modules/cart';
 
 NProgress.configure({ showSpinner: false });
-const whiteList = ['/login', '/register', '/social-callback', '/register*', '/register/*', '/index', '/'];
+const whiteList = [
+  '/login',
+  '/register',
+  '/social-callback',
+  '/register*',
+  '/register/*',
+  '/index',
+  '/',
+  '/indexB',
+  '/indexMro',
+  '/indexFuli',
+  '/reg',
+  '/search',
+  '/item'
+];
 
 const isWhiteList = (path: string) => {
   return whiteList.some((pattern) => isPathMatch(pattern, path));
 };
 
 // 获取主站完整 URL(用于跨域跳转)
-function getMainSiteUrl(path: any) {
+function getMainSiteUrl(path: string) {
   if (import.meta.env.PROD) {
-    return `https://www.yoe365.com${path}`;
+    return `https://www.yingpai365.com${path}`;
   } else {
-    return `http://localhost:5101${path}`;
+    // 本地开发:指向 www.yingpai365.com 加上当前运行的端口
+    // 假设你启动 vite 后访问的是 http://www.yingpai365.com
+    const devPort = window.location.port || import.meta.env.VITE_APP_PORT;
+    return `http://www.yingpai365.com:${devPort}${path}`;
   }
 }
 
@@ -28,36 +46,48 @@ router.beforeEach(async (to, from, next) => {
   NProgress.start();
   const site = getCurrentSite();
   const allowedPaths = SITE_ROUTES[site];
-  const host = window.location.hostname;
-  const port = window.location.port;
+
   if (getToken()) {
     const [err] = await tos(useUserStore().getInfo());
     if (err) {
       await useUserStore().logout();
       ElMessage.error(err);
-      window.location.href = getMainSiteUrl('/index');
+      if (import.meta.env.VITE_DOMAIN_NAME == 'true') {
+        window.location.href = getMainSiteUrl('/login');
+      } else {
+        next('/login');
+      }
       NProgress.done();
     } else {
-      if (!allowedPaths.includes(to.path)) {
-        console.warn(`[${site}] 禁止访问 ${to.path}`);
-        window.location.href = getMainSiteUrl('/index');
-        NProgress.done();
+      cartStore().onCartCount();
+      // 是否开启多域名
+      if (import.meta.env.VITE_DOMAIN_NAME == 'true') {
+        if (!allowedPaths.includes(to.path)) {
+          console.warn(`[${site}] 禁止访问 ${to.path}`);
+          window.location.href = getMainSiteUrl('/index');
+          NProgress.done();
+        } else {
+          next();
+          NProgress.done();
+        }
       } else {
         next();
         NProgress.done();
       }
     }
   } else {
-    // 没有token
+    // 没有 token
     if (isWhiteList(to.path)) {
-      if (host == 'www.yoe365.com' || port == '5101') {
-        next();
-      } else {
-        window.location.href = getMainSiteUrl(to.path);
-      }
+      next();
       NProgress.done();
     } else {
-      window.location.href = getMainSiteUrl('/index');
+      // 非白名单且无 token,强制去登录
+      if (import.meta.env.VITE_DOMAIN_NAME == 'true') {
+        window.location.href = getMainSiteUrl('/login');
+      } else {
+        next('/login');
+      }
+      // 或者 '/login' 根据你的白名单设置
       NProgress.done();
     }
   }

+ 6 - 0
src/router/index.ts

@@ -296,6 +296,12 @@ export const constantRoutes: RouteRecordRaw[] = [
         component: () => import('@/views/enterprise/purchaseHabit/index.vue'),
         meta: { title: '采购习惯', hidden: true, workbench: true }
       },
+      {
+        path: 'enterprise/changePerson',
+        name: 'PurchaseHabit',
+        component: () => import('@/views/enterprise/changePerson/index.vue'),
+        meta: { title: '更换负责人', hidden: true, workbench: true }
+      },
       {
         path: 'enterprise/messageNotice',
         name: 'MessageNotice',

+ 18 - 0
src/store/modules/cart.ts

@@ -0,0 +1,18 @@
+import { getProductShoppingCartCount } from '@/api/goods/index';
+
+export const cartStore = defineStore('cart', () => {
+  const cartCount = ref<any>(0);
+
+  const onCartCount = () => {
+    getProductShoppingCartCount({}).then((res) => {
+      if (res.code == 200) {
+        cartCount.value = res.data;
+      }
+    });
+  };
+
+  return {
+    cartCount,
+    onCartCount
+  };
+});

+ 1 - 0
src/types/env.d.ts

@@ -30,6 +30,7 @@ interface ImportMetaEnv {
   VITE_APP_CLIENT_ID: string;
   VITE_APP_WEBSOCKET: string;
   VITE_APP_SSE: string;
+  VITE_DOMAIN_NAME: string;
 }
 interface ImportMeta {
   readonly env: ImportMetaEnv;

+ 19 - 13
src/utils/request.ts

@@ -9,8 +9,20 @@ import { LoadingInstance } from 'element-plus/es/components/loading/src/loading'
 import FileSaver from 'file-saver';
 import { encryptBase64, encryptWithAes, generateAesKey, decryptWithAes, decryptBase64 } from '@/utils/crypto';
 import { encrypt, decrypt } from '@/utils/jsencrypt';
+import { onPath } from '@/utils/siteConfig';
 import router from '@/router';
-import { getApiBase } from '@/utils/siteConfig';
+
+// 获取主站完整 URL(用于跨域跳转)
+function getMainSiteUrl(path: string) {
+  if (import.meta.env.PROD) {
+    return `https://www.yingpai365.com${path}`;
+  } else {
+    // 本地开发:指向 www.yingpai365.com 加上当前运行的端口
+    // 假设你启动 vite 后访问的是 http://www.yingpai365.com
+    const devPort = window.location.port || import.meta.env.VITE_APP_PORT;
+    return `http://www.yingpai365.com:${devPort}${path}`;
+  }
+}
 
 const encryptHeader = 'encrypt-key';
 let downloadLoadingInstance: LoadingInstance;
@@ -27,8 +39,7 @@ axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8';
 axios.defaults.headers['clientid'] = import.meta.env.VITE_APP_CLIENT_ID;
 // 创建 axios 实例
 const service = axios.create({
-  // baseURL: import.meta.env.VITE_APP_BASE_API,
-  baseURL: getApiBase(),
+  baseURL: import.meta.env.VITE_APP_BASE_API,
   // withCredentials: true,
   timeout: 50000,
   transitional: {
@@ -37,15 +48,6 @@ const service = axios.create({
   }
 });
 
-// 获取主站完整 URL(用于跨域跳转)
-function getMainSiteUrl(path: any) {
-  if (import.meta.env.PROD) {
-    return `https://www.yoe365.com${path}`;
-  } else {
-    return `http://localhost:5101${path}`;
-  }
-}
-
 // 请求拦截器
 service.interceptors.request.use(
   (config: InternalAxiosRequestConfig) => {
@@ -163,7 +165,11 @@ service.interceptors.response.use(
       // });
       // }
       useUserStore().logout().then(() => {
-        window.location.href = getMainSiteUrl('/index');
+        if (import.meta.env.VITE_DOMAIN_NAME == 'true') {
+          window.location.href = getMainSiteUrl('/login');
+        }else{
+          router.push('/login');
+        }
       });
       return Promise.reject('无效的会话,或者会话已过期,请重新登录。');
     } else if (code === HttpStatus.SERVER_ERROR) {

+ 90 - 136
src/utils/siteConfig.ts

@@ -1,28 +1,4 @@
-// src/utils/site.ts
-
-// 开发环境:端口 → 站点
-const DEV_PORT_MAP: Record<string, any> = {
-  '5101': 'www',
-  '5102': 'b',
-  '5103': 'mro',
-  '5104': 'fuli',
-  '5105': 'reg',
-  '5106': 'breg',
-  '5107': 'greg',
-  '5108': 'passport',
-  '5109': 'search',
-  '5110': 'item',
-  '5111': 'cart',
-  '5112': 'trad',
-  '5113': 'payc',
-  '5114': 'order',
-  '5115': 'plan',
-  '5116': 'plan_info',
-  '5117': 'i',
-  '5118': 'easybuv'
-};
-
-// 每个站点允许的路由
+// 每个站点允许的路由 (保持不变)
 export const SITE_ROUTES: Record<any, string[]> = {
   www: ['/', '/index'], //优易365主站
   b: ['/indexB'], //企业购商城
@@ -78,144 +54,122 @@ export const SITE_ROUTES: Record<any, string[]> = {
     '/valueAdded/maintenanceApply',
     '/enterprise/messageNotice',
     '/enterprise/securitySetting',
-    '/enterprise/securitySetting/resetPassword'
+    '/enterprise/securitySetting/resetPassword',
+    '/enterprise/securitySetting/changePhone',
+    '/enterprise/changePerson'
   ], //订单列表
 
   i: ['/i'], //个人信息
   easybuv: ['/easybuv'] //地址管理
 };
 
-// 获取当前站点(开发用端口,线上用域名)
+// 获取当前站点
 export function getCurrentSite(): any {
-  if (import.meta.env.PROD) {
-    // 线上:根据域名判断
-    const host = window.location.hostname;
-    if (host === 'b.yoe365.com') return 'b';
-    if (host === 'mro.yoe365.com') return 'mro';
-    if (host === 'mro.yoe365.com') return 'fuli';
-    if (host === 'mro.yoe365.com') return 'reg';
-    if (host === 'mro.yoe365.com') return 'breg';
-    if (host === 'mro.yoe365.com') return 'greg';
-    if (host === 'mro.yoe365.com') return 'passport';
-    if (host === 'mro.yoe365.com') return 'search';
-    if (host === 'mro.yoe365.com') return 'item';
-    if (host === 'mro.yoe365.com') return 'cart';
-    if (host === 'mro.yoe365.com') return 'trad';
-    if (host === 'mro.yoe365.com') return 'payc';
-    if (host === 'mro.yoe365.com') return 'order';
-    if (host === 'mro.yoe365.com') return 'plan';
-    if (host === 'mro.yoe365.com') return 'plan_info';
-    if (host === 'mro.yoe365.com') return 'i';
-    if (host === 'mro.yoe365.com') return 'easybuv';
-    return 'www';
-  }
+  // 无论是生产还是开发,现在都统一通过域名判断
+  const host = window.location.hostname;
 
-  // 本地:根据端口判断
-  const port = window.location.port || '80';
-  return DEV_PORT_MAP[port] || 'www';
-}
+  // 定义本地开发环境的域名映射关系
+  // 确保你的 hosts 文件已经配置了这些域名指向 127.0.0.1
+  if (host === 'www.yingpai365.com' || host === 'localhost') return 'www'; // 兼容未配hosts的情况
+  if (host === 'b.yingpai365.com') return 'b';
+  if (host === 'mro.yingpai365.com') return 'mro';
+  if (host === 'fuli.yingpai365.com') return 'fuli';
+  if (host === 'reg.yingpai365.com') return 'reg';
+  if (host === 'breg.yingpai365.com') return 'breg';
+  if (host === 'greg.yingpai365.com') return 'greg';
+  if (host === 'passport.yingpai365.com') return 'passport';
+  if (host === 'search.yingpai365.com') return 'search';
+  if (host === 'item.yingpai365.com') return 'item';
+  if (host === 'cart.yingpai365.com') return 'cart';
+  if (host === 'trad.yingpai365.com') return 'trad';
+  if (host === 'payc.yingpai365.com') return 'payc';
+  if (host === 'order.yingpai365.com') return 'order';
+  if (host === 'plan.yingpai365.com') return 'plan';
+  if (host === 'plan_info.yingpai365.com') return 'plan_info';
+  if (host === 'i.yingpai365.com') return 'i';
+  if (host === 'easybuv.yingpai365.com') return 'easybuv';
 
-// 根据站点返回 API 基地址
-
-export function getApiBase() {
-  const site = getCurrentSite();
-  const map: Record<any, string> = {
-    www: 'https://www.yoe365.com',
-    b: 'https://b.yoe365.com',
-    mro: 'https://mro.yoe365.com',
-    fuli: 'https://fuli.yoe365.com',
-    reg: 'https://reg.yoe365.com',
-    breg: 'https://breg.yoe365.com',
-    greg: 'https://greg.yoe365.com',
-    passport: 'https://passport.yoe365.com',
-    search: 'https://search.yoe365.com',
-    item: 'https://item.yoe365.com',
-    cart: 'https://cart.yoe365.com',
-    trad: 'https://trad.yoe365.com',
-    payc: 'https://payc.yoe365.com',
-    order: 'https://order.yoe365.com',
-    plan: 'https://plan.yoe365.com',
-    plan_info: 'https://plan_info.yoe365.com',
-    i: 'https://i.yoe365.com',
-    easybuv: 'https://easybuv.yoe365.com'
-  };
+  // 生产环境逻辑 (保持不变,或者合并到上面的判断中)
   if (import.meta.env.PROD) {
-    return map[site];
-  } else {
-    // return '/dev-api'
-    // return 'http://192.168.1.52:8080';
-    // return 'https://ceshi.xiaoluwebsite.xyz';
-    return 'http://localhost:8080';
+    // 如果上面没匹配到,且是生产环境,可以尝试原有的逻辑或默认返回 www
+    // 这里建议直接复用上面的 hostname 判断,因为生产环境也是域名
+    return 'www';
   }
+
+  return 'www'; // 默认 fallback
 }
 
+// ... PATH_TO_SITE_MAP 和 getSiteByPath 保持不变 ...
 const PATH_TO_SITE_MAP: Record<string, any> = {};
 for (const [site, paths] of Object.entries(SITE_ROUTES)) {
   for (const path of paths) {
     PATH_TO_SITE_MAP[path] = site as any;
   }
 }
-
 export function getSiteByPath(path: string): any | null {
-  // 支持带查询参数(如 /login?redirect=xxx)
   const cleanPath = path.split('?')[0];
   return PATH_TO_SITE_MAP[cleanPath] || null;
 }
+
+// 跨站跳转逻辑
+import router from '@/router';
 export function onPath(path: string) {
-  const targetSite = getSiteByPath(path);
-  if (!targetSite) {
-    // window.open(url, '_blank');
-    console.error(`[跨站跳转失败] 路径 "${path}" 未关联任何站点`);
-    return;
-  }
+  console.log('[跨站跳转]', path);
+  // return
+  if (import.meta.env.VITE_DOMAIN_NAME == 'true') {
+    const targetSite = getSiteByPath(path);
 
-  let url = '';
+    if (!targetSite) {
+      console.error(`[跨站跳转失败] 路径 "${path}" 未关联任何站点`);
+      return;
+    }
 
-  if (import.meta.env.PROD) {
-    const domainMap: Record<any, string> = {
-      www: 'https://www.yoe365.com',
-      b: 'https://b.yoe365.com',
-      mro: 'https://mro.yoe365.com',
-      fuli: 'https://fuli.yoe365.com',
-      reg: 'https://reg.yoe365.com',
-      breg: 'https://breg.yoe365.com',
-      greg: 'https://greg.yoe365.com',
-      passport: 'https://passport.yoe365.com',
-      search: 'https://search.yoe365.com',
-      item: 'https://item.yoe365.com',
-      cart: 'https://cart.yoe365.com',
-      trad: 'https://trad.yoe365.com',
-      payc: 'https://payc.yoe365.com',
-      order: 'https://order.yoe365.com',
-      plan: 'https://plan.yoe365.com',
-      plan_info: 'https://plan_info.yoe365.com',
-      i: 'https://i.yoe365.com',
-      easybuv: 'https://easybuv.yoe365.com'
+    const currentSite = getCurrentSite();
+
+    // 【新增】判断是否是同域名
+    const isSameSite = currentSite === targetSite;
+
+    let url = '';
+    // 域名映射表 (保持不变)
+    const domainMap: Record<string, string> = {
+      www: 'www.yingpai365.com',
+      b: 'b.yingpai365.com',
+      mro: 'mro.yingpai365.com',
+      fuli: 'fuli.yingpai365.com',
+      reg: 'reg.yingpai365.com',
+      breg: 'breg.yingpai365.com',
+      greg: 'greg.yingpai365.com',
+      passport: 'passport.yingpai365.com',
+      search: 'search.yingpai365.com',
+      item: 'item.yingpai365.com',
+      cart: 'cart.yingpai365.com',
+      trad: 'trad.yingpai365.com',
+      payc: 'payc.yingpai365.com',
+      order: 'order.yingpai365.com',
+      plan: 'plan.yingpai365.com',
+      plan_info: 'plan_info.yingpai365.com',
+      i: 'i.yingpai365.com',
+      easybuv: 'easybuv.yingpai365.com'
     };
-    url = `${domainMap[targetSite]}${path}`;
+
+    const baseDomain = domainMap[targetSite];
+
+    if (import.meta.env.PROD) {
+      url = `https://${baseDomain}${path}`;
+    } else {
+      const devPort = window.location.port || import.meta.env.VITE_APP_PORT;
+      url = `http://${baseDomain}:${devPort}${path}`;
+    }
+
+    // 【修改】根据是否同域名决定跳转方式
+    if (isSameSite) {
+      // 同域名且传入了 router,使用 Vue Router 内部跳转
+      router.push(path);
+    } else {
+      // 跨域名 或 未传入 router,使用 window.open 打开新窗口
+      window.open(url, '_blank');
+    }
   } else {
-    const portMap: Record<any, string> = {
-      www: 'http://localhost:5101',
-      b: 'http://localhost:5102',
-      mro: 'http://localhost:5103',
-      fuli: 'http://localhost:5104',
-      reg: 'http://localhost:5105',
-      breg: 'http://localhost:5106',
-      greg: 'http://localhost:5107',
-      passport: 'http://localhost:5108',
-      search: 'http://localhost:5109',
-      item: 'http://localhost:5110',
-      cart: 'http://localhost:5111',
-      trad: 'http://localhost:5112',
-      payc: 'http://localhost:5113',
-      order: 'http://localhost:5114',
-      plan: 'http://localhost:5115',
-      plan_info: 'http://localhost:5116',
-      i: 'http://localhost:5117',
-      easybuv: 'http://localhost:5118'
-    };
-    url = `${portMap[targetSite]}${path}`;
+    router.push(path);
   }
-
-  window.open(url, '_blank');
 }

+ 2 - 2
src/views/cart/index.vue

@@ -41,7 +41,7 @@
           </template>
         </el-table-column>
         <el-table-column label="小计" width="140">
-          <template #default="scope"> ¥{{ scope.row.memberPrice * scope.row.productNum }} </template>
+          <template #default="scope"> ¥{{ (scope.row.memberPrice * scope.row.productNum).toFixed(2) }} </template>
         </el-table-column>
         <el-table-column label="操作">
           <template #default="scope">
@@ -91,7 +91,7 @@
           </template>
         </el-table-column>
         <el-table-column label="小计" width="140" align="center">
-          <template #default="scope"> ¥{{ scope.row.memberPrice * scope.row.productNum }} </template>
+          <template #default="scope"> ¥{{ (scope.row.memberPrice * scope.row.productNum).toFixed(2) }} </template>
         </el-table-column>
         <el-table-column label="操作">
           <template #default="scope">

+ 368 - 0
src/views/enterprise/changePerson/index.vue

@@ -0,0 +1,368 @@
+<template>
+  <div class="change-person-container">
+    <div class="change-content">
+      <!-- 头部标题 -->
+      <div class="page-header">
+        <div class="page-title">变更采购负责人</div>
+      </div>
+
+      <!-- 步骤条 -->
+      <div class="steps-container">
+        <!-- 步骤1 -->
+        <div class="step-item" :class="{ active: currentStep >= 1 }">
+          <div class="step-circle">
+            <el-icon v-if="currentStep >= 1"><Check /></el-icon>
+            <span v-else>1</span>
+          </div>
+          <div class="step-label">验证身份</div>
+        </div>
+        <div class="step-line" :class="{ active: currentStep > 1 }"></div>
+
+        <!-- 步骤2 -->
+        <div class="step-item" :class="{ active: currentStep >= 2 }">
+          <div class="step-circle">
+            <el-icon v-if="currentStep > 2"><Check /></el-icon>
+            <span v-else>2</span>
+          </div>
+          <div class="step-label">选择人员</div>
+        </div>
+        <div class="step-line" :class="{ active: currentStep > 2 }"></div>
+
+        <!-- 步骤3 -->
+        <div class="step-item" :class="{ active: currentStep >= 3 }">
+          <div class="step-circle">
+            <span v-if="currentStep < 3">3</span>
+            <el-icon v-else><Check /></el-icon>
+          </div>
+          <div class="step-label">完成</div>
+        </div>
+      </div>
+
+      <!-- 步骤1:验证身份内容 -->
+      <div class="step-content" v-if="currentStep === 1">
+        <el-form ref="step1FormRef" :model="step1Form" label-width="120px" class="verify-form">
+          <el-form-item label="手机号码:">
+            <div class="form-item-wrapper">
+              <el-input v-model="step1Form.phone" placeholder="请输入手机号码" class="form-input" />
+              <span class="form-tip">若该手机号已无法使用请联系客服</span>
+            </div>
+          </el-form-item>
+
+          <el-form-item label="验证码:">
+            <div class="form-item-wrapper">
+              <el-input v-model="step1Form.code" placeholder="短信验证码" class="form-input code-input">
+                <template #suffix>
+                  <el-button link class="send-code-btn" :disabled="countdown > 0" @click="handleSendCode">
+                    {{ countdown > 0 ? `${countdown}s后发送` : '发送验证码' }}
+                  </el-button>
+                </template>
+              </el-input>
+            </div>
+          </el-form-item>
+
+          <el-form-item label=" ">
+            <div class="captcha-box">
+              <el-radio v-model="step1Form.verified" :label="true" class="captcha-radio">点击验证</el-radio>
+            </div>
+          </el-form-item>
+
+          <el-form-item label=" " class="action-item">
+            <el-button type="primary" class="next-btn" @click="handleNextStep">下一步</el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+
+      <!-- 步骤2:选择人员内容 (模拟) -->
+      <div class="step-content" v-if="currentStep === 2">
+        <el-form label-width="120px" class="verify-form">
+          <el-form-item label="选择新负责人:">
+            <el-select v-model="step2Form.person" placeholder="请选择新采购负责人" class="form-input">
+              <el-option label="张三" value="zhangsan" />
+              <el-option label="李四" value="lisi" />
+            </el-select>
+          </el-form-item>
+          <el-form-item label=" " class="action-item">
+            <el-button @click="currentStep = 1">上一步</el-button>
+            <el-button type="primary" class="next-btn" @click="currentStep = 3" style="width: auto; padding: 0 40px">提交</el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+
+      <!-- 步骤3:完成内容 (模拟) -->
+      <div class="step-content" v-if="currentStep === 3">
+        <div class="success-content">
+          <el-icon class="success-icon" color="#e60012" :size="80"><CircleCheckFilled /></el-icon>
+          <div class="success-title">负责人变更成功!</div>
+          <el-button type="primary" class="next-btn" style="margin-top: 40px; width: 200px" @click="currentStep = 1">返回</el-button>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, reactive } from 'vue';
+import { Check, CircleCheckFilled } from '@element-plus/icons-vue';
+import { ElMessage } from 'element-plus';
+
+const currentStep = ref(1);
+
+const step1Form = reactive({
+  phone: '',
+  code: '',
+  verified: false
+});
+
+const step2Form = reactive({
+  person: ''
+});
+
+const countdown = ref(0);
+
+// 发送验证码模拟方法
+const handleSendCode = () => {
+  if (!step1Form.phone) {
+    ElMessage.warning('请输入手机号码');
+    return;
+  }
+  countdown.value = 60;
+  const timer = setInterval(() => {
+    countdown.value--;
+    if (countdown.value <= 0) {
+      clearInterval(timer);
+    }
+  }, 1000);
+  ElMessage.success('验证码已发送');
+};
+
+const handleNextStep = () => {
+  if (!step1Form.phone || !step1Form.code) {
+    ElMessage.warning('请填写完整的手机号和验证码');
+    return;
+  }
+  if (!step1Form.verified) {
+    ElMessage.warning('请完成点击验证');
+    return;
+  }
+  currentStep.value = 2;
+};
+</script>
+
+<style scoped lang="scss">
+.change-person-container {
+  background: #f4f5f5;
+  min-height: 100%;
+  padding: 0px;
+  flex: 1;
+}
+
+.change-content {
+  background: #fff;
+  border-radius: 4px;
+  min-height: calc(100vh - 40px);
+  margin: 0 auto;
+  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
+
+  .page-header {
+    border-bottom: 1px solid #f0f0f0;
+    padding: 24px 30px;
+
+    .page-title {
+      font-size: 16px;
+      color: #333;
+      font-weight: 500;
+    }
+  }
+}
+
+.steps-container {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin: 60px auto 70px;
+  max-width: 650px;
+}
+
+.step-item {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  position: relative;
+  width: 80px;
+
+  .step-circle {
+    width: 48px;
+    height: 48px;
+    border-radius: 50%;
+    border: 2px solid #ddd;
+    background: #fff;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-size: 20px;
+    color: #ccc;
+    margin-bottom: 12px;
+    font-weight: 500;
+    transition: all 0.3s;
+  }
+
+  .step-label {
+    font-size: 14px;
+    color: #999;
+    transition: all 0.3s;
+  }
+
+  &.active {
+    .step-circle {
+      border-color: #e60012;
+      color: #e60012;
+    }
+    .step-label {
+      color: #e60012;
+      font-weight: 500;
+    }
+  }
+}
+
+.step-line {
+  flex: 1;
+  height: 2px;
+  background: #ddd;
+  margin: 0 10px;
+  margin-bottom: 30px; /* 居中对齐横线与圆圈中心 */
+  transition: all 0.3s;
+
+  &.active {
+    background: #e60012;
+  }
+}
+
+.step-content {
+  display: flex;
+  justify-content: center;
+  padding-bottom: 100px;
+}
+
+.verify-form {
+  width: 550px;
+
+  :deep(.el-form-item__label) {
+    font-size: 14px;
+    color: #333;
+    font-weight: normal;
+  }
+
+  .form-item-wrapper {
+    display: flex;
+    align-items: center;
+    width: 100%;
+    gap: 15px;
+
+    .form-input {
+      width: 320px;
+
+      :deep(.el-input__wrapper) {
+        box-shadow: 0 0 0 1px #dcdfe6 inset;
+        border-radius: 2px;
+        background-color: #f7f9fb;
+        &.is-focus {
+          box-shadow: 0 0 0 1px #e60012 inset !important;
+        }
+      }
+
+      :deep(.el-input__inner) {
+        height: 38px;
+      }
+    }
+
+    .form-tip {
+      font-size: 12px;
+      color: #999;
+      white-space: nowrap;
+    }
+  }
+
+  .send-code-btn {
+    color: #e60012;
+    font-size: 14px;
+    font-weight: 500;
+
+    &:hover {
+      color: #159c81;
+    }
+    &.is-disabled {
+      color: #999;
+    }
+  }
+
+  .captcha-box {
+    width: 320px;
+    height: 42px;
+    background: #f4f6fb;
+    border: 1px solid #ccd6e8;
+    border-radius: 2px;
+    display: flex;
+    align-items: center;
+    padding-left: 20px;
+
+    .captcha-radio {
+      :deep(.el-radio__input.is-checked .el-radio__inner) {
+        border-color: #bbc7da;
+        background: #bbc7da;
+        &::after {
+          background-color: #6a82a7;
+          width: 6px;
+          height: 6px;
+        }
+      }
+      :deep(.el-radio__inner) {
+        width: 16px;
+        height: 16px;
+      }
+      :deep(.el-radio__label) {
+        color: #666;
+        font-size: 14px;
+      }
+    }
+  }
+
+  .action-item {
+    margin-top: 15px;
+  }
+
+  .next-btn {
+    width: 320px;
+    height: 40px;
+    background-color: #e60012;
+    border-color: #e60012;
+    border-radius: 2px;
+    font-size: 14px;
+  }
+}
+
+.success-content {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding-top: 50px;
+
+  .success-icon {
+    margin-bottom: 25px;
+  }
+
+  .success-title {
+    font-size: 18px;
+    color: #333;
+    font-weight: 500;
+  }
+
+  .next-btn {
+    background-color: #e60012;
+    border-color: #e60012;
+    &:hover {
+      background-color: #159c81;
+      border-color: #159c81;
+    }
+  }
+}
+</style>

+ 1 - 0
src/views/enterprise/companyInfo/index.vue

@@ -249,6 +249,7 @@ const handleTabClick = (tabKey: string) => {
   else if (tabKey === 'purchaseHabit') router.push('/enterprise/purchaseHabit');
   else if (tabKey === 'invoice') router.push('/enterprise/invoiceManage');
   else if (tabKey === 'creditApply') router.push('/cost/quotaControl/apply');
+  else if (tabKey === 'changePerson') router.push('/enterprise/changePerson');
 };
 </script>
 

+ 267 - 183
src/views/enterprise/purchaseHistory/index.vue

@@ -2,46 +2,49 @@
   <div class="order-manage-container">
     <div class="page-title"><i class="title-bar"></i><span>历史购买</span></div>
     <!-- 搜索栏 -->
-    <div class="search-bar">
-      <el-input v-model="queryParams.keyword" placeholder="搜索订单号" style="width: 200px" clearable @keyup.enter="handleQuery">
-        <template #prefix
-          ><el-icon><Search /></el-icon
-        ></template>
-      </el-input>
-      <el-date-picker
-        v-model="queryParams.dateRange"
-        type="daterange"
-        range-separator="—"
-        start-placeholder="开始日期"
-        end-placeholder="结束日期"
-        style="width: 240px"
-      />
-      <el-button type="primary" @click="handleQuery">搜索</el-button>
-      <el-button @click="handleReset">重置</el-button>
+    <div class="flex-row-between">
+      <div class="flex-row-start">
+        <el-input v-model="queryParams.keyword" placeholder="搜索订单号" style="width: 260px" clearable @keyup.enter="handleQuery">
+          <template #prefix
+            ><el-icon><Search /></el-icon
+          ></template>
+        </el-input>
+        <el-date-picker
+          v-model="queryParams.dateRange"
+          type="daterange"
+          range-separator="—"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          style="width: 260px; margin-left: 10px"
+        />
+      </div>
+      <div>
+        <el-button type="primary" @click="handleQuery">搜索</el-button>
+        <el-button @click="handleReset">重置</el-button>
+      </div>
     </div>
-    <!-- 筛选栏 -->
-    <div class="filter-bar">
-      <span class="filter-label">下单部门</span>
-      <el-tree-select
-        v-model="queryParams.department"
-        style="width: 100px"
-        :data="deptList"
-        :props="{ value: 'deptId', label: 'deptName', children: 'children' }"
-        value-key="deptId"
-        placeholder="请选择"
-        check-strictly
-        :render-after-expand="false"
-        clearable
-      >
-      </el-tree-select>
-      <span class="filter-label">状态</span>
-      <el-select v-model="queryParams.status" placeholder="请选择" style="width: 100px" clearable>
-        <el-option v-for="dict in order_status" :key="dict.value" :label="dict.label" :value="dict.value" />
-      </el-select>
-      <span class="filter-label">支付方式</span>
-      <el-select v-model="queryParams.payType" placeholder="请选择" style="width: 100px" clearable
-        ><el-option v-for="dict in pay_method" :key="dict.value" :label="dict.label" :value="dict.value"
-      /></el-select>
+    <div class="flex-row-between" style="margin-top: 10px">
+      <div class="flex-row-start">
+        <el-tree-select
+          v-model="queryParams.department"
+          style="width: 160px"
+          :data="deptList"
+          :props="{ value: 'deptId', label: 'deptName', children: 'children' }"
+          value-key="deptId"
+          placeholder="下单部门"
+          check-strictly
+          :render-after-expand="false"
+          clearable
+        >
+        </el-tree-select>
+        <el-select v-model="queryParams.status" placeholder="状态" style="width: 160px; margin-left: 10px" clearable>
+          <el-option v-for="dict in order_status" :key="dict.value" :label="dict.label" :value="dict.value" />
+        </el-select>
+        <el-select v-model="queryParams.payType" placeholder="支付方式" style="width: 160px; margin-left: 10px" clearable
+          ><el-option v-for="dict in pay_method" :key="dict.value" :label="dict.label" :value="dict.value" />
+        </el-select>
+      </div>
+      <div class="flex-row-start"></div>
     </div>
     <!-- Tab切换 -->
     <div class="tab-bar">
@@ -54,20 +57,27 @@
     <!-- 订单列表 -->
     <div class="order-list">
       <div v-for="order in orderList" :key="order.id" class="order-card">
-        <div class="order-header">
-          <span class="order-time">{{ order.orderTime }}</span>
-          <span class="order-info">订单号:{{ order.orderNo }}</span>
-          <span class="order-info">下单人:{{ order.orderPerson }}</span>
-          <span class="order-info">部门:{{ order.department }}</span>
-          <el-button type="danger" size="small" @click="handleAddCart(order)">批量加入购物车</el-button>
-          <el-button type="primary" link class="expand-btn" @click="handleExpand(order)"
-            >{{ order.expanded ? '收起' : '展开' }} <el-icon><ArrowDown /></el-icon
-          ></el-button>
+        <div class="order-header flex-row-between">
+          <div class="flex-row-start" style="gap: 0 15px">
+            <el-checkbox style="margin: 2px 0px 0px 0" v-model="order.checked" @change="handleOrderCheck" />
+            <div>{{ order.orderTime }}</div>
+            <div>订单号:{{ order.orderNo }}</div>
+            <div>下单人:{{ order.orderPerson }}</div>
+            <div>部门:{{ order.department }}</div>
+          </div>
+          <div class="flex-row-start">
+            <div class="expand-btn" @click="handleAddCart(order)">批量加入购物车</div>
+            <div class="open-btn" v-if="order.products && order.products.length > 5" @click="handleExpand(order)">
+              <span style="margin-right: 5px"> {{ order.expanded ? '收起' : '展开' }}</span>
+              <el-icon v-if="order.expanded"><ArrowUp /></el-icon>
+              <el-icon v-else><ArrowDown /></el-icon>
+            </div>
+          </div>
         </div>
         <div v-if="order.countdown" class="countdown-bar">订单锁定剩余时间:{{ order.countdown }}</div>
         <div class="product-list">
-          <div v-for="(item, itemIndex) in order.expanded ? order.products : order.products.slice(0, 1)" :key="itemIndex" class="product-row">
-            <div class="product-cell product-info-cell">
+          <div v-for="(item, itemIndex) in order.expanded ? order.products : order.products.slice(0, 5)" :key="itemIndex" class="product-row">
+            <div class="product-info-cell">
               <div class="product-image">
                 <el-image :src="item.image" fit="contain"
                   ><template #error
@@ -76,39 +86,40 @@
                 ></el-image>
               </div>
               <div class="product-detail">
-                <div class="product-name">{{ item.name }}</div>
-                <div class="product-spec">{{ item.spec1 }} {{ item.spec2 }}</div>
+                <div class="product-name ellipsis">{{ item.name }}</div>
+                <div class="product-spec">{{ item.spec1 }} | {{ item.spec2 }}</div>
                 <div class="product-price">¥{{ item.price }}</div>
               </div>
               <div class="product-quantity">x{{ item.quantity }}</div>
             </div>
-            <div class="product-cell amount-cell" v-if="itemIndex === 0">
+            <div class="amount-cell" v-if="itemIndex === 0">
               <div class="amount-info">
-                <span class="label">支付款</span><span class="value highlight">¥{{ order.payAmount }}</span>
+                <span class="label">支付款</span><span class="value highlight">¥{{ order.payAmount }}</span>
               </div>
               <div class="amount-info">
                 <span class="label">含运费:</span><span class="value">¥{{ order.freight }}</span>
               </div>
             </div>
-            <!-- <div class="product-cell status-cell" v-if="itemIndex === 0">
-              <span class="status-text" :style="{ color: getStatusColor(order.status) }">{{ order.statusText }}</span>
-              <el-button type="primary" link size="small" @click="handleViewDetail(order)">查看订单轨迹</el-button>
-              <template v-if="order.auditStatus"
-                ><span :class="['audit-status', getAuditStatusClass(order.auditStatus)]">{{ order.auditStatus }}</span
-                ><el-button type="primary" link size="small">查看审批流</el-button></template
-              >
-              <el-button v-if="order.fileCount" type="primary" link size="small">审核文件({{ order.fileCount }})</el-button>
-            </div> -->
-            <div class="product-cell action-cell" v-if="itemIndex === 0">
-              <el-button type="primary" link size="small" @click="handleAddCart(order)">加入购物车</el-button>
+            <div v-else style="width: 200px"></div>
+            <div class="status-cell">
+              <el-button size="small" @click="handleAddCart(order)">加入购物车</el-button>
             </div>
           </div>
         </div>
+        <!-- 显示更多商品提示 -->
+        <div
+          v-if="!order.expanded && order.products && order.products.length > 5"
+          class="more-products-hint"
+          @click="handleExpand(order)"
+          style="cursor: pointer"
+        >
+          该订单共 {{ order.products.length }} 件商品,点击展开查看全部
+        </div>
       </div>
       <el-empty v-if="orderList.length === 0" description="暂无订单" />
     </div>
     <!-- 分页 -->
-    <TablePagination v-model:page="queryParams.pageNum" v-model:page-size="queryParams.pageSize" :total="total" @change="handleQuery" />
+    <TablePagination v-model:page="queryParams.pageNum" v-model:page-size="queryParams.pageSize" :total="total" @change="fetchOrderList" />
   </div>
 </template>
 
@@ -126,8 +137,8 @@ import { addProductShoppingCart } from '@/api/goods/index';
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { order_status, pay_method } = toRefs<any>(proxy?.useDict('order_status', 'pay_method'));
 
-const router = useRouter();
 const activeTab = ref('all');
+const selectAll = ref(false);
 const loading = ref(false);
 
 const deptList = ref([]);
@@ -159,7 +170,7 @@ watch(activeTab, (newTab) => {
   fetchOrderList();
 });
 
-const queryParams = reactive({ keyword: '', dateRange: null, department: '', status: '', payType: '', pageNum: 1, pageSize: 5 });
+const queryParams = reactive({ keyword: '', dateRange: [], department: '', status: '', payType: '', pageNum: 1, pageSize: 5 });
 const total = ref(0);
 const allOrders = ref<any[]>([]);
 
@@ -213,6 +224,35 @@ const loadDeptTree = async () => {
   }
 };
 
+/** 单个加入购物车 */
+const handleAddCart = async (order: any) => {
+  const res = await getOrderProducts([order.id]);
+  if (res.code === 200 && res.rows) {
+    const products = res.rows.map((p: any) => ({
+      productId: p.productId,
+      productNum: p.orderQuantity || 0
+    }));
+
+    const promises = products.map((item) => addProductShoppingCart({ productId: item.productId, productNum: item.productNum }));
+    Promise.all(promises).then(() => {
+      ElMessage.success(`已将${products.length}件商品加入购物车`);
+    });
+  }
+
+  // addProductShoppingCart({ productId: item.id, productNum: 1 }).then((res: any) => {
+  //   if (res.code == 200) {
+  //     ElMessage.success('已加入购物车');
+  //   }
+  // });
+};
+const formatDate = (date: Date | string | number): string => {
+  if (!date) return '';
+  const d = new Date(date);
+  const year = d.getFullYear();
+  const month = String(d.getMonth() + 1).padStart(2, '0');
+  const day = String(d.getDate()).padStart(2, '0');
+  return `${year}-${month}-${day}`;
+};
 // 获取订单列表
 const fetchOrderList = async () => {
   loading.value = true;
@@ -227,13 +267,54 @@ const fetchOrderList = async () => {
     if (queryParams.department) params.department = queryParams.department;
     if (queryParams.status) params.orderStatuses = queryParams.status; // 使用orderStatuses支持多状态查询
     if (queryParams.payType) params.payType = queryParams.payType;
-    if (queryParams.dateRange && queryParams.dateRange.length === 2) {
-      params.beginTime = queryParams.dateRange[0];
-      params.endTime = queryParams.dateRange[1];
+    if (queryParams.dateRange && queryParams.dateRange.length == 2) {
+      // params.beginTime = queryParams.dateRange[0];
+      // params.endTime = queryParams.dateRange[1];
+      params.params = {
+        beginTime: formatDate(queryParams.dateRange[0]), // 将日期转换为字符串格式
+
+        endTime: formatDate(queryParams.dateRange[1]) // 将日期转换为字符串格式
+      };
     }
 
+    console.log('发送到后端的参数:', params);
     const res = await getOrderList(params);
+    console.log('后端返回的数据:', res);
     if (res.code === 200) {
+      // 调试:打印后端返回的第一条订单数据
+      if (res.rows && res.rows.length > 0) {
+        console.log('后端���回的订单状态值:', res.rows[0].orderStatus);
+        console.log('完整的订单数据:', res.rows[0]);
+      }
+
+      // 获取订单商品数据
+      const orderProductsMap: Record<number, any[]> = {};
+      const orderIds = (res.rows || []).map((o: any) => o.id);
+      if (orderIds.length > 0) {
+        try {
+          const prodRes = await getOrderProducts(orderIds);
+          if (prodRes.code === 200 && prodRes.rows) {
+            prodRes.rows.forEach((p: any) => {
+              if (!orderProductsMap[p.orderId]) {
+                orderProductsMap[p.orderId] = [];
+              }
+              orderProductsMap[p.orderId].push({
+                id: p.id,
+                productId: p.productId,
+                image: p.productImage || '',
+                name: p.productName || '',
+                spec1: p.productUnit || '',
+                spec2: p.productNo || '',
+                price: p.orderPrice || 0,
+                quantity: p.orderQuantity || 0
+              });
+            });
+          }
+        } catch (e) {
+          console.error('获取商品列表失败:', e);
+        }
+      }
+
       // 将后端数据转换为前端需要的格式
       allOrders.value = (res.rows || []).map((order: OrderMain) => ({
         id: order.id,
@@ -248,10 +329,17 @@ const fetchOrderList = async () => {
         countdown: '',
         auditStatus: order.checkStatus,
         fileCount: 0,
+        checked: false,
         expanded: false,
-        products: [] // 商品信息需要单独加载
+        products: orderProductsMap[order.id] || [] // 商品信息已加载
       }));
 
+      // 调试:打印转换后的订单状态
+      console.log(
+        '转换后的订单状态分布:',
+        allOrders.value.map((o) => o.status)
+      );
+
       total.value = res.total || 0;
     }
   } catch (error) {
@@ -263,47 +351,18 @@ const fetchOrderList = async () => {
 
 const orderList = computed(() => allOrders.value);
 
-const getStatusColor = (status: string) =>
-  ({ completed: '#67c23a', preOrder: '#e6a23c', shipping: '#409eff', cancelled: '#909399' })[status] || '#909399';
-const getAuditStatusClass = (auditStatus: string) => (auditStatus === '审批通过' ? 'success' : auditStatus === '审批驳回' ? 'danger' : 'warning');
-
 const handleExpand = async (order: any) => {
   const orderIndex = allOrders.value.findIndex((o) => o.id === order.id);
   if (orderIndex === -1) return;
 
-  const currentOrder = allOrders.value[orderIndex];
-
-  if (!currentOrder.expanded && currentOrder.products.length === 0) {
-    try {
-      const res = await getOrderProducts([order.id]);
-      if (res.code === 200 && res.rows) {
-        const products = res.rows.map((p: any) => ({
-          id: p.productId || p.id,
-          image: p.productImage || '',
-          name: p.productName || '',
-          spec1: p.productUnit || '',
-          spec2: p.productNo || '',
-          price: p.orderPrice || 0,
-          quantity: p.orderQuantity || 0
-        }));
-
-        // 替换整个数组以触发响应式更新
-        allOrders.value = allOrders.value.map((o, i) => (i === orderIndex ? { ...o, expanded: true, products } : o));
-        return;
-      }
-    } catch (error) {
-      console.error('加载商品失败:', error);
-      return;
-    }
-  }
-
   // 替换整个数组以触发响应式更新
   allOrders.value = allOrders.value.map((o, i) => (i === orderIndex ? { ...o, expanded: !o.expanded } : o));
 };
 
-const handleViewDetail = (order: any) => {
-  router.push(`/order/orderManage/detail/${order.orderNo}`);
+const handleOrderCheck = () => {
+  selectAll.value = orderList.value.every((order) => order.checked);
 };
+
 const handleQuery = () => {
   queryParams.pageNum = 1;
   fetchOrderList();
@@ -317,44 +376,6 @@ const handleReset = () => {
   fetchOrderList();
 };
 
-// 加入购物车
-const handleAddCart = async (order: any) => {
-  try {
-    // 如果商品列表为空,先加载商品
-    if (!order.products || order.products.length === 0) {
-      const res = await getOrderProducts([order.id]);
-      if (res.code === 200 && res.rows) {
-        order.products = res.rows.map((p: any) => ({
-          id: p.productId || p.id,
-          image: p.productImage || '',
-          name: p.productName || '',
-          spec1: p.productUnit || '',
-          spec2: p.productNo || '',
-          price: p.orderPrice || 0,
-          quantity: p.orderQuantity || 0
-        }));
-      } else {
-        ElMessage.warning('无法获取订单商品信息');
-        return;
-      }
-    }
-
-    // 批量加入购物车
-    const promises = order.products.map((product: any) =>
-      addProductShoppingCart({
-        productId: product.id,
-        productNum: product.quantity || 1
-      })
-    );
-
-    await Promise.all(promises);
-    ElMessage.success(`已将${order.products.length}件商品加入购物车`);
-  } catch (error) {
-    console.error('加入购物车失败:', error);
-    ElMessage.error('加入购物车失败');
-  }
-};
-
 // 页面加载时获取订单列表
 onMounted(() => {
   loadDeptTree();
@@ -364,13 +385,14 @@ onMounted(() => {
 
 <style scoped lang="scss">
 .order-manage-container {
-  width: 100%;
   padding: 20px;
   background: #fff;
   min-height: 100%;
+  width: 100%;
   display: flex;
   flex-direction: column;
-  max-height: calc(100vh - 120px);
+  margin-bottom: 20px;
+  // max-height: calc(100vh - 120px); // 减去顶部导航栏和其他元素高度
 }
 .page-title {
   font-size: 16px;
@@ -387,22 +409,7 @@ onMounted(() => {
   background: #e60012;
   border-radius: 2px;
 }
-.search-bar {
-  display: flex;
-  align-items: center;
-  gap: 15px;
-  margin-bottom: 15px;
-}
-.filter-bar {
-  display: flex;
-  align-items: center;
-  gap: 10px;
-  margin-bottom: 15px;
-  .filter-label {
-    font-size: 14px;
-    color: #666;
-  }
-}
+
 .tab-bar {
   display: flex;
   justify-content: space-between;
@@ -433,8 +440,8 @@ onMounted(() => {
   }
 }
 .order-list {
-  flex: 1;
-  overflow-y: auto;
+  // flex: 1;
+  // overflow-y: auto;
   margin-bottom: 15px;
   .order-card {
     border: 1px solid #eee;
@@ -442,19 +449,20 @@ onMounted(() => {
     margin-bottom: 15px;
     overflow: hidden;
     .order-header {
-      display: flex;
-      align-items: center;
-      gap: 15px;
       padding: 12px 15px;
       background: #f9f9f9;
       border-bottom: 1px solid #eee;
-      font-size: 13px;
-      color: #666;
-      .order-time {
-        color: #333;
-      }
+      font-size: 14px;
+      color: #101828;
       .expand-btn {
-        margin-left: auto;
+        color: #165dff;
+        margin-left: 10px;
+        cursor: pointer;
+      }
+      .open-btn {
+        color: #364153;
+        margin-left: 10px;
+        cursor: pointer;
       }
     }
     .countdown-bar {
@@ -467,7 +475,7 @@ onMounted(() => {
     .product-list {
       .product-row {
         display: flex;
-        border-bottom: 1px solid #f5f5f5;
+        // border-bottom: 1px solid #f5f5f5;
         &:last-child {
           border-bottom: none;
         }
@@ -479,9 +487,9 @@ onMounted(() => {
         justify-content: center;
       }
       .product-info-cell {
+        display: flex;
         flex: 1;
-        flex-direction: row;
-        align-items: center;
+        padding: 15px;
         gap: 15px;
         .product-image {
           width: 80px;
@@ -504,21 +512,22 @@ onMounted(() => {
         }
         .product-detail {
           flex: 1;
+          width: 0;
           .product-name {
             font-size: 14px;
-            color: #333;
+            color: #000000;
             margin-bottom: 5px;
-            line-height: 1.4;
           }
           .product-spec {
             font-size: 12px;
             color: #999;
-            margin-bottom: 5px;
+            margin-bottom: 10px;
           }
           .product-price {
             font-size: 16px;
             font-weight: bold;
             color: #e60012;
+            margin-bottom: 5px;
           }
         }
         .product-quantity {
@@ -527,13 +536,14 @@ onMounted(() => {
         }
       }
       .amount-cell {
-        width: 120px;
-        border-left: 1px solid #f5f5f5;
+        width: 200px;
+        padding: 15px;
         .amount-info {
           margin-bottom: 5px;
           .label {
             font-size: 12px;
             color: #999;
+            margin-right: 4px;
           }
           .value {
             font-size: 14px;
@@ -547,16 +557,18 @@ onMounted(() => {
         }
       }
       .status-cell {
-        width: 120px;
-        border-left: 1px solid #f5f5f5;
+        width: 140px;
+        padding: 15px;
+        display: flex;
         align-items: flex-start;
-        gap: 5px;
+        justify-content: flex-end;
+        gap: 10px;
         .status-text {
           font-size: 14px;
           font-weight: 500;
         }
         .audit-status {
-          font-size: 12px;
+          font-size: 14px;
           &.success {
             color: #e60012;
           }
@@ -575,6 +587,78 @@ onMounted(() => {
         gap: 3px;
       }
     }
+    .more-products-hint {
+      padding: 10px 15px;
+      background: #f5f5f5;
+      font-size: 12px;
+      color: #666;
+      text-align: center;
+      border-top: 1px solid #f0f0f0;
+    }
+  }
+}
+
+.bottom-bar {
+  background: #fafafa;
+  border: 1px solid #eee;
+  border-radius: 4px;
+  padding: 15px 20px;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  flex-shrink: 0;
+  .bottom-right {
+    display: flex;
+    align-items: center;
+    gap: 15px;
+    .selected-info {
+      font-size: 14px;
+      color: #666;
+      em {
+        color: #e60012;
+        font-style: normal;
+        font-weight: bold;
+      }
+    }
+  }
+}
+.evaluate-product {
+  display: flex;
+  align-items: center;
+  gap: 15px;
+  padding: 15px;
+  background: #f9f9f9;
+  border-radius: 4px;
+  margin-bottom: 20px;
+  .product-image {
+    width: 60px;
+    height: 60px;
+    background: #fff;
+    border-radius: 4px;
+    overflow: hidden;
+    flex-shrink: 0;
+    .el-image {
+      width: 100%;
+      height: 100%;
+    }
+    .image-placeholder {
+      width: 100%;
+      height: 100%;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+    }
+  }
+  .product-info {
+    .product-name {
+      font-size: 14px;
+      color: #333;
+      margin-bottom: 5px;
+    }
+    .product-spec {
+      font-size: 12px;
+      color: #999;
+    }
   }
 }
 :deep(.table-pagination) {

+ 18 - 17
src/views/enterprise/securitySetting/changePhone.vue

@@ -44,8 +44,8 @@
       <!-- 步骤1:验证身份 -->
       <div class="step-content" v-if="currentStep === 1">
         <div class="phone-info">
-          <span>已绑定的手机:</span>
-          <span class="phone-number">180****7722</span>
+          <span>已绑定的手机:{{ step1Form.phone }}</span>
+          <span class="phone-number"></span>
         </div>
         <div class="phone-tip">若该手机号已无法使用请联系客服</div>
 
@@ -62,7 +62,7 @@
         </el-form>
 
         <div class="step-actions">
-          <el-button type="success" class="next-btn" @click="handleNextStep">下一步</el-button>
+          <el-button type="danger" class="next-btn" @click="handleNextStep">下一步</el-button>
         </div>
 
         <!-- 温馨提醒 -->
@@ -90,17 +90,17 @@
         </el-form>
         <div class="step-actions">
           <el-button @click="currentStep = 1">上一步</el-button>
-          <el-button type="success" class="next-btn" @click="handleSubmit">确认更换</el-button>
+          <el-button type="danger" class="next-btn" @click="handleSubmit">确认更换</el-button>
         </div>
       </div>
 
       <!-- 步骤3:完成 -->
       <div class="step-content" v-if="currentStep === 3">
         <div class="success-content">
-          <el-icon class="success-icon" color="#52c41a" :size="60"><CircleCheckFilled /></el-icon>
+          <el-icon class="success-icon" color="#e60012" :size="60"><CircleCheckFilled /></el-icon>
           <div class="success-title">手机号码更换成功!</div>
           <div class="success-desc">您的安全手机已更换为 {{ step2Form.newPhone }}</div>
-          <el-button type="success" @click="$router.push('/enterprise/securitySetting')">返回安全设置</el-button>
+          <el-button type="danger" @click="$router.push('/enterprise/securitySetting')">返回安全设置</el-button>
         </div>
       </div>
     </div>
@@ -109,14 +109,15 @@
 
 <script setup lang="ts">
 import { ref, reactive } from 'vue';
-import { Check, CircleCheckFilled } from '@element-plus/icons-vue';
+import { Check, CircleCheckFilled, Phone } from '@element-plus/icons-vue';
 import { ElMessage } from 'element-plus';
-
+import { useRoute } from 'vue-router';
 const currentStep = ref(1);
-
+const route = useRoute();
 // 步骤1表单
 const step1FormRef = ref();
 const step1Form = reactive({
+  phone: route.query.phone,
   code: '',
   verified: false
 });
@@ -281,22 +282,22 @@ const handleSubmit = async () => {
 
   &.active {
     .step-circle {
-      border-color: #52c41a;
-      color: #52c41a;
+      border-color: #e60012;
+      color: #e60012;
     }
     .step-label {
-      color: #52c41a;
+      color: #e60012;
     }
   }
 
   &.done {
     .step-circle {
-      border-color: #52c41a;
-      background: #52c41a;
+      border-color: #e60012;
+      background: #e60012;
       color: #fff;
     }
     .step-label {
-      color: #52c41a;
+      color: #e60012;
     }
   }
 }
@@ -309,7 +310,7 @@ const handleSubmit = async () => {
   margin-bottom: 30px;
 
   &.active {
-    background: #52c41a;
+    background: #e60012;
   }
 }
 
@@ -352,7 +353,7 @@ const handleSubmit = async () => {
 
   .send-code-btn {
     margin-left: 15px;
-    color: #52c41a;
+    color: #e60012;
   }
 
   .verify-checkbox {

+ 14 - 4
src/views/enterprise/securitySetting/index.vue

@@ -34,7 +34,7 @@
       </div>
 
       <!-- 安全手机 -->
-      <!-- <div class="setting-card">
+      <div class="setting-card">
         <div class="setting-icon">
           <el-icon :size="20" color="#fff"><Grid /></el-icon>
         </div>
@@ -43,7 +43,7 @@
           <div class="setting-desc">安全手机可以用于登录帐号,重置密码或其他安全验证</div>
         </div>
         <el-button type="danger" @click="handleChangePhone">更换</el-button>
-      </div> -->
+      </div>
     </div>
 
     <!-- 修改密码弹窗 -->
@@ -141,7 +141,12 @@ const handleBack = () => {
   router.push('/enterprise/companyInfo');
 };
 const handleModifyPassword = () => {
-  router.push('/enterprise/securitySetting/resetPassword');
+  router.push({
+    path: '/enterprise/securitySetting/resetPassword',
+    query: {
+      phone: securityData.phone
+    }
+  });
 };
 const getCurrentUser = async () => {
   const res = await getCurrentUserInfo();
@@ -157,7 +162,12 @@ const handleSavePassword = async () => {
   passwordDialogVisible.value = false;
 };
 const handleChangePhone = () => {
-  router.push('/enterprise/securitySetting/changePhone');
+  router.push({
+    path: '/enterprise/securitySetting/changePhone',
+    query: {
+      phone: securityData.phone
+    }
+  });
 };
 const handleSendCode = () => {
   if (!phoneForm.phone) {

+ 27 - 9
src/views/enterprise/securitySetting/resetPassword.vue

@@ -82,7 +82,7 @@
       <!-- 步骤3:完成 -->
       <div class="step-content" v-if="currentStep === 3">
         <div class="success-content">
-          <el-icon class="success-icon" color="#52c41a" :size="60"><CircleCheckFilled /></el-icon>
+          <el-icon class="success-icon" color="#e60012" :size="60"><CircleCheckFilled /></el-icon>
           <div class="success-title">密码重置成功!</div>
           <div class="success-desc">您的登录密码已重置成功,请使用新密码登录</div>
           <el-button type="danger" @click="$router.push('/enterprise/securitySetting')">返回安全设置</el-button>
@@ -96,13 +96,16 @@
 import { ref, reactive } from 'vue';
 import { Check, CircleCheckFilled } from '@element-plus/icons-vue';
 import { ElMessage } from 'element-plus';
+import { useRoute } from 'vue-router';
+import { changePwd } from '@/api/pc/enterprise/index';
 
 const currentStep = ref(1);
+const route = useRoute();
 
 // 步骤1表单
 const step1FormRef = ref();
 const step1Form = reactive({
-  phone: '18062697722',
+  phone: route.query.phone as any,
   code: '',
   verified: false
 });
@@ -169,9 +172,24 @@ const handleSubmit = async () => {
   const valid = await step2FormRef.value?.validate().catch(() => false);
   if (!valid) return;
 
-  // TODO: 调用修改密码接口
-  ElMessage.success('密码重置成功');
-  currentStep.value = 3;
+  try {
+    const submitData = {
+      phone: step1Form.phone,
+      code: step1Form.code,
+      password: step2Form.newPassword,
+      confirmPassword: step2Form.confirmPassword
+    };
+
+    const res: any = await changePwd(submitData);
+    if (res.code === 200) {
+      ElMessage.success('密码重置成功');
+      currentStep.value = 3;
+    } else {
+      ElMessage.error(res.msg || '密码修改失败');
+    }
+  } catch (error) {
+    console.error('修改密码失败:', error);
+  }
 };
 </script>
 
@@ -270,12 +288,12 @@ const handleSubmit = async () => {
 
   &.done {
     .step-circle {
-      border-color: #52c41a;
-      background: #52c41a;
+      border-color: #e60012;
+      background: #e60012;
       color: #fff;
     }
     .step-label {
-      color: #52c41a;
+      color: #e60012;
     }
   }
 }
@@ -288,7 +306,7 @@ const handleSubmit = async () => {
   margin-bottom: 30px;
 
   &.active {
-    background: #52c41a;
+    background: #e60012;
   }
 }
 

+ 15 - 11
src/views/home/index-fuli.vue

@@ -105,11 +105,11 @@
       <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>
+            <img class="sell-img" :src="item.productImage" alt="" />
+            <div class="sell-name ellipsis2">{{ item.itemName || '' }}</div>
             <div class="sell-price">
-              <span class="price1">¥{{ item.memberPrice || '23.22' }}</span>
-              <span class="price2">¥{{ item.marketPrice || '52.12' }}</span>
+              <span class="price1">¥{{ item.memberPrice || '' }}</span>
+              <span class="price2">¥{{ item.marketPrice || '' }}</span>
             </div>
           </div>
         </template>
@@ -120,10 +120,10 @@
         <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-name ellipsis2">{{ item.name || '' }}</div>
             <div class="goods-price">
-              <span class="price1">¥{{ item.memberPrice || '23.22' }}</span>
-              <span class="price2">¥{{ item.marketPrice || '52.12' }}</span>
+              <span class="price1">¥{{ item.memberPrice || '' }}</span>
+              <span class="price2">¥{{ item.marketPrice || '' }}</span>
             </div>
           </div>
         </div>
@@ -135,7 +135,7 @@
         <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">
+        <div v-for="(item, index) in recommend" :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">
@@ -187,8 +187,8 @@ const realList = ref<any>([]);
 const interestsList = ref<any>([]);
 const scenario = ref<any>([]);
 const popular = ref<any>([]);
-const goodsList = ref<any>([{}, {}, {}]);
-const recommend = ref<any>([{}, {}, {}]);
+const goodsList = ref<any>([]);
+const recommend = ref<any>([]);
 
 //头部分类
 getProductCategoryTree({}).then((res) => {
@@ -247,7 +247,11 @@ getRecommendAdList({}).then((res) => {
 //热门定制
 getHotCustomGiftFloorList({}).then((res) => {
   if (res.code == 200) {
-    popular.value = res.data;
+    getGiftFloorLinkProductList({ floorId: res.data[0].id }).then((res1) => {
+      if (res1.code == 200) {
+        popular.value = res1.data;
+      }
+    });
   }
 });
 

+ 66 - 28
src/views/home/index-mro.vue

@@ -104,9 +104,9 @@
         <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">{{ item.title||'' }}</div>
+              <div class="trade-title">{{ item.title || '' }}</div>
               <div class="trade-info ellipsis2">
-                {{ item.remark||'' }}
+                {{ item.remark || '' }}
               </div>
               <img class="trade-look" src="@/assets/images/home/indexMro1.png" alt="" />
             </div>
@@ -123,23 +123,23 @@
           <img src="@/assets/images/home/indexMro3.png" alt="" />
         </div>
         <div class="goods-box">
-          <img class="goods-one" src="" alt="" />
+          <img class="goods-one" :src="item.imageUrl" alt="" />
           <div class="goods-shop">
-            <template v-for="(item1, index1) in 10" :key="index1">
+            <template v-for="(item1, index1) in item.goodsList" :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>
+                <img class="shop-img" :src="item1.productImage ? item1.productImage.split(',')[0] : ''" alt="" />
+                <div class="shop-name ellipsis2">{{ item1.itemName || '' }}</div>
                 <div class="shop-price">
-                  <span class="price1">¥{{ item.memberPrice || '23.22' }}</span>
-                  <span class="price2">¥{{ item.marketPrice || '52.12' }}</span>
+                  <span class="price1">¥{{ item1.memberPrice || '' }}</span>
+                  <span class="price2">¥{{ item1.marketPrice || '' }}</span>
                 </div>
               </div>
             </template>
           </div>
-          <div class="goods-brand flex-column-between">
+          <div class="goods-brand flex-column-between" v-if="item.brandList && item.brandList.length > 0">
             <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 v-for="(item1, index1) in item.brandList" :key="index1">
+                <img clear-both v-if="Number(index1) < 6" class="brand-img" :src="item1.brandLogo" alt="" />
               </template>
             </div>
             <div class="brand-more flex-row-center">
@@ -156,18 +156,18 @@
         <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 v-for="(item, index) in recommendNav" :key="index">
+          <div @click="onNav(item)" class="nav-list" :class="categoryId == item.id ? 'hig' : ''" v-if="Number(index) < 9">{{ item.title }}</div>
         </template>
       </div>
       <!-- 轮播展位商品 -->
       <div class="sell-bos recommend">
-        <div v-for="(item, index) in 20" :key="index" class="sell-list">
+        <div v-for="(item, index) in recommendList" :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-name ellipsis2">{{ item.itemName || '' }}</div>
           <div class="sell-price">
-            <span class="price1">¥{{ item.memberPrice || '23.22' }}</span>
-            <span class="price2">¥{{ item.marketPrice || '52.12' }}</span>
+            <span class="price1">¥{{ item.memberPrice || '' }}</span>
+            <span class="price2">¥{{ item.marketPrice || '' }}</span>
           </div>
         </div>
       </div>
@@ -205,6 +205,9 @@ const interestsList = ref<any>([]);
 const sellList = ref<any>([]);
 const tradeList = ref<any>([]);
 const goodsList = ref<any>([]);
+const recommendNav = ref<any>([]);
+const recommendList = ref<any>([]);
+const categoryId = ref<any>('');
 
 onMounted(() => {
   if (getToken()) {
@@ -230,7 +233,7 @@ const enterClassify = (res: any) => {
 
 //头部分类
 getProductCategoryTree({
-  platform:1
+  platform: 1
 }).then((res) => {
   if (res.code == 200) {
     classifyList.value = res.data;
@@ -273,33 +276,68 @@ getBusinessLabelList({}).then((res) => {
 });
 
 //循环
-getIndustrialFloor({}).then((res) => {
+getIndustrialFloor({}).then(async (res) => {
   if (res.code == 200) {
-    goodsList.value = res.data;
-    res.data.forEach((item: any) => {
-      getIndustrialFloorProductList({ floorId: item.id }).then((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 getIndustrialFloorProductList({ floorId: item.id });
+        if (datas2.code == 200) {
+          item.goodsList = datas2.data;
         }
-      });
-      getIndustrialFloorBrand({ floorId: item.id }).then((res) => {
-        if (res.code == 200) {
+
+        const datas3 = await getIndustrialFloorBrand({ floorId: item.id });
+        if (datas2.code == 200) {
+          item.brandList = datas3.data;
         }
-      });
-    });
+      } catch (error) {}
+    }
+
+    goodsList.value = res.data;
   }
 });
 
 //为你推荐-分类
 getRecommendedCategory({}).then((res) => {
   if (res.code == 200) {
+    recommendNav.value = res.data;
+    recommendNav.value.unshift({
+      id: '',
+      title: '全部'
+    });
   }
 });
 
 //为你推荐-商品
 getRecommendedCategoryProductList({}).then((res) => {
   if (res.code == 200) {
+    recommendList.value = res.data;
   }
 });
+
+const onNav = (item: any) => {
+  categoryId.value = item.id;
+  getRecommendedCategoryProductList({ categoryId: categoryId.value }).then((res) => {
+    if (res.code == 200) {
+      recommendList.value = res.data;
+    }
+  });
+};
 </script>
 
 <style lang="scss" scoped>

+ 63 - 10
src/views/home/index.vue

@@ -63,8 +63,9 @@
           </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>
+            <!-- @click="onPath('/reg')" -->
+            <el-button v-if="!userInfo.nickName" type="primary" plain round size="small" style="width: 64px">注册</el-button>
+            <el-button v-if="userInfo.nickName" type="primary" plain round size="small" style="width: 64px" @click="onlogout()">退出</el-button>
           </div>
         </div>
         <div class="real-time">
@@ -98,7 +99,7 @@
         <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 class="title-more flex-row-start" @click="onPath(hotTitle.linkUrl ? hotTitle.linkUrl : '/plan')">
         <div style="margin-right: 5px">{{ hotTitle.linkWord }}</div>
         <el-icon :size="13" color="#83899F">
           <ArrowRight />
@@ -120,7 +121,7 @@
         <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 class="title-more flex-row-start" @click="onPath(sceneTitle.linkUrl ? sceneTitle.linkUrl : '/plan/procure')">
         <div style="margin-right: 5px">{{ sceneTitle.linkWord }}</div>
         <el-icon :size="13" color="#83899F">
           <ArrowRight />
@@ -171,7 +172,7 @@
         <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 class="title-more flex-row-start" @click="onPath(hotTitle.linkUrl ? hotTitle.linkUrl : '/search/special')">
         <div style="margin-right: 5px">{{ expertTitle.linkWord }}</div>
         <el-icon :size="13" color="#83899F">
           <ArrowRight />
@@ -288,7 +289,7 @@
         <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 class="title-more flex-row-start" @click="onPath(projectTitle.linkUrl ? projectTitle.linkUrl : '/plan/project')">
         <div style="margin-right: 5px">{{ projectTitle.linkWord }}</div>
         <el-icon :size="13" color="#83899F">
           <ArrowRight />
@@ -308,7 +309,9 @@
               <div></div>
               <div class="flex-row-start">
                 <div style="margin-right: 5px">了解详情</div>
-                <el-icon :size="14" color="#E7000B"><ArrowRight /></el-icon>
+                <el-icon :size="14" color="#E7000B">
+                  <ArrowRight />
+                </el-icon>
               </div>
             </div>
           </div>
@@ -567,6 +570,14 @@ getClassificationFloorList({}).then(async (res) => {
 const onInfo = (res: any) => {
   router.push('/shop/info?id=' + res.id);
 };
+import { useUserStore } from '@/store/modules/user';
+const onlogout = () => {
+  useUserStore()
+    .logout()
+    .then(() => {
+      onPath('/login');
+    });
+};
 </script>
 
 <style lang="scss" scoped>
@@ -586,6 +597,7 @@ const onInfo = (res: any) => {
       width: 234px;
       height: 540px;
       background: #ffffff;
+
       &.classify-show {
         position: absolute;
         z-index: 10;
@@ -716,6 +728,7 @@ const onInfo = (res: any) => {
         margin-top: 10px;
         display: flex;
         gap: 0 10px;
+
         .head-item {
           flex: 1;
           background-color: #ffffff;
@@ -726,6 +739,7 @@ const onInfo = (res: any) => {
           cursor: pointer;
           border-radius: 5px;
           overflow: hidden;
+
           img {
             width: 100%;
             height: 100%;
@@ -734,12 +748,14 @@ const onInfo = (res: any) => {
             // margin-right: 10px;
             // border-radius: 10px;
           }
+
           .head-title {
             .head1 {
               font-weight: 550;
               font-size: 22px;
               color: #101828;
             }
+
             .head2 {
               width: 76px;
               height: 21px;
@@ -1060,7 +1076,8 @@ const onInfo = (res: any) => {
           color: #364153;
           display: -webkit-box;
           -webkit-line-clamp: 2;
-          line-clamp: 2; /* 添加标准属性 */
+          line-clamp: 2;
+          /* 添加标准属性 */
           -webkit-box-orient: vertical;
           overflow: hidden;
           text-overflow: ellipsis;
@@ -1074,6 +1091,7 @@ const onInfo = (res: any) => {
     width: 1200px;
     display: flex;
     margin-top: 12px;
+
     .expert-list {
       width: 230px;
       height: 306px;
@@ -1081,25 +1099,30 @@ const onInfo = (res: any) => {
       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;
@@ -1118,21 +1141,25 @@ const onInfo = (res: any) => {
     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;
@@ -1228,20 +1255,24 @@ const onInfo = (res: any) => {
           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;
@@ -1249,6 +1280,7 @@ const onInfo = (res: any) => {
           }
         }
       }
+
       .home2-two {
         width: 177px;
         height: 273px;
@@ -1263,13 +1295,15 @@ const onInfo = (res: any) => {
           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; /* 添加标准属性 */
+          line-clamp: 2;
+          /* 添加标准属性 */
           -webkit-box-orient: vertical;
           overflow: hidden;
           text-overflow: ellipsis;
@@ -1283,25 +1317,30 @@ const onInfo = (res: any) => {
       }
     }
   }
+
   .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;
@@ -1311,9 +1350,11 @@ const onInfo = (res: any) => {
           color: #101828;
           margin-bottom: 10px;
           cursor: pointer;
+
           &:hover {
             color: var(--el-color-primary);
           }
+
           &.hig {
             background: var(--el-color-primary);
             color: #ffffff;
@@ -1321,6 +1362,7 @@ const onInfo = (res: any) => {
         }
       }
     }
+
     .shop-list {
       width: 230px;
       height: 306px;
@@ -1328,22 +1370,26 @@ const onInfo = (res: any) => {
       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;
@@ -1362,12 +1408,14 @@ const onInfo = (res: any) => {
     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;
@@ -1378,26 +1426,31 @@ const onInfo = (res: any) => {
         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; /* 添加标准属性 */
+        line-clamp: 2;
+        /* 添加标准属性 */
         -webkit-box-orient: vertical;
         overflow: hidden;
         text-overflow: ellipsis;
       }
+
       .project-more {
         text-align: right;
         font-size: 14px;

+ 5 - 3
src/views/item/index.vue

@@ -220,8 +220,8 @@ const getInfo = () => {
       carousel.value = [];
       if (res.data.imageUrl) {
         carousel.value = res.data.imageUrl.split(',');
-        if(carousel.value.length>5){
-          carousel.value = carousel.value.slice(0, 5)
+        if (carousel.value.length > 5) {
+          carousel.value = carousel.value.slice(0, 5);
         }
       }
       dataInfo.value = res.data;
@@ -293,7 +293,8 @@ const onCarousel = (type: number, index?: any) => {
 const handleChange = (val: any) => {
   // num.value = val;
 };
-
+import { cartStore } from '@/store/modules/cart';
+const cart = cartStore();
 const onCart = () => {
   addProductShoppingCart({
     productId: id.value,
@@ -301,6 +302,7 @@ const onCart = () => {
   }).then((res) => {
     if (res.code == 200) {
       ElMessage.success('加入购物车成功');
+      cart.onCartCount();
     }
   });
 };

+ 11 - 13
src/views/order/afterSale/index.vue

@@ -30,19 +30,17 @@
             ><el-icon><Search /></el-icon
           ></template>
         </el-input>
-        <el-date-picker
-          v-model="queryParams.dateRange"
-          type="daterange"
-          range-separator="—"
-          start-placeholder="开始日期"
-          end-placeholder="结束日期"
-          style="width: 240px"
-        />
-      </div>
-
-      <div class="filter-bar">
-        <span class="filter-label">状态</span>
-        <el-select v-model="queryParams.status" placeholder="请选择" style="width: 100px" clearable>
+        <div style="width: 240px">
+          <el-date-picker
+            v-model="queryParams.dateRange"
+            type="daterange"
+            range-separator="—"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期"
+            style="width: 240px"
+          />
+        </div>
+        <el-select v-model="queryParams.status" placeholder="状态" style="width: 240px" clearable>
           <el-option label="申请中" value="0" />
           <el-option label="已退货" value="1" />
           <el-option label="已拒绝" value="2" />

+ 49 - 26
src/views/order/orderAudit/index.vue

@@ -10,41 +10,37 @@
 
     <!-- 搜索栏 -->
     <div class="search-bar">
-      <el-input v-model="queryParams.keyword" placeholder="搜索" style="width: 150px" clearable>
+      <el-input v-model="queryParams.keyword" placeholder="搜索" style="width: 240px" clearable>
         <template #prefix>
           <el-icon><Search /></el-icon>
         </template>
       </el-input>
-      <el-date-picker
-        v-model="queryParams.dateRange"
-        type="daterange"
-        range-separator="—"
-        start-placeholder="开始日期"
-        end-placeholder="结束日期"
-        style="width: 240px"
-      />
-    </div>
-
-    <!-- 筛选栏 -->
-    <div class="filter-bar">
-      <span class="filter-label">下单部门</span>
+      <div style="width: 240px">
+        <el-date-picker
+          v-model="queryParams.dateRange"
+          type="daterange"
+          range-separator="—"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          style="width: 240px"
+        />
+      </div>
       <el-tree-select
         v-model="queryParams.department"
-        style="width: 100px"
+        style="width: 240px"
         :data="deptList"
         :props="{ value: 'deptId', label: 'deptName', children: 'children' }"
         value-key="deptId"
-        placeholder="请选择"
+        placeholder="下单部门"
         check-strictly
         :render-after-expand="false"
         clearable
       >
       </el-tree-select>
-      <!-- <span class="filter-label">筛选</span>
-      <el-select v-model="queryParams.filter1" placeholder="请选择" style="width: 100px" clearable>
-        <el-option label="条件1" value="1" />
-        <el-option label="条件2" value="2" />
-      </el-select> -->
+      <div>
+        <el-button type="primary" @click="handleQuery">搜索</el-button>
+        <el-button @click="handleReset">重置</el-button>
+      </div>
     </div>
 
     <!-- 订单列表 -->
@@ -92,7 +88,7 @@
             </div>
             <div class="product-cell amount-cell">
               <div class="amount-info">
-                <span class="label">支付款</span>
+                <span class="label">支付款:</span>
                 <span class="value highlight">¥{{ order.payableAmount }}</span>
               </div>
               <div class="amount-info">
@@ -114,7 +110,7 @@
             </div>
             <div class="product-cell action-cell">
               <template v-if="activeMainTab === 'myAudit' && order.checkStatus === '0'">
-                <el-button type="primary" link size="small" @click="handleApprove(order)">同意</el-button>
+                <el-button type="success" link size="small" @click="handleApprove(order)">同意</el-button>
                 <el-button type="danger" link size="small" @click="handleReject(order)">拒绝</el-button>
               </template>
               <template v-if="activeMainTab === 'myApply' && order.checkStatus === '0'">
@@ -226,7 +222,23 @@ const checkOrderData = reactive({
 
 const auditForm = reactive({ opinion: '' });
 const auditRules = { opinion: [{ required: true, message: '请输入审批意见', trigger: 'blur' }] };
-
+const handleQuery = () => {
+  loadOrderList();
+};
+const handleReset = () => {
+  queryParams.keyword = '';
+  queryParams.dateRange = null;
+  queryParams.department = '';
+  loadOrderList();
+};
+const formatDate = (date: Date | string | number): string => {
+  if (!date) return '';
+  const d = new Date(date);
+  const year = d.getFullYear();
+  const month = String(d.getMonth() + 1).padStart(2, '0');
+  const day = String(d.getDate()).padStart(2, '0');
+  return `${year}-${month}-${day}`;
+};
 // 加载订单列表数据
 const loadOrderList = async () => {
   try {
@@ -247,6 +259,16 @@ const loadOrderList = async () => {
       params.checkStatus = '2';
     }
 
+    // 添加筛选条件
+    if (queryParams.keyword) params.orderNo = queryParams.keyword;
+    if (queryParams.department) params.createDept = queryParams.department;
+    if (queryParams.dateRange && queryParams.dateRange.length == 2) {
+      params.params = {
+        beginTime: formatDate(queryParams.dateRange[0]),
+        endTime: formatDate(queryParams.dateRange[1])
+      };
+    }
+
     const res = await getOrderList(params);
     if (res.code === 200 && res.rows) {
       allOrders.value = res.rows.map((item: any) => ({
@@ -544,7 +566,7 @@ const handleSubmitAudit = async () => {
       }
 
       .amount-cell {
-        width: 120px;
+        width: 150px;
         border-left: 1px solid #f5f5f5;
 
         .amount-info {
@@ -552,6 +574,7 @@ const handleSubmitAudit = async () => {
           .label {
             font-size: 12px;
             color: #999;
+            margin-right: 5px;
           }
           .value {
             font-size: 14px;
@@ -597,7 +620,7 @@ const handleSubmitAudit = async () => {
         width: 100px;
         border-left: 1px solid #f5f5f5;
         // align-items: flex-start;
-        gap: 5px;
+        // gap: 5px;
       }
     }
   }

+ 92 - 59
src/views/order/orderEvaluation/index.vue

@@ -3,57 +3,63 @@
     <PageTitle title="订单评价" />
     <StatusTabs v-model="activeMainTab" :tabs="mainTabs" type="line" />
 
-    <div class="search-bar">
-      <el-input v-model="queryParams.keyword" placeholder="搜索" style="width: 150px" clearable>
+    <!-- <div class="search-bar">
+      <el-input v-model="queryParams.keyword" placeholder="搜索" style="width: 260px" clearable>
         <template #prefix
           ><el-icon><Search /></el-icon
         ></template>
       </el-input>
-      <el-date-picker
-        v-model="queryParams.dateRange"
-        type="daterange"
-        range-separator="—"
-        start-placeholder="开始日期"
-        end-placeholder="结束日期"
-        style="width: 240px"
-      />
-    </div>
+      <div style="width: 260px">
+        <el-date-picker
+          v-model="queryParams.dateRange"
+          type="daterange"
+          range-separator="—"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          style="width: 260px"
+        />
+      </div>
+    </div> 
 
     <div class="filter-bar">
-      <span class="filter-label">下单部门</span>
       <el-tree-select
         v-model="queryParams.department"
-        style="width: 100px"
+        style="width: 160px"
         :data="deptList"
         :props="{ value: 'deptId', label: 'deptName', children: 'children' }"
         value-key="deptId"
-        placeholder="请选择"
+        placeholder="下单部门"
         check-strictly
         :render-after-expand="false"
         clearable
       >
       </el-tree-select>
-      <span class="filter-label">状态</span>
-      <el-select v-model="queryParams.status" placeholder="请选择" style="width: 100px" clearable>
+      <el-select v-model="queryParams.status" placeholder="状态" style="width: 160px" clearable>
         <el-option v-for="dict in order_status" :key="dict.value" :label="dict.label" :value="dict.value" />
       </el-select>
-      <span class="filter-label">支付方式</span>
-      <el-select v-model="queryParams.payType" placeholder="请选择" style="width: 100px" clearable>
+      <el-select v-model="queryParams.payType" placeholder="支付方式" style="width: 160px" clearable>
         <el-option v-for="dict in pay_method" :key="dict.value" :label="dict.label" :value="dict.value" />
       </el-select>
-    </div>
+    </div>-->
 
     <div class="order-list">
       <div v-for="(order, orderIndex) in orderList" :key="orderIndex" class="order-card">
-        <div class="order-header">
-          <span class="order-time">{{ order.orderTime }}</span>
-          <span class="order-no">订单号:{{ order.orderNo }}</span>
-          <el-button type="primary" link class="expand-btn" @click="order.expanded = !order.expanded"
-            >{{ order.expanded ? '收起' : '展开' }} <el-icon><ArrowRight /></el-icon
-          ></el-button>
-          <el-button type="primary" link class="detail-btn" @click="handleViewDetail(order)"
-            >订单详情 <el-icon><ArrowRight /></el-icon
-          ></el-button>
+        <div class="order-header flex-row-between">
+          <div class="flex-row-start">
+            <span class="order-time">{{ order.orderTime }}</span>
+            <span class="order-no">订单号:{{ order.orderNo }}</span>
+          </div>
+          <div class="flex-row-start">
+            <div class="expand-btn" @click="handleViewDetail(order)">
+              <span style="margin-right: 5px; margin-bottom: 2px">订单详情</span>
+              <el-icon><ArrowRight /></el-icon>
+            </div>
+            <div class="open-btn" v-if="order.products && order.products.length > 1" @click="order.expanded = !order.expanded">
+              <span style="margin-right: 5px"> {{ order.expanded ? '收起' : '展开' }}</span>
+              <el-icon v-if="order.expanded"><ArrowUp /></el-icon>
+              <el-icon v-else><ArrowDown /></el-icon>
+            </div>
+          </div>
         </div>
         <div class="product-list">
           <div
@@ -61,7 +67,7 @@
             :key="productIndex"
             class="product-row"
           >
-            <div class="product-cell product-info-cell">
+            <div class="product-info-cell">
               <div class="product-image">
                 <el-image :src="product.image" fit="contain">
                   <template #error
@@ -71,27 +77,27 @@
                 </el-image>
               </div>
               <div class="product-detail">
-                <div class="product-name">{{ product.name }}</div>
-                <div class="product-spec">{{ product.spec1 }} {{ product.spec2 }}</div>
+                <div class="product-name ellipsis">{{ product.name }}</div>
+                <div class="product-spec">{{ product.spec1 }} | {{ product.spec2 }}</div>
                 <div class="product-price">¥{{ product.price }}</div>
               </div>
               <div class="product-quantity">x{{ product.quantity }}</div>
             </div>
-            <div class="product-cell amount-cell" v-if="productIndex === 0">
+            <div class="amount-cell" v-if="productIndex === 0">
               <div class="amount-info">
-                <span class="label">支付款</span><span class="value highlight">¥{{ order.payAmount }}</span>
+                <span class="label">支付款</span><span class="value highlight">¥{{ order.payAmount }}</span>
               </div>
               <div class="amount-info">
                 <span class="label">{{ order.payMethod }}</span>
               </div>
             </div>
-            <div class="product-cell status-cell" v-if="productIndex === 0">
+            <div class="status-cell" v-if="productIndex === 0">
               <span class="status-text success">{{ order.statusText }}</span>
             </div>
-            <div class="product-cell action-cell" v-if="productIndex === 0">
-              <el-button v-if="activeMainTab === '0'" type="primary" link size="small" @click="handleEvaluate(order)">评价</el-button>
-              <el-button v-if="activeMainTab === '1'" type="primary" link size="small" @click="handleFollowUpEvaluate(order)">追评</el-button>
-              <el-button v-if="activeMainTab === '2'" type="primary" link size="small" @click="handleViewEvaluation(order)">查看评价</el-button>
+            <div class="action-cell" v-if="productIndex === 0">
+              <el-button v-if="activeMainTab === '0'" type="primary" link @click="handleEvaluate(order)">评价</el-button>
+              <el-button v-if="activeMainTab === '1'" type="primary" link @click="handleFollowUpEvaluate(order)">追评</el-button>
+              <el-button v-if="activeMainTab === '2'" type="primary" link @click="handleViewEvaluation(order)">查看评价</el-button>
             </div>
           </div>
           <!-- 显示更多商品提示 -->
@@ -145,7 +151,7 @@ import { useRouter } from 'vue-router';
 import { Search, Edit, ChatDotRound, Document, ArrowRight, Picture, Plus } from '@element-plus/icons-vue';
 import { ElMessage } from 'element-plus';
 import { PageTitle, StatusTabs } from '@/components';
-import { getOrderList, getOrderProducts, cancelOrder, deleteOrder, getEvalutionList, addOrderEvaluation } from '@/api/pc/enterprise/order';
+import { getOrderList, getOrderProducts, getEvalutionList, addOrderEvaluation, getOrderEvaluation } from '@/api/pc/enterprise/order';
 import type { OrderMain, OrderStatusStats } from '@/api/pc/enterprise/orderTypes';
 import { getDeptTree } from '@/api/pc/organization';
 import { DeptInfo } from '@/api/pc/organization/types';
@@ -238,8 +244,10 @@ const getorders = async () => {
 
     if (queryParams.keyword) params.orderNo = queryParams.keyword;
     if (queryParams.dateRange && queryParams.dateRange.length === 2) {
-      params.beginTime = queryParams.dateRange[0];
-      params.endTime = queryParams.dateRange[1];
+      params.params = {
+        beginTime: queryParams.dateRange[0],
+        endTime: queryParams.dateRange[1]
+      };
     }
     if (queryParams.department) params.department = queryParams.department;
     if (queryParams.status) params.orderStatus = queryParams.status;
@@ -321,17 +329,32 @@ const handleEvaluate = (order: any) => {
   evaluateForm.evaluationType = 1;
   evaluateDialogVisible.value = true;
 };
-const handleFollowUpEvaluate = (order: any) => {
-  currentOrder.value = order;
-  currentProduct.value = order.products[0];
-  evaluateDialogTitle.value = '追加评价';
-  evaluateForm.deliverGoods = undefined;
-  evaluateForm.content = '';
-  evaluateForm.evaluationType = 2;
-  evaluateDialogVisible.value = true;
+const handleFollowUpEvaluate = async (order: any) => {
+  const res = await getOrderEvaluation(order.orderId);
+  if (res.code === 200 && res.data) {
+    currentOrder.value = order;
+    currentProduct.value = order.products[0];
+    evaluateDialogTitle.value = '追加评价';
+    evaluateForm.deliverGoods = res.data.deliverGoods;
+    evaluateForm.content = res.data.content;
+    evaluateForm.evaluationType = 2;
+    evaluateDialogVisible.value = true;
+  } else {
+    ElMessage.error('获取评价失败');
+  }
 };
-const handleViewEvaluation = (order: any) => {
-  ElMessage.info('查看评价详情');
+const handleViewEvaluation = async (order: any) => {
+  const res = await getOrderEvaluation(order.orderId);
+  if (res.code === 200 && res.data) {
+    currentOrder.value = order;
+    currentProduct.value = order.products[0];
+    evaluateDialogTitle.value = '查看评价';
+    evaluateForm.deliverGoods = res.data.deliverGoods;
+    evaluateForm.content = res.data.content;
+    evaluateDialogVisible.value = true;
+  } else {
+    ElMessage.error('获取评价失败');
+  }
 };
 const handleSubmitEvaluate = async () => {
   const valid = await evaluateFormRef.value?.validate();
@@ -396,6 +419,7 @@ onMounted(() => {
   background: #fff;
   min-height: 100%;
   width: 100%;
+  margin-bottom: 20px;
 }
 .search-bar {
   display: flex;
@@ -428,6 +452,16 @@ onMounted(() => {
       border-bottom: 1px solid #eee;
       font-size: 13px;
       color: #666;
+      .open-btn {
+        color: #364153;
+        margin-left: 10px;
+        cursor: pointer;
+      }
+      .expand-btn {
+        color: #165dff;
+        margin-left: 10px;
+        cursor: pointer;
+      }
       .order-time {
         color: #333;
       }
@@ -454,9 +488,9 @@ onMounted(() => {
         justify-content: center;
       }
       .product-info-cell {
+        display: flex;
         flex: 1;
-        flex-direction: row;
-        align-items: center;
+        padding: 15px;
         gap: 15px;
         .product-image {
           width: 80px;
@@ -483,12 +517,11 @@ onMounted(() => {
             font-size: 14px;
             color: #333;
             margin-bottom: 5px;
-            line-height: 1.4;
           }
           .product-spec {
             font-size: 12px;
             color: #999;
-            margin-bottom: 5px;
+            margin-bottom: 10px;
           }
           .product-price {
             font-size: 16px;
@@ -502,8 +535,8 @@ onMounted(() => {
         }
       }
       .amount-cell {
-        width: 120px;
-        border-left: 1px solid #f5f5f5;
+        width: 200px;
+        padding: 15px;
         .amount-info {
           margin-bottom: 5px;
           .label {
@@ -523,8 +556,8 @@ onMounted(() => {
       }
       .status-cell {
         width: 80px;
-        border-left: 1px solid #f5f5f5;
         align-items: center;
+        padding: 15px;
         .status-text {
           font-size: 13px;
           font-weight: 500;
@@ -534,8 +567,8 @@ onMounted(() => {
         }
       }
       .action-cell {
+        padding: 15px;
         width: 80px;
-        border-left: 1px solid #f5f5f5;
         align-items: center;
       }
     }

+ 1 - 0
src/views/order/orderManage/detail.vue

@@ -244,6 +244,7 @@ const handleBack = () => {
 
 <style scoped lang="scss">
 .order-detail-container {
+  flex: 1;
   background: #f5f5f5;
   min-height: 100%;
 }

+ 144 - 141
src/views/order/orderManage/index.vue

@@ -2,64 +2,71 @@
   <div class="order-manage-container">
     <div class="page-title"><i class="title-bar"></i><span>订单管理</span></div>
     <!-- 搜索栏 -->
-    <div class="search-bar">
-      <el-input v-model="queryParams.keyword" placeholder="搜索订单号" style="width: 200px" clearable @keyup.enter="handleQuery">
-        <template #prefix
-          ><el-icon><Search /></el-icon
-        ></template>
-      </el-input>
-      <el-date-picker
-        v-model="queryParams.dateRange"
-        type="daterange"
-        range-separator="—"
-        start-placeholder="开始日期"
-        end-placeholder="结束日期"
-        style="width: 240px"
-      />
-      <el-button type="primary" @click="handleQuery">搜索</el-button>
-      <el-button @click="handleReset">重置</el-button>
+    <div class="flex-row-between">
+      <div class="flex-row-start">
+        <el-input v-model="queryParams.keyword" placeholder="搜索订单号" style="width: 260px" clearable @keyup.enter="handleQuery">
+          <template #prefix
+            ><el-icon><Search /></el-icon
+          ></template>
+        </el-input>
+        <el-date-picker
+          v-model="queryParams.dateRange"
+          type="daterange"
+          range-separator="—"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          style="width: 260px; margin-left: 10px"
+        />
+      </div>
+      <div>
+        <el-button type="primary" @click="handleQuery">搜索</el-button>
+        <el-button @click="handleReset">重置</el-button>
+      </div>
     </div>
-    <!-- 筛选栏 -->
-    <div class="filter-bar">
-      <span class="filter-label">下单部门</span>
-      <el-tree-select
-        v-model="queryParams.department"
-        style="width: 100px"
-        :data="deptList"
-        :props="{ value: 'deptId', label: 'deptName', children: 'children' }"
-        value-key="deptId"
-        placeholder="请选择"
-        check-strictly
-        :render-after-expand="false"
-        clearable
-      >
-      </el-tree-select>
-      <span class="filter-label">状态</span>
-      <el-select v-model="queryParams.status" placeholder="请选择" style="width: 100px" clearable>
-        <el-option v-for="dict in order_status" :key="dict.value" :label="dict.label" :value="dict.value" />
-      </el-select>
-      <span class="filter-label">支付方式</span>
-      <el-select v-model="queryParams.payType" placeholder="请选择" style="width: 100px" clearable
-        ><el-option v-for="dict in pay_method" :key="dict.value" :label="dict.label" :value="dict.value"
-      /></el-select>
-      <div class="filter-right">
-        <el-dropdown
-          ><el-button
-            >订单导出 <el-icon><ArrowDown /></el-icon></el-button
-          ><template #dropdown
-            ><el-dropdown-menu><el-dropdown-item>导出Excel</el-dropdown-item><el-dropdown-item>导出PDF</el-dropdown-item></el-dropdown-menu></template
-          ></el-dropdown
+    <div class="flex-row-between" style="margin-top: 10px">
+      <div class="flex-row-start">
+        <el-tree-select
+          v-model="queryParams.department"
+          style="width: 160px"
+          :data="deptList"
+          :props="{ value: 'deptId', label: 'deptName', children: 'children' }"
+          value-key="deptId"
+          placeholder="下单部门"
+          check-strictly
+          :render-after-expand="false"
+          clearable
         >
-        <el-dropdown
-          ><el-button
-            >订单打印 <el-icon><ArrowDown /></el-icon></el-button
-          ><template #dropdown
+        </el-tree-select>
+        <el-select v-model="queryParams.status" placeholder="状态" style="width: 160px; margin-left: 10px" clearable>
+          <el-option v-for="dict in order_status" :key="dict.value" :label="dict.label" :value="dict.value" />
+        </el-select>
+        <el-select v-model="queryParams.payType" placeholder="支付方式" style="width: 160px; margin-left: 10px" clearable
+          ><el-option v-for="dict in pay_method" :key="dict.value" :label="dict.label" :value="dict.value" />
+        </el-select>
+      </div>
+      <div class="flex-row-start">
+        <el-dropdown>
+          <el-button
+            >订单导出 <el-icon><ArrowDown /></el-icon
+          ></el-button>
+          <template #dropdown>
+            <el-dropdown-menu>
+              <el-dropdown-item>导出Excel</el-dropdown-item>
+              <el-dropdown-item>导出PDF</el-dropdown-item>
+            </el-dropdown-menu>
+          </template>
+        </el-dropdown>
+        <el-dropdown style="margin-left: 10px">
+          <el-button
+            >订单打印 <el-icon><ArrowDown /></el-icon
+          ></el-button>
+          <template #dropdown
             ><el-dropdown-menu
               ><el-dropdown-item>打印订单</el-dropdown-item><el-dropdown-item>打印发货单</el-dropdown-item></el-dropdown-menu
             ></template
-          ></el-dropdown
-        >
-        <el-button>下载电子签单</el-button>
+          >
+        </el-dropdown>
+        <el-button style="margin-left: 10px">下载电子签单</el-button>
       </div>
     </div>
     <!-- Tab切换 -->
@@ -76,29 +83,27 @@
     <!-- 订单列表 -->
     <div class="order-list">
       <div v-for="order in orderList" :key="order.id" class="order-card">
-        <div class="order-header">
-          <el-checkbox v-model="order.checked" @change="handleOrderCheck" />
-          <span class="order-time">{{ order.orderTime }}</span>
-          <span class="order-info">订单号:{{ order.orderNo }}</span>
-          <span class="order-info">下单人:{{ order.orderPerson }}</span>
-          <span class="order-info">部门:{{ order.department }}</span>
-          <el-button
-            class="expand-btn"
-            v-for="action in getOrderActions(order)"
-            :key="action"
-            type="primary"
-            link
-            @click="handleAction(action, order)"
-            >{{ action }}</el-button
-          >
-          <el-button v-if="order.products && order.products.length > 5" type="primary" link class="expand-btn" @click="handleExpand(order)"
-            >{{ order.expanded ? '收起' : '展开' }} <el-icon><ArrowDown /></el-icon
-          ></el-button>
+        <div class="order-header flex-row-between">
+          <div class="flex-row-start" style="gap: 0 15px">
+            <el-checkbox style="margin: 2px 0px 0px 0" v-model="order.checked" @change="handleOrderCheck" />
+            <div>{{ order.orderTime }}</div>
+            <div>订单号:{{ order.orderNo }}</div>
+            <div>下单人:{{ order.orderPerson }}</div>
+            <div>部门:{{ order.department }}</div>
+          </div>
+          <div class="flex-row-start">
+            <div class="expand-btn" v-for="action in getOrderActions(order)" :key="action" @click="handleAction(action, order)">{{ action }}</div>
+            <div class="open-btn" v-if="order.products && order.products.length > 5" @click="handleExpand(order)">
+              <span style="margin-right: 5px"> {{ order.expanded ? '收起' : '展开' }}</span>
+              <el-icon v-if="order.expanded"><ArrowUp /></el-icon>
+              <el-icon v-else><ArrowDown /></el-icon>
+            </div>
+          </div>
         </div>
         <div v-if="order.countdown" class="countdown-bar">订单锁定剩余时间:{{ order.countdown }}</div>
         <div class="product-list">
           <div v-for="(item, itemIndex) in order.expanded ? order.products : order.products.slice(0, 5)" :key="itemIndex" class="product-row">
-            <div class="product-cell product-info-cell">
+            <div class="product-info-cell">
               <div class="product-image">
                 <el-image :src="item.image" fit="contain"
                   ><template #error
@@ -107,31 +112,30 @@
                 ></el-image>
               </div>
               <div class="product-detail">
-                <div class="product-name">{{ item.name }}</div>
-                <div class="product-spec">{{ item.spec1 }} {{ item.spec2 }}</div>
+                <div class="product-name ellipsis">{{ item.name }}</div>
+                <div class="product-spec">{{ item.spec1 }} | {{ item.spec2 }}</div>
                 <div class="product-price">¥{{ item.price }}</div>
+                <el-button size="small" @click="handleAddCart(item)">加入购物车</el-button>
               </div>
               <div class="product-quantity">x{{ item.quantity }}</div>
             </div>
-            <div class="product-cell amount-cell" v-if="itemIndex === 0">
+            <div class="amount-cell" v-if="itemIndex === 0">
               <div class="amount-info">
-                <span class="label">支付款</span><span class="value highlight">¥{{ order.payAmount }}</span>
+                <span class="label">支付款</span><span class="value highlight">¥{{ order.payAmount }}</span>
               </div>
               <div class="amount-info">
                 <span class="label">含运费:</span><span class="value">¥{{ order.freight }}</span>
               </div>
             </div>
-            <div class="product-cell status-cell" v-if="itemIndex === 0">
+            <div class="status-cell" v-if="itemIndex === 0">
               <span class="status-text" :style="{ color: getStatusColor(order.status) }">{{ order.statusText }}</span>
+              <span v-if="order.auditStatus" :class="['audit-status', getAuditStatusClass(order.auditStatus)]">{{
+                order.auditStatus == '0' ? '待审批' : order.auditStatus == '1' ? '审批通过' : '审批驳回'
+              }}</span>
               <!-- <el-button type="primary" link size="small" @click="handleViewDetail(order)">查看订单轨迹</el-button> -->
-              <template v-if="order.auditStatus"
-                ><span :class="['audit-status', getAuditStatusClass(order.auditStatus)]">{{
-                  order.auditStatus == '0' ? '待审批' : order.auditStatus == '1' ? '审批通过' : '审批驳回'
-                }}</span>
-                <!-- <el-button type="primary" link size="small">查看审批流</el-button> -->
-              </template>
               <el-button v-if="order.fileCount" type="primary" link size="small">审核文件({{ order.fileCount }})</el-button>
             </div>
+            <div v-else style="width: 340px"></div>
             <!-- <div class="product-cell action-cell" v-if="itemIndex === 0">
               <el-button
                 v-for="action in getOrderActions(order)"
@@ -341,7 +345,16 @@ const loadDeptTree = async () => {
 };
 
 /** 单个加入购物车 */
-const handleAddCart = async (order: any) => {
+const handleAddCart = async (item: any) => {
+  addProductShoppingCart({ productId: item.id, productNum: 1 }).then((res: any) => {
+    if (res.code == 200) {
+      ElMessage.success('已加入购物车');
+    }
+  });
+};
+
+/** 单个加入购物车 */
+const handleAddCartBatch = async (order: any) => {
   const res = await getOrderProducts([order.id]);
   if (res.code === 200 && res.rows) {
     const products = res.rows.map((p: any) => ({
@@ -354,14 +367,15 @@ const handleAddCart = async (order: any) => {
       ElMessage.success(`已将${products.length}件商品加入购物车`);
     });
   }
-
-  // addProductShoppingCart({ productId: item.id, productNum: 1 }).then((res: any) => {
-  //   if (res.code == 200) {
-  //     ElMessage.success('已加入购物车');
-  //   }
-  // });
 };
-
+const formatDate = (date: Date | string | number): string => {
+  if (!date) return '';
+  const d = new Date(date);
+  const year = d.getFullYear();
+  const month = String(d.getMonth() + 1).padStart(2, '0');
+  const day = String(d.getDate()).padStart(2, '0');
+  return `${year}-${month}-${day}`;
+};
 // 获取订单列表
 const fetchOrderList = async () => {
   loading.value = true;
@@ -373,12 +387,16 @@ const fetchOrderList = async () => {
 
     // 添加筛选条件
     if (queryParams.keyword) params.orderNo = queryParams.keyword;
-    if (queryParams.department) params.department = queryParams.department;
+    if (queryParams.department) params.createDept = queryParams.department;
     if (queryParams.status) params.orderStatuses = queryParams.status; // 使用orderStatuses支持多状态查询
     if (queryParams.payType) params.payType = queryParams.payType;
     if (queryParams.dateRange && queryParams.dateRange.length == 2) {
-      params.beginTime = queryParams.dateRange[0];
-      params.endTime = queryParams.dateRange[1];
+      // params.beginTime = queryParams.dateRange[0];
+      // params.endTime = queryParams.dateRange[1];
+      params.params = {
+        beginTime: formatDate(queryParams.dateRange[0]), // 将日期转换为字符串格式
+        endTime: formatDate(queryParams.dateRange[1]) // 将日期转换为字符串格式
+      };
     }
 
     console.log('发送到后端的参数:', params);
@@ -591,7 +609,7 @@ const handleAction = (action: string, order: any) => {
       handleEvaluate(order);
       break;
     case '再次购买':
-      handleAddCart(order);
+      handleAddCartBatch(order);
       break;
     case '申请售后':
       handleApplyAfter(order);
@@ -697,7 +715,8 @@ onMounted(() => {
   width: 100%;
   display: flex;
   flex-direction: column;
-  max-height: calc(100vh - 120px); // 减去顶部导航栏和其他元素高度
+  margin-bottom: 20px;
+  // max-height: calc(100vh - 120px); // 减去顶部导航栏和其他元素高度
 }
 .page-title {
   font-size: 16px;
@@ -714,28 +733,7 @@ onMounted(() => {
   background: #e60012;
   border-radius: 2px;
 }
-.search-bar {
-  display: flex;
-  align-items: center;
-  gap: 15px;
-  margin-bottom: 15px;
-}
-.filter-bar {
-  display: flex;
-  align-items: center;
-  gap: 10px;
-  margin-bottom: 15px;
-  .filter-label {
-    font-size: 14px;
-    color: #666;
-  }
-  .filter-right {
-    flex: 1;
-    display: flex;
-    justify-content: flex-end;
-    gap: 10px;
-  }
-}
+
 .tab-bar {
   display: flex;
   justify-content: space-between;
@@ -766,8 +764,8 @@ onMounted(() => {
   }
 }
 .order-list {
-  flex: 1;
-  overflow-y: auto;
+  // flex: 1;
+  // overflow-y: auto;
   margin-bottom: 15px;
   .order-card {
     border: 1px solid #eee;
@@ -775,19 +773,20 @@ onMounted(() => {
     margin-bottom: 15px;
     overflow: hidden;
     .order-header {
-      display: flex;
-      align-items: center;
-      gap: 15px;
       padding: 12px 15px;
       background: #f9f9f9;
       border-bottom: 1px solid #eee;
-      font-size: 13px;
-      color: #666;
-      .order-time {
-        color: #333;
-      }
+      font-size: 14px;
+      color: #101828;
       .expand-btn {
-        margin-left: auto;
+        color: #165dff;
+        margin-left: 10px;
+        cursor: pointer;
+      }
+      .open-btn {
+        color: #364153;
+        margin-left: 10px;
+        cursor: pointer;
       }
     }
     .countdown-bar {
@@ -800,7 +799,7 @@ onMounted(() => {
     .product-list {
       .product-row {
         display: flex;
-        border-bottom: 1px solid #f5f5f5;
+        // border-bottom: 1px solid #f5f5f5;
         &:last-child {
           border-bottom: none;
         }
@@ -812,9 +811,9 @@ onMounted(() => {
         justify-content: center;
       }
       .product-info-cell {
+        display: flex;
         flex: 1;
-        flex-direction: row;
-        align-items: center;
+        padding: 15px;
         gap: 15px;
         .product-image {
           width: 80px;
@@ -837,21 +836,22 @@ onMounted(() => {
         }
         .product-detail {
           flex: 1;
+          width: 0;
           .product-name {
             font-size: 14px;
-            color: #333;
+            color: #000000;
             margin-bottom: 5px;
-            line-height: 1.4;
           }
           .product-spec {
             font-size: 12px;
             color: #999;
-            margin-bottom: 5px;
+            margin-bottom: 10px;
           }
           .product-price {
             font-size: 16px;
             font-weight: bold;
             color: #e60012;
+            margin-bottom: 5px;
           }
         }
         .product-quantity {
@@ -860,13 +860,14 @@ onMounted(() => {
         }
       }
       .amount-cell {
-        width: 120px;
-        border-left: 1px solid #f5f5f5;
+        width: 200px;
+        padding: 15px;
         .amount-info {
           margin-bottom: 5px;
           .label {
             font-size: 12px;
             color: #999;
+            margin-right: 4px;
           }
           .value {
             font-size: 14px;
@@ -880,16 +881,18 @@ onMounted(() => {
         }
       }
       .status-cell {
-        width: 120px;
-        border-left: 1px solid #f5f5f5;
+        width: 140px;
+        padding: 15px;
+        display: flex;
         align-items: flex-start;
-        gap: 5px;
+        justify-content: flex-end;
+        gap: 10px;
         .status-text {
           font-size: 14px;
           font-weight: 500;
         }
         .audit-status {
-          font-size: 12px;
+          font-size: 14px;
           &.success {
             color: #e60012;
           }

+ 127 - 2
src/views/trad/index.vue

@@ -10,7 +10,12 @@
         <span class="border"></span>
         <!-- <span>某某部门</span> -->
       </div>
-      <div class="address-title">收货地址</div>
+      <div class="address-title">
+        <div>收货地址</div>
+        <el-button type="danger" link @click="handleAdd">
+          <el-icon><Plus /></el-icon>新增收货地址
+        </el-button>
+      </div>
       <div class="address-bos">
         <div
           @click="onAddress(item)"
@@ -144,13 +149,43 @@
         </div>
       </div>
     </div>
+
+    <!-- 新增/编辑弹窗 -->
+    <el-dialog v-model="dialogVisible" title="新增收货地址" width="550px">
+      <el-form ref="formRef" :model="formAddress" :rules="rules" label-width="100px">
+        <el-form-item label="收货人" prop="name">
+          <el-input v-model="formAddress.name" placeholder="请输入收货人姓名" />
+        </el-form-item>
+        <el-form-item label="联系电话" prop="phone">
+          <el-input v-model="formAddress.phone" placeholder="请输入联系电话" />
+        </el-form-item>
+        <el-form-item label="所在地区" prop="region">
+          <el-cascader
+            v-model="formAddress.regionCodes"
+            :options="regionData as any"
+            placeholder="请选择省/市/区"
+            style="width: 100%"
+            @change="handleRegionChange"
+          />
+        </el-form-item>
+        <el-form-item label="详细地址" prop="address">
+          <el-input v-model="formAddress.address" type="textarea" :rows="2" placeholder="请输入详细地址" />
+        </el-form-item>
+        <el-form-item label="设为默认"><el-switch v-model="formAddress.isDefault" /></el-form-item>
+      </el-form>
+      <template #footer>
+        <el-button @click="dialogVisible = false">取消</el-button>
+        <el-button type="danger" @click="handleSave">确定</el-button>
+      </template>
+    </el-dialog>
   </div>
 </template>
 
 <script setup lang="ts">
-import { getAddressList } from '@/api/pc/enterprise';
+import { getAddressList, addAddress } from '@/api/pc/enterprise';
 import { shoppingCartList, pcOrdersubmit } from '@/api/goods/index';
 import { onPath } from '@/utils/siteConfig';
+import { regionData } from 'element-china-area-data';
 const route = useRoute();
 const ids = ref<any>('');
 const tableData = ref<any>([]);
@@ -175,6 +210,19 @@ const options = [
   }
 ];
 
+//收货地址
+const dialogVisible = ref(false);
+const formRef = ref();
+const formAddress = reactive({ name: '', phone: '', regionCodes: [], region: '', address: '', isDefault: false });
+const rules = {
+  name: [{ required: true, message: '请输入收货人姓名', trigger: 'blur' }],
+  phone: [
+    { required: true, message: '请输入联系电话', trigger: 'blur' },
+    { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
+  ],
+  address: [{ required: true, message: '请输入详细地址', trigger: 'blur' }]
+};
+
 onMounted(() => {
   ids.value = route.query.ids;
   form.value.productShoppingCartId = ids.value.split(',');
@@ -233,6 +281,80 @@ const onSubmit = () => {
   });
   console.log(form.value);
 };
+
+const handleAdd = () => {
+  resetForm();
+  dialogVisible.value = true;
+};
+
+const resetForm = () => {
+  formAddress.name = '';
+  formAddress.phone = '';
+  formAddress.regionCodes = [];
+  formAddress.region = '';
+  formAddress.address = '';
+  formAddress.isDefault = false;
+};
+
+// 处理地区选择变化
+const handleRegionChange = (value: string[]) => {
+  if (value && value.length === 3) {
+    // 根据选中的代码查找对应的名称
+
+    // 根据编码获取名称
+    const names: string[] = [];
+    if (value[0]) {
+      const province = regionData.find((item: any) => item.value === value[0]);
+      if (province) {
+        names.push(province.label);
+
+        if (value[1] && province.children) {
+          const city = province.children.find((item: any) => item.value === value[1]);
+          if (city) {
+            names.push(city.label);
+
+            if (value[2] && city.children) {
+              const county = city.children.find((item: any) => item.value === value[2]);
+              if (county) {
+                names.push(county.label);
+              }
+            }
+          }
+        }
+      }
+    }
+
+    // 将省市区名称用斜杠连接
+    formAddress.region = names.join('/');
+  }
+};
+const handleSave = async () => {
+  const valid = await formRef.value?.validate();
+  if (!valid) return;
+  try {
+    const data: any = {
+      consignee: formAddress.name,
+      phone: formAddress.phone,
+      address: formAddress.address,
+      isDefault: formAddress.isDefault
+    };
+
+    // 如果选择了省市区,发送代码
+    if (formAddress.regionCodes && formAddress.regionCodes.length === 3) {
+      data.provincialNo = formAddress.regionCodes[0];
+      data.cityNo = formAddress.regionCodes[1];
+      data.countryNo = formAddress.regionCodes[2];
+      data.provincialCityCountry = formAddress.region;
+    }
+
+    await addAddress(data);
+    ElMessage.success('新增成功');
+    dialogVisible.value = false;
+    loadAddressList();
+  } catch (error) {
+    ElMessage.error('操作失败');
+  }
+};
 </script>
 
 <style lang="scss" scoped>
@@ -269,6 +391,9 @@ const onSubmit = () => {
       font-size: 14px;
       color: #101828;
       margin: 30px 0 10px 0;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
     }
     .address-bos {
       display: flex;

+ 19 - 17
src/views/valueAdded/maintenance/apply.vue

@@ -189,8 +189,10 @@ onMounted(() => {
 
 <style scoped lang="scss">
 .maintenance-apply-container {
-  min-height: 100vh;
   background-color: #fff;
+  flex: 1;
+  border-radius: 4px;
+  padding: 20px;
 }
 
 .page-header {
@@ -428,9 +430,9 @@ onMounted(() => {
       transition: all 0.3s;
 
       &.active {
-        border-color: #409eff;
-        color: #409eff;
-        background-color: #ecf5ff;
+        border-color: var(--el-color-primary);
+        color: var(--el-color-primary);
+        // background-color: #ecf5ff;
       }
 
       &:hover {
@@ -445,19 +447,19 @@ onMounted(() => {
 }
 
 .next-btn {
-  background-color: #0fb881;
-  border-color: #0fb881;
-  color: #fff;
-  padding: 8px 25px;
-  border-radius: 2px;
-  font-weight: normal;
-
-  &:hover,
-  &:focus {
-    background-color: #12cc90;
-    border-color: #12cc90;
-    color: #fff;
-  }
+  // background-color: #0fb881;
+  // border-color: #0fb881;
+  // color: #fff;
+  // padding: 8px 25px;
+  // border-radius: 2px;
+  // font-weight: normal;
+
+  // &:hover,
+  // &:focus {
+  //   background-color: #12cc90;
+  //   border-color: #12cc90;
+  //   color: #fff;
+  // }
 }
 
 /* Override error styles to match exactly the mockup */

+ 1 - 0
src/views/valueAdded/maintenance/index.vue

@@ -32,6 +32,7 @@ const handleApply = () => {
   background: #fff;
   min-height: 100%;
   flex: 1;
+  border-radius: 4px;
 }
 
 .empty-state {

+ 24 - 2
vite.config.ts

@@ -20,12 +20,34 @@ export default defineConfig(({ mode, command }) => {
     plugins: createPlugins(env, command === 'build'),
     server: {
       host: '0.0.0.0',
+      allowedHosts: [
+        'www.yingpai365.com',
+        'b.yingpai365.com',
+        'mro.yingpai365.com',
+        'fuli.yingpai365.com',
+        'reg.yingpai365.com',
+        'breg.yingpai365.com',
+        'greg.yingpai365.com',
+        'passport.yingpai365.com',
+        'search.yingpai365.com',
+        'item.yingpai365.com',
+        'cart.yingpai365.com',
+        'trad.yingpai365.com',
+        'payc.yingpai365.com',
+        'order.yingpai365.com',
+        'plan.yingpai365.com',
+        'plan_info.yingpai365.com',
+        'i.yingpai365.com',
+        'easybuv.yingpai365.com'
+      ],
       port: Number(env.VITE_APP_PORT),
+      // port: Number(env.VITE_APP_PORT),
       open: true,
       proxy: {
         [env.VITE_APP_BASE_API]: {
-          // target: 'http://localhost:8080',
-          target: 'https://ceshi.xiaoluwebsite.xyz',
+          target: 'http://localhost:8080',
+          // target: 'http://yp1.yingpaipay.com:9026',
+          // target: 'https://jingyang.xiaoluwebsite.xyz',
           // target: 'http://192.168.1.52:8080',
           changeOrigin: true,
           ws: true,