hurx 1 mēnesi atpakaļ
vecāks
revīzija
49c71a1e08

+ 1 - 1
src/layout/components/header.vue

@@ -35,7 +35,7 @@ const goToLogin = () => {
 };
 
 const goToMyOrder = () => {
-  router.push('/enterprise/companyInfo');
+  onPath('/order/orderManage');
 };
 </script>
 

+ 4 - 1
src/utils/siteConfig.ts

@@ -75,7 +75,10 @@ export const SITE_ROUTES: Record<any, string[]> = {
     '/organization/approvalFlow/create',
     '/order/orderManage/detail/:orderNo',
     '/order/orderManage/applyAfter',
-    '/valueAdded/maintenanceApply'
+    '/valueAdded/maintenanceApply',
+    '/enterprise/messageNotice',
+    '/enterprise/securitySetting',
+    '/enterprise/securitySetting/resetPassword'
   ], //订单列表
 
   i: ['/i'], //个人信息

+ 30 - 30
src/views/enterprise/messageNotice/index.vue

@@ -3,12 +3,12 @@
     <PageTitle title="消息通知" />
 
     <!-- Tab切换 -->
-    <div class="tab-nav">
+    <!-- <div class="tab-nav">
       <div v-for="tab in tabs" :key="tab.key" :class="['tab-item', { active: activeTab === tab.key }]" @click="activeTab = tab.key">
         <el-icon><component :is="tab.icon" /></el-icon>
         <span>{{ tab.label }}</span>
       </div>
-    </div>
+    </div> -->
 
     <!-- 消息列表 -->
     <div class="message-list">
