gaoluyang
3 天以前 77861fcc5ee1c4f8e7c6412b373cb438c7313930
src/pages/sales/salesAccount/detail.vue
@@ -1,279 +1,989 @@
<template>
  <view class="account-detail">
    <!-- 顶部标题栏 -->
    <view class="header">
      <up-icon name="arrow-left" size="20" color="#333" @click="goBack" />
      <text class="title">台账详情</text>
    </view>
    <!-- 使用通用页面头部组件 -->
      <PageHeader title="台账详情" @back="goBack" />
    <!-- 表单区域 -->
    <view class="form-section">
      <van-form ref="formRef" :modelValue="form" :rules="rules" label-width="100px" input-align="right">
        <van-field label="销售合同号" name="salesContractNo" borderBottom="true" v-model="form.salesContractNo" placeholder="请输入销售合同号">
        </van-field>
            <van-field label="销售合同号" name="salesContractNo" borderBottom="true" v-model="form.salesContractNo" placeholder="请输入销售合同号">
            </van-field>
            <van-field label="销售合同号" name="salesContractNo" borderBottom="true" v-model="form.salesContractNo" placeholder="请输入销售合同号">
            </van-field>
            <van-field label="销售合同号" name="salesContractNo" borderBottom="true" v-model="form.salesContractNo" placeholder="请输入销售合同号">
            </van-field>
            <van-field label="销售合同号" name="salesContractNo" borderBottom="true" v-model="form.salesContractNo" placeholder="请输入销售合同号">
            </van-field>
            <van-field label="销售合同号" name="salesContractNo" borderBottom="true" v-model="form.salesContractNo" placeholder="请输入销售合同号">
            </van-field>
            <van-field label="录入人" name="salesContractNo" borderBottom="true" v-model="form.salesContractNo" placeholder="请输入" readonly>
            </van-field>
            <van-field label="录入日期" name="salesContractNo" borderBottom="true" v-model="form.salesContractNo" placeholder="请输入" readonly>
            </van-field>
      </van-form>
    </view>
         <!-- 表单区域 -->
      <up-form @submit="onSubmit" label-width="110" ref="formRef" :rules="rules" :model="form">
    <!-- 产品信息 -->
    <view class="product-section">
      <view class="section-header">
        <text class="section-title">产品信息</text>
        <button class="add-btn" @click="addProduct">新增</button>
      </view>
      <view class="product-card" v-for="(product, idx) in products" :key="idx">
        <view class="product-row">
          <text class="product-label">产品类</text>
          <uni-easyinput v-model="product.type" placeholder="请输入产品类" />
        </view>
        <view class="product-row">
          <text class="product-label">单位</text>
          <uni-easyinput v-model="product.unit" placeholder="请输入单位" />
          <text class="product-label">数量</text>
          <uni-easyinput v-model="product.amount" placeholder="请输入数量" type="number" />
        </view>
        <view class="product-row">
          <text class="product-label">税率</text>
          <uni-easyinput v-model="product.taxRate" placeholder="请输入税率" />
          <text class="product-label">含税单价</text>
          <uni-easyinput v-model="product.taxPrice" placeholder="请输入含税单价" />
        </view>
        <view class="product-row">
          <text class="product-label">含税总价</text>
          <uni-easyinput v-model="product.taxTotal" placeholder="请输入含税总价" />
          <text class="product-label">合同金额</text>
          <uni-easyinput v-model="product.contractAmount" placeholder="请输入合同金额" />
        </view>
        <view class="product-row">
          <text class="product-label">操作</text>
          <uni-easyinput v-model="product.operateDate" placeholder="请输入操作时间" />
        </view>
        <view class="product-row">
          <text class="product-label">备注</text>
          <uni-easyinput v-model="product.remark" placeholder="请输入备注" />
        </view>
        <view class="product-row del-row">
          <button class="del-btn" @click="removeProduct(idx)">删除</button>
        </view>
      </view>
    </view>
    <!-- 底部按钮 -->
    <view class="footer-btns">
      <van-button class="cancel-btn" @click="goBack">取消</van-button>
      <van-button class="save-btn" @click="submitForm">保存</van-button>
    </view>
         <up-form-item label="销售合同号" prop="salesContractNo" >
            <up-input v-model="form.salesContractNo" placeholder="自动生成" disabled />
         </up-form-item>
         <up-form-item
            label="业务员"
            prop="salesman"
            required
            @click="showPicker = true"
         >
            <up-input
               v-model="form.salesman"
               readonly
               @click="showPicker = true"
               placeholder="点击选择业务员"
            />
            <template #right>
               <up-icon
                  name="arrow-right"
                  @click="showPicker = true"
               ></up-icon>
            </template>
         </up-form-item>
         <up-form-item label="客户合同号" prop="customerContractNo" required >
            <up-input
               v-model="form.customerContractNo"
               placeholder="请输入客户合同号"
            />
         </up-form-item>
         <up-form-item
            label="客户名称"
            prop="customerName"
            required
         >
            <up-input
               v-model="form.customerName"
               readonly
               placeholder="点击选择客户"
               @click="showCustomerPicker = true"
            />
            <template #right>
               <up-icon
                  name="arrow-right"
                  @click="showCustomerPicker = true"
               ></up-icon>
            </template>
         </up-form-item>
         <up-form-item label="项目名称" prop="projectName" required >
            <up-input v-model="form.projectName" placeholder="请输入项目名称" />
         </up-form-item>
         <up-form-item
            label="签订日期"
            prop="executionDate"
            required
         >
            <up-input
               v-model="form.executionDate"
               readonly
               placeholder="点击选择时间"
               @click="showDatePicker = true"
            />
            <template #right>
               <up-icon
                  name="arrow-right"
                  @click="showDatePicker = true"
               ></up-icon>
            </template>
         </up-form-item>
         <up-form-item label="付款方式" prop="paymentMethod" >
            <up-input v-model="form.paymentMethod" placeholder="请输入付款方式" />
         </up-form-item>
         <up-form-item label="录入人" prop="entryPersonName" >
            <up-input v-model="form.entryPersonName" placeholder="请输入" disabled />
         </up-form-item>
         <up-form-item label="录入日期" prop="entryDate" >
            <up-input v-model="form.entryDate" placeholder="请输入" disabled />
         </up-form-item>
         <!-- 业务员选择 -->
         <up-action-sheet
            :show="showPicker"
            :actions="userActionList"
            title="选择业务员"
            @select="onSalesmanSelect"
            @close="showPicker = false"
         />
         <!-- 日期选择 -->
         <up-popup :show="showDatePicker" mode="bottom" @close="showDatePicker = false">
            <up-datetime-picker
               :show="true"
               v-model="pickerDateValue"
               @confirm="onDateConfirm"
               @cancel="showDatePicker = false"
               mode="date"
            />
         </up-popup>
         <!-- 客户选择 -->
         <up-action-sheet
            :show="showCustomerPicker"
            :actions="customerActionList"
            title="选择客户"
            @select="onCustomerSelect"
            @close="showCustomerPicker = false"
         />
         <!-- 产品大类选择器 -->
         <up-popup :show="showCategoryPicker" mode="bottom">
            <!-- 头部按钮区域 -->
            <view class="popup-header">
               <view @click="showCategoryPicker = false" class="cancelButton">取消</view>
               <view @click="confirmCategorySelection" class="confirmButton">确定</view>
            </view>
            <u-tree
               :data="productOptions"
               :props="defaultProps"
               show-checkbox
               default-expand-all
               check-strictly
               @check-change="onCategoryConfirm"
            />
         </up-popup>
         <!-- 规格型号选择器 -->
         <up-action-sheet
            :show="showSpecificationPicker"
            :actions="specificationActionList"
            title="选择规格型号"
            @select="onSpecificationSelect"
            @close="showSpecificationPicker = false"
         />
         <!-- 税率选择器 -->
         <up-action-sheet
            :show="showTaxRatePicker"
            :actions="taxRateActionList"
            title="选择税率"
            @select="onTaxRateSelect"
            @close="showTaxRatePicker = false"
         />
         <!-- 发票类型选择器 -->
         <up-action-sheet
            :show="showInvoiceTypePicker"
            :actions="invoiceTypeActionList"
            title="选择发票类型"
            @select="onInvoiceTypeSelect"
            @close="showInvoiceTypePicker = false"
         />
         <!-- 产品信息 -->
         <view class="product-section">
            <view class="section-header">
               <view>
                  <text class="section-title">产品信息</text>
               </view>
               <view>
                  <up-button type="primary" size="small" @click="addProduct" class="add-btn" v-if="operationType !== 'view'">
                     新增
                  </up-button>
               </view>
            </view>
            <view class="product-card" v-for="(product, idx) in productData" :key="idx">
               <!-- 产品类 -->
               <view class="product-header">
                  <view class="product-title">
                     <view class="document-icon">
                        <up-icon name="file-text" size="16" color="#ffffff"></up-icon>
                     </view>
                     <text class="product-productCategory">产品 {{ idx + 1 }}</text>
                  </view>
                  <!-- 操作按钮 -->
                  <view class="product-actions" v-if="operationType !== 'view'">
                     <up-button type="error" size="mini" @click="removeProduct(idx)" class="del-btn">
                        删除
                     </up-button>
                  </view>
               </view>
               <!-- 产品信息表单 -->
               <view class="product-form">
                  <!-- 产品大类 -->
                  <up-form-item
                     label="产品大类"
                     prop="productCategory"
                     required
                     :rules="productRules"
                  >
                     <up-input
                        v-model="product.productCategory"
                        readonly
                        placeholder="请选择"
                        @click="openCategoryPicker(idx)"
                     />
                     <template #right>
                        <up-icon
                           name="arrow-right"
                           @click="showCategoryPicker = true"
                        ></up-icon>
                     </template>
                  </up-form-item>
                  <!-- 规格型号 -->
                  <up-form-item
                     label="规格型号"
                     prop="specificationModel"
                     required
                     :rules="productRules"
                  >
                     <up-input
                        v-model="product.specificationModel"
                        readonly
                        placeholder="请选择"
                        @click="openSpecificationPicker(idx)"
                     />
                     <template #right>
                        <up-icon
                           name="arrow-right"
                           @click="showSpecificationPicker = true"
                        ></up-icon>
                     </template>
                  </up-form-item>
                  <!-- 单位 -->
                  <up-form-item
                     label="单位"
                     prop="unit"
                     required
                     :rules="productRules"
                  >
                     <up-input
                        v-model="product.unit"
                        placeholder="请输入"
                     />
                  </up-form-item>
                  <!-- 税率 -->
                  <up-form-item
                     label="税率(%)"
                     prop="taxRate"
                     required
                     :rules="productRules"
                  >
                     <up-input
                        v-model="product.taxRate"
                        readonly
                        placeholder="请选择"
                        @click="openTaxRatePicker(idx)"
                     />
                     <template #right>
                        <up-icon
                           name="arrow-right"
                           @click="showTaxRatePicker = true"
                        ></up-icon>
                     </template>
                  </up-form-item>
                  <!-- 含税单价 -->
                  <up-form-item
                     label="含税单价(元)"
                     prop="taxInclusiveUnitPrice"
                     required
                     :rules="productRules"
                  >
                     <up-input
                        v-model="product.taxInclusiveUnitPrice"
                        type="number"
                        placeholder="请输入"
                        @blur="formatTaxPrice(idx)"
                     />
                  </up-form-item>
                  <!-- 数量 -->
                  <up-form-item
                     label="数量"
                     prop="quantity"
                     required
                     :rules="productRules"
                  >
                     <up-input
                        v-model="product.quantity"
                        type="number"
                        placeholder="请输入"
                        @blur="formatAmount(idx)"
                     />
                  </up-form-item>
                  <!-- 含税总价 -->
                  <up-form-item
                     label="含税总价(元)"
                     prop="taxInclusiveTotalPrice"
                     required
                     :rules="productRules"
                  >
                     <up-input
                        v-model="product.taxInclusiveTotalPrice"
                        type="number"
                        placeholder="请输入"
                        @blur="formatTaxTotal(idx)"
                     />
                  </up-form-item>
                  <!-- 不含税总价 -->
                  <up-form-item
                     label="不含税总价(元)"
                     prop="taxExclusiveTotalPrice"
                     required
                     :rules="productRules"
                  >
                     <up-input
                        v-model="product.taxExclusiveTotalPrice"
                        type="number"
                        placeholder="请输入"
                        @blur="formatNoTaxTotal(idx)"
                     />
                  </up-form-item>
                  <!-- 发票类型 -->
                  <up-form-item
                     label="发票类型"
                     prop="invoiceType"
                     required
                     :rules="productRules"
                  >
                     <up-input
                        v-model="product.invoiceType"
                        readonly
                        placeholder="请选择"
                        @click="openInvoiceTypePicker(idx)"
                     />
                     <template #right>
                        <up-icon
                           name="arrow-right"
                           @click="showInvoiceTypePicker = true"
                        ></up-icon>
                     </template>
                  </up-form-item>
               </view>
            </view>
         </view>
      </up-form>
      <!-- 使用公共底部按钮组件 -->
      <FooterButtons
         :show="operationType !== 'view'"
         cancelText="取消"
         confirmText="保存"
         @cancel="goBack"
         @confirm="onSubmit"
      />
  </view>
