周宾
8 天以前 8845ac3d32217b6cf765934dc29dffe0065232d8
src/pages/productionManagement/productionDispatching/index.vue
@@ -2,109 +2,232 @@
   <view class="production-dispatching">
      <!-- 使用通用页面头部组件 -->
      <PageHeader title="生产派工" @back="goBack" />
      <!-- 炒机状态展示 -->
      <view class="machines-section">
         <view class="section-title">炒机状态</view>
         <view class="machines-grid">
            <view v-for="machine in machines" :key="machine.id" class="machine-card">
               <view class="machine-title">炒机{{ machine.id }}</view>
               <view class="machine-metrics">
                  <view class="metric-item">
                     <text class="metric-label">总量(kg)</text>
                     <up-input
                        v-model="machineTotal[machine.key]"
                        type="number"
                        placeholder="请输入总量"
                        border="surround"
                        size="mini"
                        class="metric-input"
                        @change="updateMachineVacant(machine.key)"
                     />
                  </view>
                  <view class="metric-item">
                     <text class="metric-label">正在生产(kg)</text>
                     <text class="metric-value">{{ machineInProduction[machine.key] }}</text>
                  </view>
                  <view class="metric-item">
                     <text class="metric-label">空余量(kg)</text>
                     <text class="metric-value">{{ machineVacant[machine.key] }}</text>
                  </view>
               </view>
            </view>
         </view>
         <!-- 损耗率设置 -->
      <view class="loss-rate-section">
         <view class="section-title">损耗率设置</view>
         <view class="loss-rate-content">
            <view class="loss-rate-item">
               <up-button
                  class="loss-rate-btn"
                  type="primary"
                  plain
                  size="small"
                  @click="showLossRateSheet = true"
               >{{ lossRate ? `损耗率: ${lossRate}%` : '请选择损耗率' }}</up-button>
               <up-action-sheet
               :show="showLossRateSheet"
               :actions="lossRateOptions"
               @select="onLossRateSelect"
               title="选择损耗率"
               @close="showLossRateSheet = false"
            />
            </view>
         </view>
      </view>
         <view class="save-section">
            <up-button type="primary" @click="saveMachineTotals" size="normal" class="save-btn">保存炒机设置</up-button>
         </view>
      </view>
      
      <!-- 搜索区域 -->
      <view class="search-section">
         <view class="search-bar">
            <view class="search-input">
         <view class="search-form">
            <view class="search-item">
               <text class="search-label">客户名称</text>
               <up-input
                  class="search-text"
                  placeholder="请输入客户名称搜索"
                  v-model="searchForm.customerName"
                  placeholder="请输入客户名称"
                  @change="handleQuery"
                  clearable
                  border="surround"
                  class="search-input"
               />
            </view>
            <view class="filter-button" @click="handleQuery">
               <up-icon name="search" size="24" color="#999"></up-icon>
            <view class="search-item">
               <text class="search-label">项目名称</text>
               <up-input
                  v-model="searchForm.projectName"
                  placeholder="请输入项目名称"
                  @change="handleQuery"
                  clearable
                  border="surround"
                  class="search-input"
               />
            </view>
            <view class="search-buttons">
               <up-button type="primary" @click="handleQuery" size="small" class="search-btn">搜索</up-button>
               <up-button @click="handleReset" size="small" class="reset-btn">重置</up-button>
            </view>
         </view>
      </view>
      
      <!-- 批量操作区域 -->
      <view class="batch-actions-section" v-if="showBatchActions">
         <view class="batch-info">
            <text class="batch-text">已选择 {{ selectedItems.length }} 个项目</text>
         </view>
         <view class="batch-buttons">
            <up-button type="primary" size="small" @click="handleAutoDispatch" class="batch-btn">自动派单</up-button>
            <up-button type="default" size="small" @click="clearSelection" class="batch-btn">取消选择</up-button>
         </view>
      </view>
      <!-- 全选操作区域 -->
      <view class="select-all-section" v-if="tableData.length > 0">
         <view class="select-all-content">
            <up-checkbox
            v-model="isAllSelected"
            @change="toggleAllSelection"
            label="全选"
            class="select-all-checkbox"
            :disabled="tableData.length === 0 || tableData.filter(item => item.pendingQuantity > 0 && item.speculativeTradingName).length === 0"
         />
         </view>
      </view>
      <!-- 生产派工列表 -->
      <view class="ledger-list" v-if="tableData.length > 0">
         <view v-for="(item, index) in tableData" :key="item.id || index">
         <view v-for="(item, index) in tableData" :key="item.id || index" class="list-item">
            <view class="ledger-item">
               <view class="item-header">
                  <view class="item-left">
                     <view class="document-icon">
                        <up-icon name="file-text" size="16" color="#ffffff"></up-icon>
               <!-- 选择复选框 -->
               <view class="item-checkbox">
                  <up-checkbox
               :model-value="selectedItems.some(selected => selected.id === item.id)"
               @change="(checked) => toggleItemSelection(item, checked)"
               :disabled="item.pendingQuantity <= 0 || !item.speculativeTradingName"
               shape="circle"
            />
               </view>
               <view class="item-content">
                  <view class="item-header">
                     <view class="item-left">
                        <view class="document-icon">
                           <up-icon name="file-text" size="16" color="#ffffff"></up-icon>
                        </view>
                        <text class="item-id">{{ item.salesContractNo }}</text>
                     </view>
                     <text class="item-id">{{ item.salesContractNo }}</text>
                     <text class="entry-date">{{ item.entryDate }}</text>
                  </view>
               </view>
               <up-divider></up-divider>
               
               <view class="item-details">
                  <view class="detail-row">
                     <text class="detail-label">录入日期</text>
                     <text class="detail-value">{{ item.entryDate }}</text>
                  <view class="item-details">
                     <!-- <view class="detail-row">
                        <text class="detail-label">客户合同号</text>
                        <text class="detail-value">{{ item.customerContractNo }}</text>
                     </view> -->
                     <view class="detail-row">
                        <text class="detail-label">客户名称</text>
                        <text class="detail-value">{{ item.customerName }}</text>
                     </view>
                     <!-- <view class="detail-row">
                        <text class="detail-label">项目名称</text>
                        <text class="detail-value">{{ item.projectName }}</text>
                     </view> -->
                     <view class="detail-row">
                        <text class="detail-label">产品大类</text>
                        <text class="detail-value">{{ item.productCategory }}</text>
                     </view>
                     <view class="detail-row">
                        <text class="detail-label">规格型号</text>
                        <text class="detail-value">{{ item.specificationModel }}</text>
                     </view>
                     <view class="detail-row">
                        <text class="detail-label">绑定机器</text>
                        <text class="detail-value">{{ item.speculativeTradingName }}</text>
                     </view>
                     <view class="detail-row">
                        <text class="detail-label">单位</text>
                        <text class="detail-value">{{ item.unit }}</text>
                     </view>
                     <view class="detail-row">
                        <text class="detail-label">录入日期</text>
                        <text class="detail-value">{{ item.entryDate }}</text>
                     </view>
                     <view class="detail-row">
                        <text class="detail-label">数量</text>
                        <text class="detail-value">{{ item.quantity }}</text>
                     </view>
                     <view class="detail-row">
                        <text class="detail-label">排产数量</text>
                        <text class="detail-value highlight">{{ item.schedulingNum }}</text>
                     </view>
                     <view class="detail-row">
                        <text class="detail-label">待排数量</text>
                        <text class="detail-value" :class="{ 'danger': item.pendingQuantity <= 0 }">{{ item.pendingQuantity }}</text>
                     </view>
                     <!-- 操作按钮区域 -->
                     <view class="action-buttons">
                        <up-button
                  type="primary"
                  size="small"
                  @click="handleDispatch(item)"
                  class="action-btn"
                  :disabled="item.pendingQuantity <= 0 || !item.speculativeTradingName"
               >
                  {{ item.pendingQuantity <= 0 ? '无需派工' : !item.speculativeTradingName ? '未绑定机器' : '生产派工' }}
               </up-button>
                     </view>
                  </view>
                  <view class="detail-row">
                     <text class="detail-label">客户合同号</text>
                     <text class="detail-value">{{ item.customerContractNo }}</text>
                  </view>
                  <view class="detail-row">
                     <text class="detail-label">客户名称</text>
                     <text class="detail-value">{{ item.customerName }}</text>
                  </view>
                  <view class="detail-row">
                     <text class="detail-label">项目名称</text>
                     <text class="detail-value">{{ item.projectName }}</text>
                  </view>
                  <view class="detail-row">
                     <text class="detail-label">产品大类</text>
                     <text class="detail-value">{{ item.productCategory }}</text>
                  </view>
                  <view class="detail-row">
                     <text class="detail-label">规格型号</text>
                     <text class="detail-value">{{ item.specificationModel }}</text>
                  </view>
                  <view class="detail-row">
                     <text class="detail-label">总数量</text>
                     <text class="detail-value">{{ item.quantity }} {{ item.unit }}</text>
                  </view>
                  <view class="detail-row">
                     <text class="detail-label">排产数量</text>
                     <text class="detail-value highlight">{{ item.schedulingNum }}</text>
                  </view>
                  <view class="detail-row">
                     <text class="detail-label">待排数量</text>
                     <text class="detail-value" :class="{ 'danger': item.pendingQuantity <= 0 }">{{ item.pendingQuantity }}</text>
                  </view>
               </view>
               <!-- 操作按钮区域 -->
               <view class="action-buttons">
                  <up-button
                     type="primary"
                     size="small"
                     @click="handleDispatch(item)"
                     class="action-btn"
                     :disabled="item.pendingQuantity <= 0"
                  >
                     生产派工
                  </up-button>
               </view>
            </view>
         </view>
      </view>
      <view v-else class="no-data">
         <text>暂无生产派工数据</text>
         <up-empty mode="data" icon="http://cdn.uviewui.com/uview/empty/data.png">
            <text class="no-data-text">暂无生产派工数据</text>
         </up-empty>
      </view>
      
      <!-- 派工弹窗 -->
      <DispatchModal ref="dispatchModalRef" @confirm="handleDispatchConfirm" />
      <!-- 自动派单弹窗 -->
      <AutoDispatchDia ref="autoDispatchDia" />
   </view>