@@ -64,42 +64,42 @@ const messageList = ref<any[]>([]);
 const loadData = () => {
   if (activeTab.value === 'approval') {
     messageList.value = [
-      {
-        time: '2025/01/10 11:42:32',
-        title: '您有一个审批流程待处理',
-        desc: '审批名称:办公用品采购申请',
-        unread: true,
-        showAction: true,
-        iconType: 'user'
-      },
-      {
-        time: '2025/01/10 11:42:32',
-        title: '您的办公用品审批申请已通过',
-        desc: '审批名称:办公用品采购申请',
-        unread: true,
-        showAction: false,
-        iconType: 'user'
-      },
-      {
-        time: '2025/01/10 11:42:32',
-        title: '您的办公用品审批申请已通过',
-        desc: '审批名称:办公用品采购申请',
-        unread: true,
-        showAction: false,
-        iconType: 'user'
-      }
+      // {
+      //   time: '2025/01/10 11:42:32',
+      //   title: '您有一个审批流程待处理',
+      //   desc: '审批名称:办公用品采购申请',
+      //   unread: true,
+      //   showAction: true,
+      //   iconType: 'user'
+      // },
+      // {
+      //   time: '2025/01/10 11:42:32',
+      //   title: '您的办公用品审批申请已通过',
+      //   desc: '审批名称:办公用品采购申请',
+      //   unread: true,
+      //   showAction: false,
+      //   iconType: 'user'
+      // },
+      // {
+      //   time: '2025/01/10 11:42:32',
+      //   title: '您的办公用品审批申请已通过',
+      //   desc: '审批名称:办公用品采购申请',
+      //   unread: true,
+      //   showAction: false,
+      //   iconType: 'user'
+      // }
     ];
     total.value = 3;
   } else if (activeTab.value === 'arrival') {
     messageList.value = [
-      { time: '2025/01/10 11:42:32', title: '包裹到货提醒', desc: '物流状态:已到达代售点', unread: true, showAction: false, iconType: 'package' },
-      { time: '2025/01/10 11:42:32', title: '包裹到货提醒', desc: '物流状态:已到达代售点', unread: false, showAction: false, iconType: 'package' }
+      // { time: '2025/01/10 11:42:32', title: '包裹到货提醒', desc: '物流状态:已到达代售点', unread: true, showAction: false, iconType: 'package' },
+      // { time: '2025/01/10 11:42:32', title: '包裹到货提醒', desc: '物流状态:已到达代售点', unread: false, showAction: false, iconType: 'package' }
     ];
     total.value = 2;
   } else {
     messageList.value = [
-      { time: '2025/01/10 11:42:32', title: '预算预警', desc: '副标题副副标题', unread: true, showAction: false, iconType: 'budget' },
-      { time: '2025/01/10 11:42:32', title: '预算预警', desc: '副标题副副标题', unread: false, showAction: false, iconType: 'budget' }
+      // { time: '2025/01/10 11:42:32', title: '预算预警', desc: '副标题副副标题', unread: true, showAction: false, iconType: 'budget' },
+      // { time: '2025/01/10 11:42:32', title: '预算预警', desc: '副标题副副标题', unread: false, showAction: false, iconType: 'budget' }
     ];
     total.value = 2;
   }

+ 317 - 468
src/views/enterprise/purchaseHabit/index.vue

@@ -1,534 +1,383 @@
 <template>
-  <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="purchase-habit-container">
+    <!-- 顶部返回 -->
+    <div class="page-header">
+      <el-button link @click="handleBack">
+        <el-icon><ArrowLeft /></el-icon>
+        <span>返回</span>
+      </el-button>
+      <span class="page-title">企业采购习惯</span>
     </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>
-    <!-- Tab切换 -->
-    <div class="tab-bar">
-      <div class="tab-left">
-        <div v-for="tab in statusTabs" :key="tab.key" :class="['tab-item', { active: activeTab === tab.key }]" @click="activeTab = tab.key">
-          <el-icon><component :is="tab.icon" /></el-icon><span>{{ tab.label }}</span>
-        </div>
-      </div>
-    </div>
-    <!-- 订单列表 -->
-    <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="primary" link class="expand-btn" @click="handleExpand(order)"
-            >{{ order.expanded ? '收起' : '展开' }} <el-icon><ArrowDown /></el-icon
-          ></el-button>
-        </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 class="product-image">
-                <el-image :src="item.image" fit="contain"
-                  ><template #error
-                    ><div class="image-placeholder">
-                      <el-icon :size="30" color="#ccc"><Picture /></el-icon></div></template
-                ></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-price">¥{{ item.price }}</div>
-              </div>
-              <div class="product-quantity">x{{ item.quantity }}</div>
+
+    <div class="page-content">
+      <el-form ref="formRef" :model="form" label-position="top">
+        <!-- 采购金额 -->
+        <el-row :gutter="40">
+          <el-col :span="12">
+            <el-form-item label="月度采购金额">
+              <el-input v-model="form.monthlyAmount" placeholder="请输入">
+                <template #suffix>万</template>
+              </el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="年度采购金额">
+              <el-input v-model="form.yearlyAmount" placeholder="请输入">
+                <template #suffix>万</template>
+              </el-input>
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <!-- 产品选型 -->
+        <el-form-item label="产品选型">
+          <div class="tag-group">
+            <div
+              v-for="item in productTypeOptions"
+              :key="item"
+              :class="['tag-item', { active: form.productTypes.includes(item) }]"
+              @click="toggleTag(form.productTypes, item)"
+            >
+              {{ item }}
             </div>
-            <div class="product-cell amount-cell" v-if="itemIndex === 0">
-              <div class="amount-info">
-                <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>
+        </el-form-item>
+
+        <!-- 日常打印量 -->
+        <el-form-item label="日常打印量">
+          <div class="tag-group">
+            <div
+              v-for="item in printVolumeOptions"
+              :key="item"
+              :class="['tag-item', { active: form.printVolume === item }]"
+              @click="form.printVolume = item"
+            >
+              {{ item }}
             </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>
+        </el-form-item>
+
+        <!-- 购买原装耗材 & 专人进行技术服务 -->
+        <el-row :gutter="40">
+          <el-col :span="12">
+            <el-form-item label="购买原装耗材">
+              <el-radio-group v-model="form.buyOriginal">
+                <el-radio v-for="dict in sys_platform_yes_no" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="专人进行技术服务">
+              <el-radio-group v-model="form.technologyService">
+                <el-radio v-for="dict in sys_platform_yes_no" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <!-- 主要办公采购类目 -->
+        <el-form-item label="主要办公采购类目">
+          <div class="tag-group">
+            <div
+              v-for="item in categoryOptions"
+              :key="item"
+              :class="['tag-item', { active: form.categories.includes(item) }]"
+              @click="toggleTag(form.categories, item)"
+            >
+              {{ item }}
             </div>
           </div>
-        </div>
+          <el-input v-model="form.otherCategory" placeholder="其他采购类目" maxlength="50" show-word-limit class="other-input" />
+        </el-form-item>
+
+        <!-- 企业福利 -->
+        <el-form-item label="企业福利">
+          <div class="tag-group">
+            <div
+              v-for="item in welfareOptions"
+              :key="item"
+              :class="['tag-item', { active: form.welfares.includes(item) }]"
+              @click="toggleTag(form.welfares, item)"
+            >
+              {{ item }}
+            </div>
+          </div>
+          <el-input v-model="form.otherScene" placeholder="其他福利" maxlength="50" show-word-limit class="other-input" />
+        </el-form-item>
+
+        <!-- 产品定制需求 -->
+        <el-form-item label="产品定制需求">
+          <div class="tag-group">
+            <div
+              v-for="item in customOptions"
+              :key="item"
+              :class="['tag-item', { active: form.customs.includes(item) }]"
+              @click="toggleTag(form.customs, item)"
+            >
+              {{ item }}
+            </div>
+          </div>
+          <el-input v-model="form.otherCustomize" placeholder="其他需求" maxlength="50" show-word-limit class="other-input" />
+        </el-form-item>
+      </el-form>
+
+      <!-- 底部按钮 -->
+      <div class="form-footer">
+        <el-button type="danger" @click="handleSave">保存</el-button>
+        <el-button @click="handleBack">取消</el-button>
       </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" />
   </div>
 </template>
 
 <script setup lang="ts">
-import { ref, reactive, computed, onMounted, watch } from 'vue';
+import { reactive, getCurrentInstance, toRefs, onMounted, ComponentInternalInstance, computed } from 'vue';
 import { useRouter } from 'vue-router';
-import { Search, ArrowDown, Document, Clock, Box, CircleCheck, CircleClose, Picture } from '@element-plus/icons-vue';
-import { TablePagination } from '@/components';
-import { getOrderList, getOrderProducts } from '@/api/pc/enterprise/order';
-import type { OrderMain } from '@/api/pc/enterprise/orderTypes';
+import { ArrowLeft } from '@element-plus/icons-vue';
 import { ElMessage } from 'element-plus';
-import { getDeptTree } from '@/api/pc/organization';
-import { DeptInfo } from '@/api/pc/organization/types';
+import { updatePurchaseHabit, getCustomerPurchaseHabitData } from '@/api/pc/enterprise/purchaseHabit';
+
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { order_status, pay_method } = toRefs<any>(proxy?.useDict('order_status', 'pay_method'));
+const { welfare_item, sys_platform_yes_no, product_types_choosing, purchase_item, product_customization, daily_print_volume } = toRefs<any>(
+  proxy?.useDict('welfare_item', 'sys_platform_yes_no', 'product_types_choosing', 'purchase_item', 'product_customization', 'daily_print_volume')
+);
 
 const router = useRouter();
-const activeTab = ref('all');
-const loading = ref(false);
-
-const deptList = ref([]);
 
-const statusTabs = [
-  { key: 'all', label: '全部订单', icon: Document },
-  { key: 'preOrder', label: '预下单', icon: Clock },
-  { key: 'shipping', label: '待收货', icon: Box },
-  { key: 'completed', label: '已完成', icon: CircleCheck },
-  { key: 'cancelled', label: '已取消', icon: CircleClose }
-];
+// 根据字典数据生成选项
+const productTypeOptions = computed(() => product_types_choosing.value?.map((item: any) => item.label) || []);
+const printVolumeOptions = computed(() => daily_print_volume.value?.map((item: any) => item.label) || []);
+const categoryOptions = computed(() => purchase_item.value?.map((item: any) => item.label) || []);
+const welfareOptions = computed(() => welfare_item.value?.map((item: any) => item.label) || []);
+const customOptions = computed(() => product_customization.value?.map((item: any) => item.label) || []);
 
-// 监听标签页切换,重置页码并重新获取数据
-watch(activeTab, (newTab) => {
-  queryParams.pageNum = 1;
-  // 根据标签页设置后端查询的状态参数
-  if (newTab === 'all') {
-    queryParams.status = '';
-  } else {
-    // 将前端标签页key映射回后端状态值
-    const tabToStatusMap: Record<string, string> = {
-      'preOrder': '0', // 待支付
-      'shipping': '4', // 待发货,部分发货,发货完成
-      'completed': '5', // 已完成
-      'cancelled': '7' // 已关闭,已取消
-    };
-    queryParams.status = tabToStatusMap[newTab] || '';
-  }
-  fetchOrderList();
+const form = reactive({
+  id: undefined,
+  customerId: undefined,
+  customerNo: '',
+  permanentOfficer: '',
+  monthlyAmount: '',
+  yearlyAmount: '',
+  productTypes: [] as string[],
+  printVolume: '',
+  printAmount: '',
+  buyOriginal: '',
+  technologyService: '',
+  categories: [] as string[],
+  otherCategory: '',
+  welfares: [] as string[],
+  customs: [] as string[],
+  adaptScenes: [] as string[],
+  otherScene: '',
+  otherCustomize: '',
+  choiceModel: '',
+  remark: ''
 });
 
-const queryParams = reactive({ keyword: '', dateRange: null, department: '', status: '', payType: '', pageNum: 1, pageSize: 5 });
-const total = ref(0);
-const allOrders = ref<any[]>([]);
-
-// 将后端状态映射为前端标签页key
-const mapBackendStatusToTabKey = (backendStatus: string) => {
-  const statusMap: Record<string, string> = {
-    '0': 'preOrder', // 待支付
-    '1': 'preOrder', // 待确认
-    '2': 'shipping', // 待发货
-    '3': 'shipping', // 部分发货
-    '4': 'shipping', // 发货完成
-    '5': 'completed', // 已完成
-    '6': 'cancelled', // 已关闭
-    '7': 'cancelled' // 已取消
-  };
-  return statusMap[backendStatus] || backendStatus;
+const toggleTag = (arr: string[], item: string) => {
+  const index = arr.indexOf(item);
+  if (index > -1) arr.splice(index, 1);
+  else arr.push(item);
 };
-
-// 根据订单状态获取状态文本
-const getStatusText = (status: string) => {
-  const statusMap: Record<string, string> = {
-    '0': '待支付',
-    '1': '待确认',
-    '2': '待发货',
-    '3': '部分发货',
-    '4': '发货完成',
-    '5': '已完成',
-    '6': '已关闭',
-    '7': '已取消'
-  };
-  return statusMap[status] || status;
+const handleBack = () => {
+  router.push('/enterprise/companyInfo');
 };
-
-// 加载部门树
-const loadDeptTree = async () => {
+const handleSave = async () => {
   try {
-    const res = await getDeptTree();
-    if (res.code === 200 && res.data) {
-      deptList.value = res.data;
+    // 将表单数据映射为接口所需格式
+    const submitData = {
+      id: form.id,
+      customerId: form.customerId,
+      customerNo: form.customerNo,
+      monthPurchase: form.monthlyAmount ? parseFloat(form.monthlyAmount) : undefined,
+      yearPurchase: form.yearlyAmount ? parseFloat(form.yearlyAmount) : undefined,
+      permanentOfficer: form.permanentOfficer,
+      choiceModel: form.productTypes.length > 0 ? product_types_choosing.value?.find((i: any) => i.label === form.productTypes[0])?.value || '' : '',
+      printAmount: form.printVolume ? daily_print_volume.value?.find((i: any) => i.label === form.printVolume)?.value || '' : '',
+      buyOriginal: form.buyOriginal,
+      technologyService: form.technologyService,
+      purchaseCategory:
+        form.categories.length > 0
+          ? form.categories
+              .map((label) => {
+                const item = purchase_item.value?.find((i: any) => i.label === label);
+                return item ? item.value : '';
+              })
+              .filter(Boolean)
+              .join(',')
+          : undefined,
+      otherCategory: form.otherCategory || undefined,
+      adaptScene:
+        form.welfares.length > 0
+          ? form.welfares
+              .map((label) => {
+                const item = welfare_item.value?.find((i: any) => i.label === label);
+                return item ? item.value : '';
+              })
+              .filter(Boolean)
+              .join(',')
+          : undefined,
+      otherScene: form.otherScene || undefined,
+      customizeDemand:
+        form.customs.length > 0
+          ? form.customs
+              .map((label) => {
+                const item = product_customization.value?.find((i: any) => i.label === label);
+                return item ? item.value : '';
+              })
+              .filter(Boolean)
+              .join(',')
+          : undefined,
+      otherCustomize: form.otherCustomize || undefined,
+      remark: form.remark || undefined
+    };
 
-      if (Array.isArray(res.data)) {
-        const treeData = proxy?.handleTree<DeptInfo>(res.data, 'deptId', 'parentId');
-        deptList.value = treeData || res.data;
-      } else {
-        deptList.value = [];
-      }
-    }
+    await updatePurchaseHabit(submitData);
+    ElMessage.success('保存成功');
+    handleBack();
   } catch (error) {
-    console.error('获取部门树失败:', error);
-    ElMessage.error('获取部门树失败');
+    ElMessage.error('保存失败');
   }
 };
 
-// 获取订单列表
-const fetchOrderList = async () => {
-  loading.value = true;
+const getPurchaseHabitData = async () => {
   try {
-    const params: any = {
-      pageNum: queryParams.pageNum,
-      pageSize: queryParams.pageSize
-    };
+    const res = await getCustomerPurchaseHabitData();
+    if (res.code === 200 && res.data) {
+      const data = res.data;
 
-    // 添加筛选条件
-    if (queryParams.keyword) params.orderNo = queryParams.keyword;
-    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];
-    }
+      // 映射数据到表单
+      form.id = data.id;
+      form.customerId = data.customerId;
+      form.customerNo = data.customerNo || '';
+      form.permanentOfficer = data.permanentOfficer || '';
+      form.monthlyAmount = data.monthPurchase || '';
+      form.yearlyAmount = data.yearPurchase || '';
 
-    const res = await getOrderList(params);
-    if (res.code === 200) {
-      // 将后端数据转换为前端需要的格式
-      allOrders.value = (res.rows || []).map((order: OrderMain) => ({
-        id: order.id,
-        orderTime: order.createTime,
-        orderNo: order.orderNo,
-        orderPerson: order.customerName, // 需要关联用户信息
-        department: order.createDeptName, // 需要关联部门信息
-        payAmount: order.payableAmount || 0,
-        freight: order.shippingFee || 0,
-        status: mapBackendStatusToTabKey(order.orderStatus || ''),
-        statusText: getStatusText(order.orderStatus || ''),
-        countdown: '',
-        auditStatus: order.checkStatus,
-        fileCount: 0,
-        expanded: false,
-        products: [] // 商品信息需要单独加载
-      }));
+      // 处理产品选型(单选)
+      form.productTypes = data.choiceModel ? [product_types_choosing.value?.find((i: any) => i.value === data.choiceModel)?.label || ''] : [];
 
-      total.value = res.total || 0;
-    }
-  } catch (error) {
-    console.error('获取订单列表失败:', error);
-  } finally {
-    loading.value = false;
-  }
-};
+      // 处理日常打印量(单选)
+      form.printVolume = data.printAmount ? daily_print_volume.value?.find((i: any) => i.value === data.printAmount)?.label || '' : '';
 
-const orderList = computed(() => allOrders.value);
+      form.categories = data.purchaseCategory
+        ? data.purchaseCategory
+            .split(',')
+            .map((id: string) => {
+              const item = purchase_item.value?.find((i: any) => i.value === id);
+              return item ? item.label : '';
+            })
+            .filter(Boolean)
+        : [];
 
-const getStatusColor = (status: string) =>
-  ({ completed: '#67c23a', preOrder: '#e6a23c', shipping: '#409eff', cancelled: '#909399' })[status] || '#909399';
-const getAuditStatusClass = (auditStatus: string) => (auditStatus === '审批通过' ? 'success' : auditStatus === '审批驳回' ? 'danger' : 'warning');
+      form.welfares = data.adaptScene
+        ? data.adaptScene
+            .split(',')
+            .map((id: string) => {
+              const item = welfare_item.value?.find((i: any) => i.value === id);
+              return item ? item.label : '';
+            })
+            .filter(Boolean)
+        : [];
 
-const handleExpand = async (order: any) => {
-  const orderIndex = allOrders.value.findIndex((o) => o.id === order.id);
-  if (orderIndex === -1) return;
+      form.customs = data.customizeDemand
+        ? data.customizeDemand
+            .split(',')
+            .map((id: string) => {
+              const item = product_customization.value?.find((i: any) => i.value === id);
+              return item ? item.label : '';
+            })
+            .filter(Boolean)
+        : [];
 
-  const currentOrder = allOrders.value[orderIndex];
+      // 处理单选字段
+      form.printAmount = data.printAmount || '';
 
-  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) => ({
-          image: p.productImage || '',
-          name: p.productName || '',
-          spec1: p.productUnit || '',
-          spec2: p.productNo || '',
-          price: p.orderPrice || 0,
-          quantity: p.orderQuantity || 0
-        }));
+      form.buyOriginal = data.buyOriginal || '';
 
-        // 替换整个数组以触发响应式更新
-        allOrders.value = allOrders.value.map((o, i) => (i === orderIndex ? { ...o, expanded: true, products } : o));
-        return;
-      }
-    } catch (error) {
-      console.error('加载商品失败:', error);
-      return;
-    }
-  }
+      form.technologyService = data.technologyService;
 
-  // 替换整个数组以触发响应式更新
-  allOrders.value = allOrders.value.map((o, i) => (i === orderIndex ? { ...o, expanded: !o.expanded } : o));
-};
+      form.choiceModel = data.choiceModel || '';
 
-const handleViewDetail = (order: any) => {
-  router.push(`/order/orderManage/detail/${order.orderNo}`);
-};
-const handleQuery = () => {
-  queryParams.pageNum = 1;
-  fetchOrderList();
-};
-const handleReset = () => {
-  queryParams.keyword = '';
-  queryParams.dateRange = null;
-  queryParams.department = '';
-  queryParams.payType = '';
-  queryParams.pageNum = 1;
-  fetchOrderList();
+      // 其他字段
+      form.otherCategory = data.otherCategory || '';
+      form.otherCustomize = data.otherCustomize || '';
+      form.otherScene = data.otherScene || '';
+      form.otherCustomize = data.otherCustomize || '';
+      form.remark = data.remark || '';
+    }
+  } catch (error) {
+    console.error('获取采购习惯数据失败:', error);
+    ElMessage.error('获取数据失败');
+  }
 };
 