</template>
<script setup>
import { ref } from 'vue';
const goBack = () => {
  uni.navigateBack();
};
const formRef = ref();
const paymentMethods = ['对公转账', '现金', '其他'];
import {onMounted, ref, computed} from 'vue';
import {userListNoPage} from "@/api/system/user";
import { formatDateToYMD } from '@/utils/ruoyi'
import {
   addOrUpdateSalesLedger,
   addOrUpdateSalesLedgerProduct,
   customerList,
   getSalesLedgerWithProducts,
   modelList,
   productTreeList
} from "@/api/salesManagement/salesLedger";
import useUserStore from "@/store/modules/user";
import {calculateTaxExclusiveTotalPrice} from "@/utils/summarizeTable";
import PageHeader from '@/components/PageHeader.vue';
import FooterButtons from '@/components/FooterButtons.vue';
// 获取页面参数
const operationType = ref('');
const editData = ref(null);
const formRef = ref(null);
const userStore = useUserStore()
const form = ref({
   id: '',
  salesContractNo: '',
  customerContract: '',
  projectName: '',
  contractAmount: '',
  executionDate: '',
   customerContractNo: '',
   customerId: '',
   customerName: '',
   projectName: '',
   executionDate: '',
  paymentMethod: '',
   entryPerson: '',
   entryPersonName: '',
   entryDate: '',
});
const rules = {
  salesContractNo: {
    rules: [{ required: true, errorMessage: '销售合同号不能为空' }]
  },
  customerContract: {
    rules: [{ required: true, errorMessage: '客户合同不能为空' }]
  },
  projectName: {
    rules: [{ required: true, errorMessage: '项目名称不能为空' }]
  },
  contractAmount: {
    rules: [{ required: true, errorMessage: '合同金额不能为空' }]
  },
  executionDate: {
    rules: [{ required: true, errorMessage: '签订日期不能为空' }]
  },
  paymentMethod: {
    rules: [{ required: true, errorMessage: '请选择付款方式' }]
  }
const showPicker = ref(false);
const showDatePicker = ref(false);
const pickerDateValue = ref(Date.now());
const showCustomerPicker = ref(false);
const userList = ref([]);
const customerOption = ref([]);
const userActionList = computed(() => {
   return userList.value.map(user => ({
      name: user.text,
      value: user.value
   }))
})
const formatter = (type, value) => {
   if (type === 'year') {
      return `${value}`;
   }
   if (type === 'month') {
      return `${value}`;
   }
   if (type === 'day') {
      return `${value}`;
   }
   return value;
};
const products = ref([
  {
    type: 'LS-29911',
    unit: '周庄镇',
    amount: '86590905972612',
    taxRate: '这里是项目名称',
    taxPrice: '这里是项目名称',
    taxTotal: '这里是项目名称',
    contractAmount: '32011元',
    operateDate: '2022-02-22 11:30:50',
    remark: '',
  },
  {
    type: 'LS-29911',
    unit: '周庄镇',
    amount: '86590905972612',
    taxRate: '这里是项目名称',
    taxPrice: '这里是项目名称',
    taxTotal: '这里是项目名称',
    contractAmount: '32011元',
    operateDate: '2022-02-22 11:30:50',
    remark: '',
  },
const customerActionList = computed(() => {
   return customerOption.value.map(customer => ({
      name: customer.text,
      value: customer.value
   }))
})
// 日期选择列表已移除,改用 up-datetime-picker
// 产品大类选择列表
const categoryActionList = computed(() => {
   const flattenCategories = (categories, result = []) => {
      categories.forEach(category => {
         result.push({
            name: category.label,
            value: category.id
         })
         if (category.children && category.children.length > 0) {
            flattenCategories(category.children, result)
         }
      })
      return result
   }
   return flattenCategories(productOptions.value)
})
// 规格型号选择列表
const specificationActionList = computed(() => {
   return modelOptions.value.map(model => ({
      name: model.text,
      value: model.value,
      unit: model.unit
   }))
})
// 税率选择列表
const taxRateActionList = computed(() => {
   return taxRateOptions.value.map(rate => ({
      name: rate.text,
      value: rate.value
   }))
})
// 发票类型选择列表
const invoiceTypeActionList = computed(() => {
   return invoiceTypeOptions.value.map(type => ({
      name: type.text,
      value: type.value
   }))
})
const productData = ref([]);
// 选择器相关变量
const showCategoryPicker = ref(false);
const showSpecificationPicker = ref(false);
const showTaxRatePicker = ref(false);
const showInvoiceTypePicker = ref(false);
// 选择器显示状态变量已在上面定义
// 临时变量已不再需要
const currentProductIndex = ref(0);
// 选项数据
const productOptions = ref([]);
const selectedCategoryNode = ref(null);
const defaultProps = ref({
   children: 'children',
   label: 'label',
   nodeKey: 'id'
});
const modelOptions = ref([]);
// 防止循环计算的标志
// const isCalculating = ref(false);
const taxRateOptions = ref([
  { text: '1', value: '1' },
  { text: '6', value: '6' },
  { text: '13', value: '13' },
]);
const invoiceTypeOptions = ref([
  { text: '增普票', value: '增普票' },
  { text: '增专票', value: '增专票' },
]);
// 表单校验规则
const rules = {
   salesman: [
      { required: true, message: '请选择业务员', trigger: 'blur' }
   ],
   customerContractNo: [
      { required: true, message: '请输入客户合同号', trigger: 'blur' }
   ],
   customerName: [
      { required: true, message: '请选择客户名称', trigger: 'blur' }
   ],
   projectName: [
      { required: true, message: '请输入项目名称', trigger: 'blur' }
   ],
   executionDate: [
      { required: true, message: '请选择签订日期', trigger: 'blur' }
   ]
};
// 产品信息校验规则
const productRules = {
   productCategory: [
      { required: true, message: '请选择产品大类', trigger: 'blur' }
   ],
   specificationModel: [
      { required: true, message: '请选择规格型号', trigger: 'blur' }
   ],
   unit: [
      { required: true, message: '请输入单位', trigger: 'blur' }
   ],
   taxRate: [
      { required: true, message: '请选择税率', trigger: 'blur' }
   ],
   taxInclusiveUnitPrice: [
      { required: true, message: '请输入含税单价', trigger: 'blur' },
      { type: 'number', min: 0, message: '含税单价必须大于0', trigger: 'blur' }
   ],
   quantity: [
      { required: true, message: '请输入数量', trigger: 'blur' },
      { type: 'number', min: 0, message: '数量必须大于0', trigger: 'blur' }
   ],
   taxInclusiveTotalPrice: [
      { required: true, message: '请输入含税总价', trigger: 'blur' },
      { type: 'number', min: 0, message: '含税总价必须大于0', trigger: 'blur' }
   ],
   taxExclusiveTotalPrice: [
      { required: true, message: '请输入不含税总价', trigger: 'blur' },
      { type: 'number', min: 0, message: '不含税总价必须大于0', trigger: 'blur' }
   ],
   invoiceType: [
      { required: true, message: '请选择发票类型', trigger: 'blur' }
   ]
};
const addProduct = () => {
  products.value.push({
    type: '',
   if (productData.value === null) {
      productData.value = []
   }
   productData.value.push({
    productCategory: '',
    specificationModel: '',
      productModelId: '',
    unit: '',
    amount: '',
    taxRate: '',
    taxPrice: '',
    taxTotal: '',
    contractAmount: '',
    operateDate: '',
    remark: '',
    taxInclusiveUnitPrice: '',
    quantity: '',
    taxInclusiveTotalPrice: '',
    taxExclusiveTotalPrice: '',
    invoiceType: ''
  });
};
// 业务员选择事件
const onSalesmanSelect = (item) => {
   form.value.salesman = item.name
}
// 日期确认事件
const onDateConfirm = (e) => {
   form.value.executionDate = formatDateToYMD(e.value)
   pickerDateValue.value = formatDateToYMD(e.value)
   showDatePicker.value = false;
}
// 客户选择事件
const onCustomerSelect = (item) => {
   form.value.customerName = item.name
   form.value.customerId = item.value
}
// 原有的确认方法已被新的action-sheet选择方法替代
const removeProduct = (idx) => {
  products.value.splice(idx, 1);
   productData.value.splice(idx, 1);
};
const submitForm = () => {
  formRef.value.validate().then(() => {
    uni.showToast({ title: '保存成功', icon: 'success' });
  });
// 显示选择器
const openCategoryPicker = (idx) => {
  currentProductIndex.value = idx;
  showCategoryPicker.value = true;
};
const openSpecificationPicker = (idx) => {
  currentProductIndex.value = idx;
  showSpecificationPicker.value = true;
};
const openTaxRatePicker = (idx) => {
  currentProductIndex.value = idx;
  showTaxRatePicker.value = true;
};
const openInvoiceTypePicker = (idx) => {
  currentProductIndex.value = idx;
  showInvoiceTypePicker.value = true;
};
// 选择器确认事件
const onCategoryConfirm = (node) => {
   // 获取选中的节点信息
   console.log('selected node---', node);
   // 存储选中的节点,用于确认时获取数据
   selectedCategoryNode.value = node;
};
// 确认产品大类选择
const confirmCategorySelection = () => {
   if (selectedCategoryNode.value) {
      // 设置选中的产品大类
      productData.value[currentProductIndex.value].productCategory = selectedCategoryNode.value.label;
      const id = selectedCategoryNode.value.id
      // 重置选中的节点
      selectedCategoryNode.value = null;
      productData.value[currentProductIndex.value].specificationModel = ''
      productData.value[currentProductIndex.value].productModelId = ''
      getModels(id)
   }
   showCategoryPicker.value = false;
};
// 获取规格型号
const getModels = (value) => {
   modelList({ id: value }).then((res) => {
      modelOptions.value = res.map(user => ({
         text: user.model,
         value: user.id,
         unit: user.unit,
      }));
   });
};
// 规格型号选择事件
const onSpecificationSelect = (item) => {
   productData.value[currentProductIndex.value].specificationModel = item.name
   productData.value[currentProductIndex.value].productModelId = item.value
   productData.value[currentProductIndex.value].unit = item.unit
}
// 税率选择事件
const onTaxRateSelect = (item) => {
   productData.value[currentProductIndex.value].taxRate = item.value
   // 重新计算不含税总价
   const inclusiveTotalPrice = parseFloat(productData.value[currentProductIndex.value].taxInclusiveTotalPrice)
   const taxRate = parseFloat(item.value)
   if (inclusiveTotalPrice && taxRate) {
      productData.value[currentProductIndex.value].taxExclusiveTotalPrice =
         calculateTaxExclusiveTotalPrice(inclusiveTotalPrice, taxRate)
   }
};
// 发票类型选择事件
const onInvoiceTypeSelect = (item) => {
   productData.value[currentProductIndex.value].invoiceType = item.name
};
// 格式化函数 - 固定两位小数
const formatTaxPrice = (idx) => {
  if (productData.value[idx].taxInclusiveUnitPrice) {
    const value = parseFloat(productData.value[idx].taxInclusiveUnitPrice);
    if (!isNaN(value)) {
         productData.value[idx].taxInclusiveUnitPrice = value.toFixed(2);
    }
  }
   if (!productData.value[currentProductIndex.value].taxRate) {
      uni.showToast({
         title: '请先选择税率',
         icon: 'none'
      });
      return;
   }
   const quantity = parseFloat(productData.value[currentProductIndex.value].quantity);
   const unitPrice = parseFloat(productData.value[currentProductIndex.value].taxInclusiveUnitPrice);
   if (!quantity || quantity <= 0 || !unitPrice) {
      return;
   }
   // 计算含税总价
   productData.value[currentProductIndex.value].taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
   // 如果有税率,计算不含税总价
   if (productData.value[currentProductIndex.value].taxRate) {
      productData.value[currentProductIndex.value].taxExclusiveTotalPrice =
         calculateTaxExclusiveTotalPrice(
            productData.value[currentProductIndex.value].taxInclusiveTotalPrice,
            productData.value[currentProductIndex.value].taxRate
         );
   }
};
// 数量输入框失焦
const formatAmount = (idx) => {
  if (productData.value[idx].quantity) {
    const value = parseFloat(productData.value[idx].quantity);
    if (!isNaN(value)) {
         productData.value[idx].quantity = value.toFixed(2);
    }
  }
   if (!productData.value[currentProductIndex.value].taxRate) {
      uni.showToast({
         title: '请先选择税率',
         icon: 'none'
      });
      return;
   }
   const quantity = parseFloat(productData.value[currentProductIndex.value].quantity);
   const unitPrice = parseFloat(productData.value[currentProductIndex.value].taxInclusiveUnitPrice);
   if (!quantity || quantity <= 0 || !unitPrice) {
      return;
   }
   // 计算含税总价
   productData.value[currentProductIndex.value].taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
   // 如果有税率,计算不含税总价
   if (productData.value[currentProductIndex.value].taxRate) {
      productData.value[currentProductIndex.value].taxExclusiveTotalPrice =
         calculateTaxExclusiveTotalPrice(
            productData.value[currentProductIndex.value].taxInclusiveTotalPrice,
            productData.value[currentProductIndex.value].taxRate
         );
   }
};
// 含税总价失焦,根据含税总价计算含税单价和数量
const formatTaxTotal = (idx) => {
  if (productData.value[idx].taxInclusiveTotalPrice) {
    const value = parseFloat(productData.value[idx].taxInclusiveTotalPrice);
    if (!isNaN(value)) {
         productData.value[idx].taxInclusiveTotalPrice = value.toFixed(2);
    }
  }
   const totalPrice = parseFloat(productData.value[currentProductIndex.value].taxInclusiveTotalPrice);
   const quantity = parseFloat(productData.value[currentProductIndex.value].quantity);
   if (!totalPrice || !quantity || quantity <= 0) {
      return;
   }
   // 计算含税单价 = 含税总价 / 数量
   productData.value[currentProductIndex.value].taxInclusiveUnitPrice = (totalPrice / quantity).toFixed(2);
   // 如果有税率,计算不含税总价
   if (productData.value[currentProductIndex.value].taxRate) {
      productData.value[currentProductIndex.value].taxExclusiveTotalPrice =
         calculateTaxExclusiveTotalPrice(
            totalPrice,
            productData.value[currentProductIndex.value].taxRate
         );
   }
};
// 不含税总价失焦, 根据不含税总价计算含税单价和数量
const formatNoTaxTotal = (idx) => {
  if (productData.value[idx].taxExclusiveTotalPrice) {
    const value = parseFloat(productData.value[idx].taxExclusiveTotalPrice);
    if (!isNaN(value)) {
         productData.value[idx].taxExclusiveTotalPrice = value.toFixed(2);
    }
  }
   if (!productData.value[currentProductIndex.value].taxRate) {
      uni.showToast({
         title: '请先选择税率',
         icon: 'none'
      });
      return;
   }
   const exclusiveTotalPrice = parseFloat(productData.value[currentProductIndex.value].taxExclusiveTotalPrice);
   const quantity = parseFloat(productData.value[currentProductIndex.value].quantity);
   const taxRate = parseFloat(productData.value[currentProductIndex.value].taxRate);
   if (!exclusiveTotalPrice || !quantity || quantity <= 0 || !taxRate) {
      return;
   }
   // 先计算含税总价 = 不含税总价 / (1 - 税率/100)
   const taxRateDecimal = taxRate / 100;
   const inclusiveTotalPrice = exclusiveTotalPrice / (1 - taxRateDecimal);
   productData.value[currentProductIndex.value].taxInclusiveTotalPrice = inclusiveTotalPrice.toFixed(2);
   // 计算含税单价 = 含税总价 / 数量
   productData.value[currentProductIndex.value].taxInclusiveUnitPrice = (inclusiveTotalPrice / quantity).toFixed(2);
};
const goBack = () => {
   // 清理本地存储的数据
   uni.removeStorageSync('operationType');
   uni.removeStorageSync('editData');
   uni.navigateBack();
};
const onSubmit = async () => {
   // 首先校验基本表单
   const formValid = await formRef.value.validate().catch(() => false);
   if (!formValid) {
      return;
   }
   // 校验产品信息
   if (!productData.value || productData.value.length === 0) {
      uni.showToast({
         title: '请添加产品信息',
         icon: 'none'
      });
      return;
   }
   // 检查每个产品是否填写完整
   for (let i = 0; i < productData.value.length; i++) {
      const errors = validateProduct(productData.value[i], i);
      if (errors.length > 0) {
         uni.showToast({
            title: errors[0],
            icon: 'none'
         });
         return;
      }
   }
   // 表单校验通过,提交数据
   form.value.productData = JSON.parse(JSON.stringify(productData.value));
   form.value.type = 1;
   addOrUpdateSalesLedger(form.value).then((res) => {
      uni.showToast({
         title: '提交成功',
         icon: 'success',
      });
      goBack();
   });
};
const setUserInfo = () => {
   form.value.entryPerson = userStore.id;
   form.value.entryPersonName = userStore.nickName;
   // 设置当天日期
   const today = new Date()
   const year = today.getFullYear()
   const month = String(today.getMonth() + 1).padStart(2, '0')
   const day = String(today.getDate()).padStart(2, '0')
   form.value.entryDate = `${year}-${month}-${day}`
   // 设置日期选择器默认值为今天
   pickerDateValue.value = `${year}-${month}-${day}`
}
// 填充表单数据(编辑模式)
const fillFormData = () => {
  if (!editData.value) return;
   getSalesLedgerWithProducts({ id: editData.value.id, type: 1 }).then((res) => {
      productData.value = res.productData;
   });
   console.log(editData.value)
  // 填充基本信息
  form.value.salesContractNo = editData.value.salesContractNo || '';
  form.value.customerContractNo = editData.value.customerContractNo || '';
  form.value.customerName = editData.value.customerName || '';
  form.value.projectName = editData.value.projectName || '';
  form.value.executionDate = editData.value.executionDate || '';
  form.value.paymentMethod = editData.value.paymentMethod || '';
  form.value.salesman = editData.value.salesman || '';
  form.value.entryPerson = editData.value.entryPerson || '';
  form.value.entryPersonName = editData.value.entryPersonName || '';
  form.value.entryDate = editData.value.entryDate || '';
  form.value.id = editData.value.id || '';
  form.value.customerId = editData.value.customerId || '';
  // 设置日期选择器的值
  if (editData.value.executionDate) {
      pickerDateValue.value = editData.value.executionDate
   }
};
const getUserList = () => {
   userListNoPage().then((res) => {
      // 移除多余的数组包装
      userList.value = res.data.map(user => ({
         text: user.nickName,
         value: user.nickName
      }));
   })
};
const getCustomerList = () => {
   customerList().then((res) => {
      // 移除多余的数组包装
      customerOption.value = res.map(item => ({
         text: item.customerName,
         value: item.id
      }));
   })
};
const convertIdToValue = (data) => {
   // 如果传入的不是数组,则返回空数组
   if (!Array.isArray(data)) {
      return [];
   }
   // 递归映射函数
   return data.map(item => {
      // 创建新对象,映射字段
      const mappedItem = {
         label: item.label, // 关键:将 label 映射为 text
         id: item.id,       // 保留 id
      };
      // 如果存在 children 数组,则递归处理
      if (item.children && Array.isArray(item.children) && item.children.length > 0) {
         mappedItem.children = convertIdToValue(item.children);
      }
      return mappedItem;
   });
};
// 获取产品大类tree数据
const getProductOptions = () => {
   productTreeList().then((res) => {
      productOptions.value = convertIdToValue(res);
   });
};
// 单个产品表单验证函数
const validateProduct = (product, index) => {
   const errors = [];
   if (!product.productCategory) {
      errors.push(`产品${index + 1}:请选择产品大类`);
   }
   if (!product.specificationModel) {
      errors.push(`产品${index + 1}:请选择规格型号`);
   }
   if (!product.unit) {
      errors.push(`产品${index + 1}:请输入单位`);
   }
   if (!product.taxRate) {
      errors.push(`产品${index + 1}:请选择税率`);
   }
   if (!product.taxInclusiveUnitPrice || parseFloat(product.taxInclusiveUnitPrice) <= 0) {
      errors.push(`产品${index + 1}:请输入有效的含税单价`);
   }
   if (!product.quantity || parseFloat(product.quantity) <= 0) {
      errors.push(`产品${index + 1}:请输入有效的数量`);
   }
   if (!product.taxInclusiveTotalPrice || parseFloat(product.taxInclusiveTotalPrice) <= 0) {
      errors.push(`产品${index + 1}:请输入有效的含税总价`);
   }
   if (!product.taxExclusiveTotalPrice || parseFloat(product.taxExclusiveTotalPrice) <= 0) {
      errors.push(`产品${index + 1}:请输入有效的不含税总价`);
   }
   if (!product.invoiceType) {
      errors.push(`产品${index + 1}:请选择发票类型`);
   }
   return errors;
};
onMounted(() => {
   // 获取页面参数
   operationType.value = uni.getStorageSync('operationType') || '';
   // 获取人员列表
   getUserList()
   // 获取客户列表
   getCustomerList()
   // 获取产品大类tree数据
   getProductOptions()
   // 赋值默认信息
   if (operationType.value === 'add') {
      setUserInfo()
   }
   // 获取编辑数据并填充表单
   const editDataStr = uni.getStorageSync('editData');
   if (editDataStr) {
      try {
         editData.value = JSON.parse(editDataStr);
         // 如果是编辑模式,等待数据加载完成后填充表单数据
         if (operationType.value !== 'add' && editData.value) {
            // 使用 nextTick 确保数据加载完成后再填充
            setTimeout(() => {
               fillFormData();
            }, 100);
         }
      } catch (error) {
         console.error('解析编辑数据失败:', error);
      }
   }
});
</script>
<style scoped lang="scss">
.account-detail {
  min-height: 100vh;
  background: #f8f9fa;
  padding-bottom: 80px;
}
.header {
  display: flex;
  align-items: center;
  background: #fff;
  padding: 16px 20px;
  border-bottom: 1px solid #f0f0f0;
  position: sticky;
  top: 0;
  z-index: 100;
}
.title {
  flex: 1;
  text-align: center;
  font-size: 18px;
  font-weight: 600;
  color: #333;
}
.form-section {
   margin-top: 16px;
}
.van-field {
   height: 56px;
   line-height: 36px;
}
.product-section {
  background: #fff;
  margin: 16px;
  border-radius: 16px;
  padding: 20px 16px 8px 16px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.04);
}
.section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
}
.section-title {
  font-size: 16px;
  font-weight: 600;
  color: #333;
}
.add-btn {
  background: #2979ff;
  color: #fff;
  border-radius: 8px;
  padding: 4px 16px;
  font-size: 14px;
}
.product-card {
  background: #f8f9fa;
  border-radius: 12px;
  padding: 12px;
  margin-bottom: 16px;
  box-shadow: 0 1px 4px rgba(41,121,255,0.06);
  position: relative;
}
.product-row {
  display: flex;
  align-items: center;
  margin-bottom: 8px;
}
.product-label {
  min-width: 60px;
  color: #888;
  font-size: 13px;
}
.del-row {
  justify-content: flex-end;
}
.del-btn {
  background: #ff4d4f;
  color: #fff;
  border-radius: 8px;
  padding: 4px 16px;
  font-size: 13px;
  margin-top: 4px;
}
.footer-btns {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  background: #fff;
  display: flex;
  justify-content: space-around;
  align-items: center;
  padding: 12px 0;
  box-shadow: 0 -2px 8px rgba(0,0,0,0.05);
  z-index: 1000;
}
.cancel-btn {
   font-weight: 400;
   font-size: 16px;
   color: #FFFFFF;
   width: 102px;
   background: #C7C9CC;
   box-shadow: 0px 4px 10px 0px rgba(3,88,185,0.2);
   border-radius: 40px 40px 40px 40px;
}
.save-btn {
   font-weight: 400;
   font-size: 16px;
   color: #FFFFFF;
   width: 224px;
   background: linear-gradient( 140deg, #00BAFF 0%, #006CFB 100%);
   box-shadow: 0px 4px 10px 0px rgba(3,88,185,0.2);
   border-radius: 40px 40px 40px 40px;
}
<style lang="scss">
@import '@/static/scss/form-common.scss';
</style>