</template>
<script setup>
import { ref, reactive, toRefs, getCurrentInstance } from "vue";
import { ref, reactive, toRefs, getCurrentInstance, nextTick } from "vue";
import { onShow } from '@dcloudio/uni-app';
import dayjs from "dayjs";
import {schedulingListPage} from "@/api/productionManagement/productionOrder.js";
import {schedulingListPage, schedulingList, addSpeculatTrading, updateSpeculatTrading, getLossRate, addLossRate, updateLossRate} from "@/api/productionManagement/productionOrder.js";
import PageHeader from "@/components/PageHeader.vue";
import DispatchModal from "./components/DispatchModal.vue";
import AutoDispatchDia from "./components/autoDispatchDia.vue";
const { proxy } = getCurrentInstance();
// 加载状态
@@ -113,23 +236,77 @@
// 列表数据
const tableData = ref([]);
// 选择相关数据
const selectedItems = ref([]);
const isAllSelected = ref(false);
const showBatchActions = ref(false);
// 搜索表单数据
const data = reactive({
   searchForm: {
      customerName: "",
      projectName: "",
   },
});
const { searchForm } = toRefs(data);
// 分页配置
const page = reactive({
   current: -1,
   size: -1,
   current: 1,
   size: 100,
   total: 0,
});
// 炒机状态数据
const machineTotal = reactive({
   m1: 0,
   m2: 0,
   m3: 0,
   m4: 0,
})
const machineInProduction = reactive({
   m1: 0,
   m2: 0,
   m3: 0,
   m4: 0,
})
const machineVacant = reactive({
   m1: 0,
   m2: 0,
   m3: 0,
   m4: 0,
})
// 炒机配置数组
const machines = [
   { id: 1, key: 'm1' },
   { id: 2, key: 'm2' },
   { id: 3, key: 'm3' },
   { id: 4, key: 'm4' }
]
// 是否有查询数据(用于判断是新增还是修改)
const hasQueryData = ref(false);
// 损耗率相关数据
const lossRate = ref(""); // 当前选择的损耗率
const showLossRateSheet = ref(false); // 控制损耗率选择面板显示
const lossRateOptions = ref([
   { name: "6%", value: "6" },
   { name: "7%", value: "7" },
   { name: "8%", value: "8" },
   { name: "9%", value: "9" },
   { name: "10%", value: "10" }
]);
const lossRateData = ref(null); // 损耗率查询返回的数据
// 派工弹窗引用
const dispatchModalRef = ref();
// 自动派单弹窗引用
const autoDispatchDia = ref();
// 通用提示函数
const showLoadingToast = (message) => {
@@ -148,9 +325,73 @@
   uni.navigateBack();
};
// 重置搜索
const handleReset = () => {
   searchForm.value.customerName = "";
   searchForm.value.projectName = "";
   handleQuery();
};
// 查询列表
const handleQuery = () => {
   page.current = 1;
   getList();
};
// 获取炒机生产数据
const getMachineProductionData = () => {
   schedulingList().then((res) => {
      if (res.data && Array.isArray(res.data)) {
         // 重置数据
         machineInProduction.m1 = 0;
         machineInProduction.m2 = 0;
         machineInProduction.m3 = 0;
         machineInProduction.m4 = 0;
         // 处理炒机数据
         res.data.forEach(item => {
            const machineId = Number(item.id);
            if (machineId >= 1 && machineId <= 4) {
               const machineKey = `m${machineId}`;
               if (item.workLoad !== null && item.workLoad !== undefined) {
                  machineTotal[machineKey] = Number(item.workLoad) || 0;
               }
               if (item.currentWorkLoad !== null && item.currentWorkLoad !== undefined) {
                  machineInProduction[machineKey] = Number(item.currentWorkLoad) || 0;
               }
               // 计算空余量
               machineVacant[machineKey] = machineTotal[machineKey] - machineInProduction[machineKey];
            }
         });
      }
   }).catch(err => {
      console.error('获取炒机数据失败:', err);
   });
};
// 损耗率选择事件
const onLossRateSelect = (action) => {
   lossRate.value = action.value;
   showLossRateSheet.value = false;
   console.log('选择了损耗率:', action.name, '值:', action.value);
};
// 获取损耗率数据
const getLossRateData = () => {
   getLossRate().then((res) => {
      if (res.data) {
         lossRateData.value = res.data;
         // 设置当前选择的损耗率
         if (res.data.rate !== null && res.data.rate !== undefined) {
            lossRate.value = res.data.rate.toString();
         }
      }
   }).catch(err => {
      console.error('获取损耗率失败:', err);
   });
};
// 获取列表数据
@@ -158,18 +399,25 @@
   loading.value = true;
   showLoadingToast('加载中...');
   
   // 构造请求参数
   const params = { ...searchForm.value, ...page };
   
   schedulingListPage(params).then((res) => {
      loading.value = false;
      closeToast();
      
      // 处理每条数据,增加pendingQuantity字段
      tableData.value = (res.data.records || []).map(item => ({
         ...item,
         pendingQuantity: (Number(item.quantity) || 0) - (Number(item.schedulingNum) || 0)
      }));
            ...item,
            pendingQuantity: (Number(item.quantity) || 0) - (Number(item.schedulingNum) || 0)
         })).filter(item => item.pendingQuantity > 0);
      page.total = res.data.total || 0;
      // 获取炒机数据
      getMachineProductionData();
      // 获取损耗率数据
      getLossRateData();
   }).catch(() => {
      loading.value = false;
      closeToast();
@@ -190,6 +438,14 @@
      return;
   }
   
   if (!item.speculativeTradingName) {
      uni.showToast({
         title: '该项目未绑定机器,无法派工',
         icon: 'none'
      });
      return;
   }
   dispatchModalRef.value?.open(item);
};
@@ -198,38 +454,595 @@
   getList(); // 刷新列表
};
// 更新炒机空余量
const updateMachineVacant = (machineKey) => {
   machineVacant[machineKey] = (Number(machineTotal[machineKey]) || 0) - (Number(machineInProduction[machineKey]) || 0);
};
// 获取炒机查询数据
const getMachineQueryData = (machineId) => {
   // 这里需要根据实际情况从查询数据中获取对应的炒机数据
   // 暂时返回一个模拟数据
   return {
      id: machineId,
      name: `炒机${machineId}`,
      workLoad: machineTotal[`m${machineId}`] || 0,
      currentWorkLoad: machineInProduction[`m${machineId}`] || 0
   };
};
// 保存损耗率设置
const saveLossRate = () => {
   if (!lossRate.value) {
      console.log('未选择损耗率,跳过保存');
      return Promise.resolve();
   }
   const lossRateDataToSave = {
      rate: parseFloat(lossRate.value) || 0
   };
   // 如果有查询到的损耗率数据,说明是修改操作,需要传递id
   if (lossRateData.value && lossRateData.value.id) {
      lossRateDataToSave.id = lossRateData.value.id;
   }
   console.log('保存损耗率数据:', lossRateDataToSave);
   // 根据是否有损耗率数据决定调用新增接口还是修改接口
   const saveLossApi = lossRateData.value && lossRateData.value.id ? updateLossRate : addLossRate;
   const successMessage = lossRateData.value && lossRateData.value.id ? '损耗率修改成功' : '损耗率新增成功';
   return saveLossApi(lossRateDataToSave).then(res => {
      console.log('损耗率保存成功:', res);
      uni.showToast({
         title: successMessage,
         icon: 'success'
      });
      // 更新损耗率数据
      if (res.data) {
         lossRateData.value = res.data;
      }
      return res;
   }).catch(err => {
      console.error('损耗率保存失败:', err);
      uni.showToast({
         title: '损耗率保存失败',
         icon: 'none'
      });
      throw err;
   });
};
// 保存炒机总量设置
const saveMachineTotals = () => {
   // 构造保存数据数组,使用machines数组循环构建
   const saveData = machines.map(machine => {
      const machineData = {
         name: `炒机${machine.id}`, // 炒机名称
         workLoad: machineTotal[machine.key] || 0,  // 总量
         vacant: machineVacant[machine.key] || 0   // 空余量
      };
      // 如果是修改操作,需要传递id字段
      if (hasQueryData.value) {
         // 这里需要从查询数据中获取对应的id
         // 假设查询数据中每个炒机数据都有id字段
         const queryData = getMachineQueryData(machine.id);
         if (queryData && queryData.id) {
            machineData.id = queryData.id;
         }
      }
      return machineData;
   });
   console.log('保存炒机设置数据:', saveData);
   // 根据是否有查询数据决定调用新增接口还是修改接口
   const saveApi = hasQueryData.value ? updateSpeculatTrading : addSpeculatTrading;
   const successMessage = hasQueryData.value ? '炒机设置修改成功' : '炒机设置新增成功';
   console.log(`调用接口: ${hasQueryData.value ? '修改' : '新增'}`);
   // 先保存损耗率,再保存炒机设置
   saveLossRate().then(() => {
      // 调用后端API保存炒机设置
      return saveApi(saveData);
   }).then(res => {
      uni.showToast({
         title: successMessage,
         icon: 'success'
      });
      console.log('保存成功:', res);
      // 保存成功后,设置hasQueryData为true,下次保存将调用修改接口
      if (!hasQueryData.value) {
         hasQueryData.value = true;
      }
   }).catch(err => {
      uni.showToast({
         title: '保存失败',
         icon: 'none'
      });
      console.error('保存失败:', err);
   });
};
// 切换单个项目选择状态
const toggleItemSelection = (item, checked) => {
   // 仅允许选择已绑定机器且待派数量>0的项目
   if (!item.speculativeTradingName || item.pendingQuantity <= 0) return;
   console.log('切换选择状态:', item.id, checked);
   // 使用更严格的比较逻辑,确保ID唯一性
   const index = selectedItems.value.findIndex(selected => {
      // 深度比较对象,确保是同一个项目
      return JSON.stringify(selected) === JSON.stringify(item);
   });
   if (checked) {
      // 如果选中且不在选中列表中,则添加
      if (index === -1) {
         selectedItems.value.push({...item}); // 创建新对象,避免引用问题
         console.log('添加项目后选中数量:', selectedItems.value.length);
      }
   } else {
      // 如果取消选中且在选中列表中,则移除
      if (index > -1) {
         selectedItems.value.splice(index, 1);
         console.log('移除项目后选中数量:', selectedItems.value.length);
      }
   }
   console.log('当前选中项目列表:', selectedItems.value.map(s => s.id));
   updateAllSelectedStatus();
   updateBatchActionsVisibility();
};
// 切换全选状态
const toggleAllSelection = () => {
   if (isAllSelected.value) {
      selectedItems.value = [];
   } else {
      selectedItems.value = tableData.value.filter(item => item.pendingQuantity > 0 && item.speculativeTradingName).map(item => ({ ...item }));
   }
   isAllSelected.value = !isAllSelected.value;
   updateBatchActionsVisibility();
};
// 更新全选状态
const updateAllSelectedStatus = () => {
   const selectableItems = tableData.value.filter(item => item.pendingQuantity > 0 && item.speculativeTradingName);
   if (selectableItems.length > 0 && selectedItems.value.length === selectableItems.length &&
      selectableItems.every(item => selectedItems.value.some(selected => selected.id === item.id))) {
      isAllSelected.value = true;
   } else {
      isAllSelected.value = false;
   }
};
// 更新批量操作显示状态
const updateBatchActionsVisibility = () => {
   showBatchActions.value = selectedItems.value.length > 0;
};
// 清空选择
const clearSelection = () => {
   selectedItems.value = [];
   isAllSelected.value = false;
   showBatchActions.value = false;
};
// 获取选中的项目
const getSelectedItems = () => {
   return selectedItems.value;
};
// 处理自动派单
const handleAutoDispatch = () => {
   if (selectedItems.value.length === 0) {
      uni.showToast({
         title: '请选择要派工的项目',
         icon: 'none'
      });
      return;
   }
   // 检查是否所有选中项目都有绑定机器
   const unboundItems = selectedItems.value.filter(item => !item.speculativeTradingName);
   if (unboundItems.length > 0) {
      uni.showToast({
         title: '所选项目中有未绑定机器的项目,无法自动派单',
         icon: 'none'
      });
      return;
   }
   // 确保传递的是完整的选中项目数组
   autoDispatchDia.value?.openDialog([...selectedItems.value]);
};
// 页面显示时加载数据
onShow(() => {
   // 加载列表数据
   getList();
   clearSelection();
});
</script>
<style scoped lang="scss">
@import '@/styles/sales-common.scss';
// 生产派工页面样式
.production-dispatching {
   min-height: 100vh;
   background: #f8f9fa;
   position: relative;
   padding: 20rpx;
}
// 列表项样式
// 损耗率设置区域
.loss-rate-section {
   background: #ffffff;
   border: 1rpx solid #e4e7ed;
   border-radius: 12rpx;
   padding: 32rpx;
   margin-top: 24rpx;
   margin-bottom: 32rpx;
   box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
}
.loss-rate-section .section-title {
   font-size: 32rpx;
   font-weight: 600;
   color: #303133;
   margin-bottom: 20rpx;
}
.loss-rate-section .loss-rate-content {
   display: flex;
   flex-direction: column;
   gap: 24rpx;
}
.loss-rate-section .loss-rate-content .loss-rate-item {
   display: flex;
   align-items: center;
   gap: 24rpx;
}
.loss-rate-section .loss-rate-content .loss-rate-label {
   font-size: 30rpx;
   font-weight: 500;
   color: #303133;
   min-width: 140rpx;
   white-space: nowrap;
}
.loss-rate-section .loss-rate-content .loss-rate-btn {
   min-width: 260rpx;
   font-size: 28rpx;
   height: 64rpx;
   line-height: 64rpx;
   border-radius: 8rpx;
   font-weight: 500;
}
// 炒机状态区域
.machines-section {
   margin-bottom: 30rpx;
}
.machines-section .section-title {
   font-size: 32rpx;
   font-weight: 600;
   color: #303133;
   margin-bottom: 20rpx;
}
.machines-grid {
   display: grid;
   grid-template-columns: 1fr 1fr;
   gap: 20rpx;
}
.machine-card {
   background: #ffffff;
   border-radius: 16rpx;
   padding: 24rpx;
   box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
   border: 1rpx solid #e9ecef;
}
.machine-title {
   font-size: 28rpx;
   font-weight: 600;
   color: #2c3e50;
   text-align: center;
   margin-bottom: 20rpx;
   padding-bottom: 16rpx;
   border-bottom: 2rpx solid #3498db;
}
.machine-metrics {
   display: flex;
   flex-direction: column;
   gap: 16rpx;
}
.metric-item {
   display: flex;
   justify-content: space-between;
   align-items: center;
   padding: 8rpx 0;
}
.metric-label {
   font-size: 24rpx;
   color: #6c757d;
}
.metric-value {
   font-size: 26rpx;
   font-weight: 600;
   color: #2c3e50;
}
// 输入框样式
.metric-input {
   width: 120rpx;
   text-align: right;
}
// 保存区域
.save-section {
   display: flex;
   justify-content: center;
   margin-top: 30rpx;
   padding-top: 20rpx;
   border-top: 1rpx solid #e9ecef;
}
.save-btn {
   min-width: 200rpx;
}
// 搜索区域
.search-section {
   background: #ffffff;
   border-radius: 16rpx;
   padding: 24rpx;
   margin-bottom: 30rpx;
   box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
}
.search-form {
   display: flex;
   flex-direction: column;
   gap: 20rpx;
}
.search-item {
   display: flex;
   align-items: center;
   gap: 20rpx;
}
.search-label {
   font-size: 26rpx;
   color: #606266;
   min-width: 140rpx;
}
.search-input {
   flex: 1;
}
.search-buttons {
   display: flex;
   gap: 20rpx;
   justify-content: flex-end;
   margin-top: 10rpx;
}
.search-btn, .reset-btn {
   min-width: 120rpx;
}
// 列表样式
.ledger-list {
   display: flex;
   flex-direction: column;
   gap: 24rpx;
}
.list-item {
   background: #ffffff;
   border-radius: 16rpx;
   overflow: hidden;
   box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
}
.ledger-item {
   .detail-value.highlight {
      color: #ff6b35;
      font-weight: 600;
   }
   .detail-value.danger {
      color: #ee0a24;
      font-weight: 600;
   }
   padding: 0;
}
.item-header {
   display: flex;
   justify-content: space-between;
   align-items: center;
   padding: 24rpx 24rpx 0 24rpx;
}
.item-left {
   display: flex;
   align-items: center;
   gap: 16rpx;
}
.document-icon {
   width: 48rpx;
   height: 48rpx;
   background: #409eff;
   border-radius: 8rpx;
   display: flex;
   align-items: center;
   justify-content: center;
}
.item-id {
   font-size: 28rpx;
   font-weight: 600;
   color: #303133;
}
.entry-date {
   font-size: 24rpx;
   color: #909399;
}
.item-details {
   padding: 24rpx;
}
.detail-row {
   display: flex;
   justify-content: space-between;
   align-items: center;
   padding: 12rpx 0;
   border-bottom: 1rpx solid #f5f5f5;
}
.detail-row:last-child {
   border-bottom: none;
}
.detail-label {
   font-size: 26rpx;
   color: #606266;
}
.detail-value {
   font-size: 26rpx;
   color: #303133;
   font-weight: 500;
}
.detail-value.highlight {
   color: #ff6b35;
   font-weight: 600;
}
.detail-value.danger {
   color: #ee0a24;
   font-weight: 600;
}
.action-buttons {
   padding: 0 24rpx 24rpx 24rpx;
   display: flex;
   justify-content: flex-end;
}
.action-btn {
   min-width: 180rpx;
}
// 批量操作区域样式
.batch-actions-section {
   background: #e8f4ff;
   border: 1rpx solid #409eff;
   border-radius: 12rpx;
   padding: 20rpx 24rpx;
   margin-bottom: 24rpx;
   display: flex;
   justify-content: space-between;
   align-items: center;
}
.batch-actions-section .batch-text {
   font-size: 28rpx;
   font-weight: 600;
   color: #409eff;
}
.batch-actions-section .batch-buttons {
   display: flex;
   gap: 16rpx;
}
.batch-actions-section .batch-btn {
   min-width: 140rpx;
}
// 全选操作区域样式
.select-all-section {
   background: #ffffff;
   border-radius: 12rpx;
   padding: 20rpx 24rpx;
   margin-bottom: 16rpx;
   border: 1rpx solid #e4e7ed;
}
.select-all-section .select-all-content {
   display: flex;
   align-items: center;
}
.select-all-section .select-all-checkbox {
   font-size: 28rpx;
   font-weight: 500;
}
// 列表项选择框样式
.ledger-item {
   display: flex;
   align-items: flex-start;
   padding: 0;
}
.item-checkbox {
   padding: 24rpx 16rpx 0 24rpx;
   display: flex;
   align-items: center;
}
.item-content {
   flex: 1;
}
// 空状态
.no-data {
   padding: 100rpx 0;
   text-align: center;
}
.no-data-text {
   font-size: 28rpx;
   color: #909399;
   margin-top: 20rpx;
}
// 点击编辑区域样式
.metric-value-container {
   cursor: pointer;
   min-width: 120rpx;
   text-align: right;
   padding: 4rpx 8rpx;
   border-radius: 4rpx;
   transition: all 0.2s ease;
}
.metric-value-container:hover {
   background-color: #f0f8ff;
   border: 1rpx solid #409eff;
}
// 适配 uView 组件样式
:deep(.up-input) {
   background: transparent;
}
</style>
:deep(.up-input__content) {
   background: #f8f9fa;
}
</style>