-// 页面加载时获取订单列表
 onMounted(() => {
-  loadDeptTree();
-  fetchOrderList();
+  getPurchaseHabitData();
 });
 </script>
 
 <style scoped lang="scss">
-.order-manage-container {
-  padding: 20px;
-  background: #fff;
+.purchase-habit-container {
+  background: #f5f5f5;
   min-height: 100%;
-  display: flex;
-  flex-direction: column;
-  max-height: calc(100vh - 120px);
-  flex: 1;
 }
-.page-title {
-  font-size: 16px;
-  font-weight: bold;
-  display: flex;
-  align-items: center;
-  gap: 8px;
-  margin-bottom: 20px;
-}
-.title-bar {
-  display: inline-block;
-  width: 3px;
-  height: 16px;
-  background: #e60012;
-  border-radius: 2px;
-}
-.search-bar {
-  display: flex;
-  align-items: center;
-  gap: 15px;
-  margin-bottom: 15px;
-}
-.filter-bar {
+.page-header {
+  background: #fff;
+  padding: 15px 20px;
   display: flex;
   align-items: center;
   gap: 10px;
-  margin-bottom: 15px;
-  .filter-label {
-    font-size: 14px;
-    color: #666;
+  border-bottom: 1px solid #eee;
+  .page-title {
+    font-size: 16px;
+    font-weight: bold;
+    color: #333;
   }
 }
-.tab-bar {
+.page-content {
+  padding: 20px;
+  background: #fff;
+  margin: 20px;
+  border-radius: 8px;
+}
+.tag-group {
   display: flex;
-  justify-content: space-between;
-  align-items: center;
-  border-bottom: 1px solid #eee;
-  margin-bottom: 15px;
-  .tab-left {
-    display: flex;
-    gap: 25px;
-  }
-  .tab-item {
-    display: flex;
-    align-items: center;
-    gap: 5px;
-    padding: 12px 0;
+  flex-wrap: wrap;
+  gap: 10px;
+  .tag-item {
+    padding: 8px 20px;
+    border: 1px solid #ddd;
+    border-radius: 4px;
     cursor: pointer;
-    color: #666;
     font-size: 14px;
-    border-bottom: 2px solid transparent;
-    margin-bottom: -1px;
-    &:hover,
-    &.active {
-      color: #333;
+    color: #666;
+    transition: all 0.2s;
+    &:hover {
+      border-color: #e60012;
+      color: #e60012;
     }
     &.active {
-      border-bottom-color: #e60012;
+      border-color: #e60012;
+      color: #e60012;
+      background: #fff5f5;
     }
   }
 }
-.order-list {
-  flex: 1;
-  overflow-y: auto;
-  margin-bottom: 15px;
-  .order-card {
-    border: 1px solid #eee;
-    border-radius: 4px;
-    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;
-      }
-      .expand-btn {
-        margin-left: auto;
-      }
-    }
-    .countdown-bar {
-      background: #fff5e6;
-      color: #e6a23c;
-      padding: 8px 15px;
-      font-size: 13px;
-      border-bottom: 1px solid #eee;
-    }
-    .product-list {
-      .product-row {
-        display: flex;
-        border-bottom: 1px solid #f5f5f5;
-        &:last-child {
-          border-bottom: none;
-        }
-      }
-      .product-cell {
-        padding: 15px;
-        display: flex;
-        flex-direction: column;
-        justify-content: center;
-      }
-      .product-info-cell {
-        flex: 1;
-        flex-direction: row;
-        align-items: center;
-        gap: 15px;
-        .product-image {
-          width: 80px;
-          height: 80px;
-          background: #f5f5f5;
-          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-detail {
-          flex: 1;
-          .product-name {
-            font-size: 14px;
-            color: #333;
-            margin-bottom: 5px;
-            line-height: 1.4;
-          }
-          .product-spec {
-            font-size: 12px;
-            color: #999;
-            margin-bottom: 5px;
-          }
-          .product-price {
-            font-size: 16px;
-            font-weight: bold;
-            color: #e60012;
-          }
-        }
-        .product-quantity {
-          font-size: 13px;
-          color: #666;
-        }
-      }
-      .amount-cell {
-        width: 120px;
-        border-left: 1px solid #f5f5f5;
-        .amount-info {
-          margin-bottom: 5px;
-          .label {
-            font-size: 12px;
-            color: #999;
-          }
-          .value {
-            font-size: 14px;
-            color: #333;
-            &.highlight {
-              font-size: 16px;
-              font-weight: bold;
-              color: #e60012;
-            }
-          }
-        }
-      }
-      .status-cell {
-        width: 120px;
-        border-left: 1px solid #f5f5f5;
-        align-items: flex-start;
-        gap: 5px;
-        .status-text {
-          font-size: 14px;
-          font-weight: 500;
-        }
-        .audit-status {
-          font-size: 12px;
-          &.success {
-            color: #e60012;
-          }
-          &.warning {
-            color: #e6a23c;
-          }
-          &.danger {
-            color: #e60012;
-          }
-        }
-      }
-    }
-  }
+.other-input {
+  margin-top: 10px;
+}
+.form-footer {
+  text-align: center;
+  padding-top: 30px;
+  border-top: 1px solid #eee;
+  margin-top: 20px;
+}
+:deep(.el-form-item__label) {
+  font-weight: 500;
+  color: #333;
 }
-:deep(.table-pagination) {
-  flex-shrink: 0;
-  margin-top: 15px;
+:deep(.el-radio) {
+  margin-right: 30px;
 }
 </style>

+ 17 - 6
src/views/enterprise/securitySetting/index.vue

@@ -16,8 +16,8 @@
           <el-icon :size="30" color="#999"><OfficeBuilding /></el-icon>
         </div>
         <div class="company-info">
-          <div class="company-name">{{ companyData.companyName }}</div>
-          <el-tag type="danger" size="small">{{ companyData.role }}</el-tag>
+          <div class="company-name">{{ companyData.contactName }}</div>
+          <!-- <el-tag type="danger" size="small">{{ companyData.role }}</el-tag> -->
         </div>
       </div>
 
@@ -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>
 
     <!-- 修改密码弹窗 -->
@@ -93,11 +93,12 @@ import { ref, reactive } from 'vue';
 import { useRouter } from 'vue-router';
 import { ArrowLeft, OfficeBuilding, Grid } from '@element-plus/icons-vue';
 import { ElMessage } from 'element-plus';
+import { getCurrentUserInfo, updateComStaff } from '@/api/pc/organization/index';
 
 const router = useRouter();
 
-const companyData = reactive({ companyName: '中国南方电网', role: '采购负责人' });
-const securityData = reactive({ phone: '180****7722' });
+const companyData = reactive({ contactName: '', role: '' });
+const securityData = reactive({ phone: '' });
 
 const passwordDialogVisible = ref(false);
 const passwordFormRef = ref();
@@ -142,6 +143,13 @@ const handleBack = () => {
 const handleModifyPassword = () => {
   router.push('/enterprise/securitySetting/resetPassword');
 };
+const getCurrentUser = async () => {
+  const res = await getCurrentUserInfo();
+  companyData.contactName = res.data.contactName;
+  companyData.role = res.data.roleName;
+  securityData.phone = res.data.phone;
+  phoneForm.phone = res.data.phone;
+};
 const handleSavePassword = async () => {
   const valid = await passwordFormRef.value?.validate();
   if (!valid) return;
@@ -169,6 +177,9 @@ const handleSavePhone = async () => {
   ElMessage.success('手机号修改成功');
   phoneDialogVisible.value = false;
 };
+onMounted(() => {
+  getCurrentUser();
+});
 </script>
 
 <style scoped lang="scss">

+ 39 - 30
src/views/order/orderManage/index.vue

@@ -91,13 +91,13 @@
             @click="handleAction(action, order)"
             >{{ action }}</el-button
           >
-          <el-button type="primary" link class="expand-btn" @click="handleExpand(order)"
+          <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>
         <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 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-image">
                 <el-image :src="item.image" fit="contain"
@@ -146,7 +146,12 @@
           </div>
         </div>
         <!-- 显示更多商品提示 -->
-        <div v-if="!order.expanded && order.products.length > 1" class="more-products-hint">
+        <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>
@@ -281,7 +286,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[]>([]);
 
@@ -371,7 +376,7 @@ 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) {
+    if (queryParams.dateRange && queryParams.dateRange.length == 2) {
       params.beginTime = queryParams.dateRange[0];
       params.endTime = queryParams.dateRange[1];
     }
@@ -386,6 +391,34 @@ const fetchOrderList = async () => {
         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,
@@ -402,7 +435,7 @@ const fetchOrderList = async () => {
         fileCount: 0,
         checked: false,
         expanded: false,
-        products: [] // 商品信息需要单独加载
+        products: orderProductsMap[order.id] || [] // 商品信息已加载
       }));
 
       // 调试:打印转换后的订单状态
@@ -477,30 +510,6 @@ 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) => ({
-          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));
 };

+ 1 - 1
src/views/organization/deptManage/index.vue

@@ -141,7 +141,7 @@ const handleEdit = (row: any) => {
   parentRow.value = null;
   formData.deptId = row.deptId;
   formData.deptName = row.deptName;
-  formData.parentId = row.parentId;
+  formData.parentId = row.parentId == 100 ? undefined : row.parentId;
   formData.status = row.status || '0';
   formData.yearlyBudget = row.yearlyBudget || 0;
   formData.parentName = '';

+ 30 - 7
src/views/organization/staffManage/index.vue

@@ -23,7 +23,7 @@
       <div class="staff-list">
         <!-- 操作栏 -->
         <div class="action-bar">
-          <el-input v-model="queryParams.keyword" placeholder="搜索员工姓名" style="width: 200px" clearable @keyup.enter="handleQuery">
+          <el-input v-model="queryParams.contactName" placeholder="搜索员工姓名" style="width: 200px" clearable @keyup.enter="handleQuery">
             <template #prefix
               ><el-icon><Search /></el-icon
             ></template>
@@ -76,6 +76,8 @@
             node-key="deptId"
             placeholder="请选择部门"
             style="width: 100%"
+            check-strictly
+            :render-after-expand="false"
             @change="handleDeptChange"
           />
         </el-form-item>
@@ -87,7 +89,7 @@
         <el-form-item label="状态">
           <el-radio-group v-model="formData.status">
             <el-radio label="0">启用</el-radio>
-            <el-radio label="1">用</el-radio>
+            <el-radio label="1">用</el-radio>
           </el-radio-group>
         </el-form-item>
       </el-form>
@@ -113,12 +115,13 @@ const formRef = ref();
 const editingRow = ref<any>(null);
 const selectedRows = ref<any[]>([]);
 
-const queryParams = reactive({ pageNum: 1, pageSize: 10, deptId: null as number | null, keyword: '' });
+const queryParams = reactive({ pageNum: 1, pageSize: 10, deptId: null as number | null, contactName: '' });
 const total = ref(0);
 
 const deptTreeData = ref<DeptInfo[]>([]);
 
 const formData = reactive({
+  id: null,
   contactName: '',
   phone: '',
   deptId: null as number | null,
@@ -172,10 +175,29 @@ const loadRoleList = async () => {
   }
 };
 
-const handleDeptChange = (value: number) => {
-  const selectedDept = deptTreeData.value.find((item) => item.deptId === value);
+const handleDeptChange = (value: any) => {
+  console.log(value);
+  // 定义递归查找函数
+  const findNode = (nodes: any[], id: any): any => {
+    for (const node of nodes) {
+      // 类型转换后比较
+      if (String(node.deptId) === String(id)) {
+        return node;
+      }
+      // 如果有子节点,递归查找
+      if (node.children && node.children.length > 0) {
+        const found = findNode(node.children, id);
+        if (found) return found;
+      }
+    }
+    return null;
+  };
+
+  const selectedDept = findNode(deptTreeData.value, value);
+
   if (selectedDept) {
     formData.deptName = selectedDept.deptName;
+    formData.deptId = selectedDept.deptId;
   }
 };
 
@@ -195,7 +217,7 @@ const loadContactList = async () => {
     };
 
     if (queryParams.deptId) params.deptId = queryParams.deptId;
-    if (queryParams.keyword) params.keyword = queryParams.keyword;
+    if (queryParams.contactName) params.contactName = queryParams.contactName;
 
     const res = await getContactList(params);
     if (res.code === 200) {
@@ -236,11 +258,12 @@ const handleAdd = () => {
 
 const handleEdit = (row: any) => {
   editingRow.value = row;
+  formData.id = row.id;
   formData.contactName = row.contactName;
   formData.phone = row.phone;
   formData.deptId = row.deptId;
   formData.roleId = row.roleId;
-  formData.status = row.statusValue;
+  formData.status = row.status;
   dialogVisible.value = true;
 };