|
|
@@ -0,0 +1,2067 @@
|
|
|
+<!-- 付款申请流程专用表单组件 -->
|
|
|
+<template>
|
|
|
+ <view class="payment-form-component">
|
|
|
+ <!-- 基本信息 -->
|
|
|
+ <uni-card>
|
|
|
+ <uni-section titleFontSize="1.3rem" title="基本信息" type="line"></uni-section>
|
|
|
+ <uni-forms ref="baseFormRef" :modelValue="baseForm" :rules="baseFormRules" label-position="left" :label-width="120" :border="true">
|
|
|
+ <uni-forms-item name="department" label="申请部门">
|
|
|
+ <uni-easyinput v-model="baseForm.department" disabled></uni-easyinput>
|
|
|
+ </uni-forms-item>
|
|
|
+ <uni-forms-item name="applyDate" label="申请日期">
|
|
|
+ <uni-easyinput v-model="baseForm.applyDate" disabled></uni-easyinput>
|
|
|
+ </uni-forms-item>
|
|
|
+ <uni-forms-item name="contractNumber" label="合同">
|
|
|
+ <view v-if="isInitiateOrFieldEditable('contract_number')" class="selector-wrapper" @click="openContractSelector">
|
|
|
+ <text v-if="baseForm.contractNumber">{{ baseForm.contractNumber }}</text>
|
|
|
+ <text v-else class="placeholder">选择合同</text>
|
|
|
+ </view>
|
|
|
+ <uni-easyinput v-else v-model="baseForm.contractNumber" disabled></uni-easyinput>
|
|
|
+ <button v-if="isInitiateOrFieldEditable('contract_number') && baseForm.contractId" type="warn" size="mini" @click="clearContract" style="margin-left: 10px;">清除</button>
|
|
|
+ </uni-forms-item>
|
|
|
+ <uni-forms-item name="payerName" label="单位" required>
|
|
|
+ <uni-easyinput v-if="isInitiateOrFieldEditable('payer_name')"
|
|
|
+ v-model="baseForm.payerName"
|
|
|
+ placeholder="请输入单位"></uni-easyinput>
|
|
|
+ <uni-easyinput v-else v-model="baseForm.payerName" disabled></uni-easyinput>
|
|
|
+ </uni-forms-item>
|
|
|
+ <uni-forms-item name="payeeName" label="收款单位" required>
|
|
|
+ <view v-if="isInitiateOrFieldEditable('payee_name') && !baseForm.contractId" class="payee-input-wrapper">
|
|
|
+ <uni-easyinput
|
|
|
+ v-model="baseForm.payeeName"
|
|
|
+ placeholder="请输入或选择收款单位"
|
|
|
+ @input="onPayeeInputChange"
|
|
|
+ ></uni-easyinput>
|
|
|
+ <button
|
|
|
+ type="primary"
|
|
|
+ size="mini"
|
|
|
+ @click="openSupplierSelector"
|
|
|
+ class="select-supplier-btn"
|
|
|
+ >
|
|
|
+ 选择供应商
|
|
|
+ </button>
|
|
|
+ </view>
|
|
|
+ <uni-easyinput v-else v-model="baseForm.payeeName" disabled></uni-easyinput>
|
|
|
+ </uni-forms-item>
|
|
|
+ <uni-forms-item name="payeeBankAccount" label="开户行及账号" required>
|
|
|
+ <uni-easyinput v-if="isInitiateOrFieldEditable('payee_bank_account')"
|
|
|
+ v-model="baseForm.payeeBankAccount"
|
|
|
+ placeholder="请输入开户行及账号"></uni-easyinput>
|
|
|
+ <uni-easyinput v-else v-model="baseForm.payeeBankAccount" disabled></uni-easyinput>
|
|
|
+ </uni-forms-item>
|
|
|
+ <uni-forms-item name="paymentType" label="付款类型" required>
|
|
|
+ <picker v-if="isInitiateOrFieldEditable('payment_type')"
|
|
|
+ @change="onPaymentTypeChange"
|
|
|
+ :value="paymentTypeIndex"
|
|
|
+ :range="paymentTypeList"
|
|
|
+ range-key="name">
|
|
|
+ <view class="picker-wrapper">
|
|
|
+ <text v-if="baseForm.paymentTypeName">{{ baseForm.paymentTypeName }}</text>
|
|
|
+ <text v-else class="placeholder">请选择付款类型</text>
|
|
|
+ </view>
|
|
|
+ </picker>
|
|
|
+ <uni-easyinput v-else v-model="baseForm.paymentTypeName" disabled></uni-easyinput>
|
|
|
+ </uni-forms-item>
|
|
|
+ <!-- 预付款:显示采购订单编号 -->
|
|
|
+ <uni-forms-item v-if="baseForm.paymentType === '1'" name="purchaseOrderNo" label="采购订单编号">
|
|
|
+ <view v-if="isInitiateOrFieldEditable('purchase_order_no')" class="selector-wrapper" @click="openPurchaseOrderSelector">
|
|
|
+ <text v-if="baseForm.purchaseOrderNo">{{ baseForm.purchaseOrderNo }}</text>
|
|
|
+ <text v-else class="placeholder">选择采购订单</text>
|
|
|
+ </view>
|
|
|
+ <uni-easyinput v-else v-model="baseForm.purchaseOrderNo" disabled></uni-easyinput>
|
|
|
+ <button v-if="isInitiateOrFieldEditable('purchase_order_no') && baseForm.purchaseOrderNo" type="warn" size="mini" @click="clearPurchaseOrder" style="margin-left: 10px;">清除</button>
|
|
|
+ </uni-forms-item>
|
|
|
+
|
|
|
+ <!-- 到付款:显示入库单编号 -->
|
|
|
+ <uni-forms-item v-if="baseForm.paymentType === '2'" name="storageOrderNo" label="入库单编号">
|
|
|
+ <view v-if="isInitiateOrFieldEditable('storage_order_no')" class="selector-wrapper" @click="openStorageOrderSelector">
|
|
|
+ <text v-if="baseForm.storageOrderNo">{{ baseForm.storageOrderNo }}</text>
|
|
|
+ <text v-else class="placeholder">选择入库单</text>
|
|
|
+ </view>
|
|
|
+ <uni-easyinput v-else v-model="baseForm.storageOrderNo" disabled></uni-easyinput>
|
|
|
+ <button v-if="isInitiateOrFieldEditable('storage_order_no') && baseForm.storageOrderNo" type="warn" size="mini" @click="clearStorageOrder" style="margin-left: 10px;">清除</button>
|
|
|
+ </uni-forms-item>
|
|
|
+ <uni-forms-item name="paymentMethod" label="付款方式" required>
|
|
|
+ <uni-easyinput v-if="isInitiateOrFieldEditable('payment_method')"
|
|
|
+ v-model="baseForm.paymentMethod"
|
|
|
+ placeholder="请输入付款方式"></uni-easyinput>
|
|
|
+ <uni-easyinput v-else v-model="baseForm.paymentMethod" disabled></uni-easyinput>
|
|
|
+ </uni-forms-item>
|
|
|
+ <uni-forms-item name="paymentDate" label="付款日期" required>
|
|
|
+ <picker v-if="isInitiateOrFieldEditable('payment_date')"
|
|
|
+ mode="date"
|
|
|
+ :value="baseForm.paymentDate"
|
|
|
+ @change="onPaymentDateChange">
|
|
|
+ <view class="picker-wrapper">
|
|
|
+ <text v-if="baseForm.paymentDate">{{ baseForm.paymentDate }}</text>
|
|
|
+ <text v-else class="placeholder">请选择付款日期</text>
|
|
|
+ </view>
|
|
|
+ </picker>
|
|
|
+ <uni-easyinput v-else v-model="baseForm.paymentDate" disabled></uni-easyinput>
|
|
|
+ </uni-forms-item>
|
|
|
+ <uni-forms-item name="amountUpper" label="付款金额(大写)">
|
|
|
+ <uni-easyinput v-model="baseForm.amountUpper" disabled></uni-easyinput>
|
|
|
+ </uni-forms-item>
|
|
|
+ <uni-forms-item name="amountLower" label="付款金额(小写)" required>
|
|
|
+ <uni-easyinput v-if="isInitiateOrFieldEditable('amount_lower')"
|
|
|
+ v-model="baseForm.amountLower"
|
|
|
+ placeholder="请输入付款金额"
|
|
|
+ type="digit"
|
|
|
+ @input="onAmountLowerInput"></uni-easyinput>
|
|
|
+ <uni-easyinput v-else v-model="baseForm.amountLower" disabled></uni-easyinput>
|
|
|
+ </uni-forms-item>
|
|
|
+ <uni-forms-item name="purpose" label="用途或理由" required>
|
|
|
+ <textarea v-if="isInitiateOrFieldEditable('purpose')"
|
|
|
+ v-model="baseForm.purpose"
|
|
|
+ placeholder="请输入用途或理由"
|
|
|
+ class="textarea-input"></textarea>
|
|
|
+ <view v-else class="textarea-display">{{ baseForm.purpose || '-' }}</view>
|
|
|
+ </uni-forms-item>
|
|
|
+ <uni-forms-item name="operator" label="经办人" required>
|
|
|
+ <uni-easyinput v-model="baseForm.operator" disabled></uni-easyinput>
|
|
|
+ </uni-forms-item>
|
|
|
+
|
|
|
+ <!-- 部门负责人签名 -->
|
|
|
+ <uni-forms-item label="部门负责人" name="deptApprover">
|
|
|
+ <view class="element_value_container">
|
|
|
+ <view v-if="isApprovalFieldEditable(deptApproverElem)" class="element_value">
|
|
|
+ <view v-if="deptApproverElem && (!deptApproverElem.defaultValue || deptApproverElem.defaultValue == '')">
|
|
|
+ <uni-row>
|
|
|
+ <uni-col :span="24">
|
|
|
+ <button type="primary" @click="handleApprovalSignature('dept_approver')">手动签名</button>
|
|
|
+ </uni-col>
|
|
|
+ <uni-col :span="24">
|
|
|
+ <button style="margin-top: 5px;" type="primary" @click="handleAutoSeal('dept_approver')">一键签名</button>
|
|
|
+ </uni-col>
|
|
|
+ </uni-row>
|
|
|
+ </view>
|
|
|
+ <view v-else-if="deptApproverElem && deptApproverElem.defaultValue" class="signature_img">
|
|
|
+ <img style="width: 100%;" mode="widthFix" @click="handleApprovalSignature('dept_approver')"
|
|
|
+ :src="config.baseUrlPre + deptApproverElem.sealImgPath"
|
|
|
+ :alt="deptApproverElem.elementName + '签名'" />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view v-else-if="deptApproverElem && typeof deptApproverElem.sealImgPath === 'string' && deptApproverElem.sealImgPath.startsWith('/shares')" class="signature_img">
|
|
|
+ <img style="width: 100%;" mode="widthFix"
|
|
|
+ :src="config.baseUrlPre + deptApproverElem.sealImgPath" />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </uni-forms-item>
|
|
|
+
|
|
|
+ <!-- 经办会计签名 -->
|
|
|
+ <uni-forms-item label="经办会计" name="accountant">
|
|
|
+ <view class="element_value_container">
|
|
|
+ <view v-if="isApprovalFieldEditable(accountantElem)" class="element_value">
|
|
|
+ <view v-if="accountantElem && (!accountantElem.defaultValue || accountantElem.defaultValue == '')">
|
|
|
+ <uni-row>
|
|
|
+ <uni-col :span="24">
|
|
|
+ <button type="primary" @click="handleApprovalSignature('accountant')">手动签名</button>
|
|
|
+ </uni-col>
|
|
|
+ <uni-col :span="24">
|
|
|
+ <button style="margin-top: 5px;" type="primary" @click="handleAutoSeal('accountant')">一键签名</button>
|
|
|
+ </uni-col>
|
|
|
+ </uni-row>
|
|
|
+ </view>
|
|
|
+ <view v-else-if="accountantElem && accountantElem.defaultValue" class="signature_img">
|
|
|
+ <img style="width: 100%;" mode="widthFix" @click="handleApprovalSignature('accountant')"
|
|
|
+ :src="config.baseUrlPre + accountantElem.sealImgPath"
|
|
|
+ :alt="accountantElem.elementName + '签名'" />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view v-else-if="accountantElem && typeof accountantElem.sealImgPath === 'string' && accountantElem.sealImgPath.startsWith('/shares')" class="signature_img">
|
|
|
+ <img style="width: 100%;" mode="widthFix"
|
|
|
+ :src="config.baseUrlPre + accountantElem.sealImgPath" />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </uni-forms-item>
|
|
|
+
|
|
|
+ <!-- 财务经理签名 -->
|
|
|
+ <uni-forms-item label="财务经理" name="financeManager">
|
|
|
+ <view class="element_value_container">
|
|
|
+ <view v-if="isApprovalFieldEditable(financeManagerElem)" class="element_value">
|
|
|
+ <view v-if="financeManagerElem && (!financeManagerElem.defaultValue || financeManagerElem.defaultValue == '')">
|
|
|
+ <uni-row>
|
|
|
+ <uni-col :span="24">
|
|
|
+ <button type="primary" @click="handleApprovalSignature('finance_manager')">手动签名</button>
|
|
|
+ </uni-col>
|
|
|
+ <uni-col :span="24">
|
|
|
+ <button style="margin-top: 5px;" type="primary" @click="handleAutoSeal('finance_manager')">一键签名</button>
|
|
|
+ </uni-col>
|
|
|
+ </uni-row>
|
|
|
+ </view>
|
|
|
+ <view v-else-if="financeManagerElem && financeManagerElem.defaultValue" class="signature_img">
|
|
|
+ <img style="width: 100%;" mode="widthFix" @click="handleApprovalSignature('finance_manager')"
|
|
|
+ :src="config.baseUrlPre + financeManagerElem.sealImgPath"
|
|
|
+ :alt="financeManagerElem.elementName + '签名'" />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view v-else-if="financeManagerElem && typeof financeManagerElem.sealImgPath === 'string' && financeManagerElem.sealImgPath.startsWith('/shares')" class="signature_img">
|
|
|
+ <img style="width: 100%;" mode="widthFix"
|
|
|
+ :src="config.baseUrlPre + financeManagerElem.sealImgPath" />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </uni-forms-item>
|
|
|
+
|
|
|
+ <!-- 分管副总部门签名 -->
|
|
|
+ <uni-forms-item label="分管副总(部门)" name="deputyManagerDept">
|
|
|
+ <view class="element_value_container">
|
|
|
+ <view v-if="isApprovalFieldEditable(deputyManagerDeptElem)" class="element_value">
|
|
|
+ <view v-if="deputyManagerDeptElem && (!deputyManagerDeptElem.defaultValue || deputyManagerDeptElem.defaultValue == '')">
|
|
|
+ <uni-row>
|
|
|
+ <uni-col :span="24">
|
|
|
+ <button type="primary" @click="handleApprovalSignature('deputy_manager_dept')">手动签名</button>
|
|
|
+ </uni-col>
|
|
|
+ <uni-col :span="24">
|
|
|
+ <button style="margin-top: 5px;" type="primary" @click="handleAutoSeal('deputy_manager_dept')">一键签名</button>
|
|
|
+ </uni-col>
|
|
|
+ </uni-row>
|
|
|
+ </view>
|
|
|
+ <view v-else-if="deputyManagerDeptElem && deputyManagerDeptElem.defaultValue" class="signature_img">
|
|
|
+ <img style="width: 100%;" mode="widthFix" @click="handleApprovalSignature('deputy_manager_dept')"
|
|
|
+ :src="config.baseUrlPre + deputyManagerDeptElem.sealImgPath"
|
|
|
+ :alt="deputyManagerDeptElem.elementName + '签名'" />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view v-else-if="deputyManagerDeptElem && typeof deputyManagerDeptElem.sealImgPath === 'string' && deputyManagerDeptElem.sealImgPath.startsWith('/shares')" class="signature_img">
|
|
|
+ <img style="width: 100%;" mode="widthFix"
|
|
|
+ :src="config.baseUrlPre + deputyManagerDeptElem.sealImgPath" />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </uni-forms-item>
|
|
|
+
|
|
|
+ <!-- 分管副总审计签名 -->
|
|
|
+ <uni-forms-item label="分管副总(审计)" name="deputyManagerAudit">
|
|
|
+ <view class="element_value_container">
|
|
|
+ <view v-if="isApprovalFieldEditable(deputyManagerAuditElem)" class="element_value">
|
|
|
+ <view v-if="deputyManagerAuditElem && (!deputyManagerAuditElem.defaultValue || deputyManagerAuditElem.defaultValue == '')">
|
|
|
+ <uni-row>
|
|
|
+ <uni-col :span="24">
|
|
|
+ <button type="primary" @click="handleApprovalSignature('deputy_manager_audit')">手动签名</button>
|
|
|
+ </uni-col>
|
|
|
+ <uni-col :span="24">
|
|
|
+ <button style="margin-top: 5px;" type="primary" @click="handleAutoSeal('deputy_manager_audit')">一键签名</button>
|
|
|
+ </uni-col>
|
|
|
+ </uni-row>
|
|
|
+ </view>
|
|
|
+ <view v-else-if="deputyManagerAuditElem && deputyManagerAuditElem.defaultValue" class="signature_img">
|
|
|
+ <img style="width: 100%;" mode="widthFix" @click="handleApprovalSignature('deputy_manager_audit')"
|
|
|
+ :src="config.baseUrlPre + deputyManagerAuditElem.sealImgPath"
|
|
|
+ :alt="deputyManagerAuditElem.elementName + '签名'" />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view v-else-if="deputyManagerAuditElem && typeof deputyManagerAuditElem.sealImgPath === 'string' && deputyManagerAuditElem.sealImgPath.startsWith('/shares')" class="signature_img">
|
|
|
+ <img style="width: 100%;" mode="widthFix"
|
|
|
+ :src="config.baseUrlPre + deputyManagerAuditElem.sealImgPath" />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </uni-forms-item>
|
|
|
+
|
|
|
+ <!-- 公司总经理签名 -->
|
|
|
+ <uni-forms-item label="公司总经理" name="generalManager">
|
|
|
+ <view class="element_value_container">
|
|
|
+ <view v-if="isApprovalFieldEditable(generalManagerElem)" class="element_value">
|
|
|
+ <view v-if="generalManagerElem && (!generalManagerElem.defaultValue || generalManagerElem.defaultValue == '')">
|
|
|
+ <uni-row>
|
|
|
+ <uni-col :span="24">
|
|
|
+ <button type="primary" @click="handleApprovalSignature('general_manager')">手动签名</button>
|
|
|
+ </uni-col>
|
|
|
+ <uni-col :span="24">
|
|
|
+ <button style="margin-top: 5px;" type="primary" @click="handleAutoSeal('general_manager')">一键签名</button>
|
|
|
+ </uni-col>
|
|
|
+ </uni-row>
|
|
|
+ </view>
|
|
|
+ <view v-else-if="generalManagerElem && generalManagerElem.defaultValue" class="signature_img">
|
|
|
+ <img style="width: 100%;" mode="widthFix" @click="handleApprovalSignature('general_manager')"
|
|
|
+ :src="config.baseUrlPre + generalManagerElem.sealImgPath"
|
|
|
+ :alt="generalManagerElem.elementName + '签名'" />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view v-else-if="generalManagerElem && typeof generalManagerElem.sealImgPath === 'string' && generalManagerElem.sealImgPath.startsWith('/shares')" class="signature_img">
|
|
|
+ <img style="width: 100%;" mode="widthFix"
|
|
|
+ :src="config.baseUrlPre + generalManagerElem.sealImgPath" />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </uni-forms-item>
|
|
|
+
|
|
|
+ <!-- 董事长签名 -->
|
|
|
+ <uni-forms-item label="董事长" name="chairman">
|
|
|
+ <view class="element_value_container">
|
|
|
+ <view v-if="isApprovalFieldEditable(chairmanElem)" class="element_value">
|
|
|
+ <view v-if="chairmanElem && (!chairmanElem.defaultValue || chairmanElem.defaultValue == '')">
|
|
|
+ <uni-row>
|
|
|
+ <uni-col :span="24">
|
|
|
+ <button type="primary" @click="handleApprovalSignature('chairman')">手动签名</button>
|
|
|
+ </uni-col>
|
|
|
+ <uni-col :span="24">
|
|
|
+ <button style="margin-top: 5px;" type="primary" @click="handleAutoSeal('chairman')">一键签名</button>
|
|
|
+ </uni-col>
|
|
|
+ </uni-row>
|
|
|
+ </view>
|
|
|
+ <view v-else-if="chairmanElem && chairmanElem.defaultValue" class="signature_img">
|
|
|
+ <img style="width: 100%;" mode="widthFix" @click="handleApprovalSignature('chairman')"
|
|
|
+ :src="config.baseUrlPre + chairmanElem.sealImgPath"
|
|
|
+ :alt="chairmanElem.elementName + '签名'" />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view v-else-if="chairmanElem && typeof chairmanElem.sealImgPath === 'string' && chairmanElem.sealImgPath.startsWith('/shares')" class="signature_img">
|
|
|
+ <img style="width: 100%;" mode="widthFix"
|
|
|
+ :src="config.baseUrlPre + chairmanElem.sealImgPath" />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </uni-forms-item>
|
|
|
+ </uni-forms>
|
|
|
+ </uni-card>
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ <!-- 签名板弹出层 -->
|
|
|
+ <uni-popup ref="signaturePopup" @maskClick="closeSignature">
|
|
|
+ <view class="signature_container" :class="{ 'signature_container_landscape': isLandscape }">
|
|
|
+ <view class="signature_content">
|
|
|
+ <l-signature ref="signatureRef" v-if="signaturePopupShow" :landscape="isLandscape" :penSize="8"
|
|
|
+ :minLineWidth="4" :maxLineWidth="12" :openSmooth="true" :preferToDataURL="true"
|
|
|
+ backgroundColor="#ffffff" penColor="black"></l-signature>
|
|
|
+ </view>
|
|
|
+ <view class="signature_button_container">
|
|
|
+ <uni-row :gutter="10">
|
|
|
+ <uni-col :span="6">
|
|
|
+ <button type="warn" @click="onclickSignatureButton('undo')">撤销</button>
|
|
|
+ </uni-col>
|
|
|
+ <uni-col :span="6">
|
|
|
+ <button type="warn" @click="onclickSignatureButton('clear')">清空</button>
|
|
|
+ </uni-col>
|
|
|
+ <uni-col :span="6">
|
|
|
+ <button type="primary" @click="onclickSignatureButton('save')">保存</button>
|
|
|
+ </uni-col>
|
|
|
+ <uni-col :span="6">
|
|
|
+ <button @click="onclickSignatureButton('landscape')">全屏</button>
|
|
|
+ </uni-col>
|
|
|
+ </uni-row>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </uni-popup>
|
|
|
+
|
|
|
+ <!-- 选择器弹出层(供应商/合同/采购订单/入库单) -->
|
|
|
+ <uni-popup ref="selectorPopup" type="center">
|
|
|
+ <view class="selector-popup">
|
|
|
+ <view class="popup-header">
|
|
|
+ <text class="popup-title">{{ selectorTitle }}</text>
|
|
|
+ <uni-icons type="closeempty" size="20" @click="closePopup"></uni-icons>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 选择器内容 -->
|
|
|
+ <view class="popup-content-wrapper">
|
|
|
+ <!-- 搜索栏 -->
|
|
|
+ <view class="search-bar">
|
|
|
+ <uni-easyinput
|
|
|
+ v-model="searchKeyword"
|
|
|
+ :placeholder="searchPlaceholder"
|
|
|
+ clearable
|
|
|
+ @confirm="handleSearch"
|
|
|
+ />
|
|
|
+ <button type="primary" size="mini" @click="handleSearch">搜索</button>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 合同类型筛选 -->
|
|
|
+ <view v-if="selectorType === 'contract'" class="filter-bar">
|
|
|
+ <picker @change="onContractTypeChange" :range="contractTypeList" range-key="name">
|
|
|
+ <view class="picker-filter">
|
|
|
+ {{ selectedContractTypeName || '全部合同类型' }}
|
|
|
+ </view>
|
|
|
+ </picker>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 入库单多选提示 -->
|
|
|
+ <view v-if="selectorType === 'storageOrder' && selectedStorageOrders.length > 0" class="selected-tip">
|
|
|
+ 已选择 {{ selectedStorageOrders.length }} 个入库单
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <scroll-view
|
|
|
+ scroll-y
|
|
|
+ class="popup-content"
|
|
|
+ refresher-enabled
|
|
|
+ :refresher-triggered="isRefreshing"
|
|
|
+ @refresherrefresh="onRefresh"
|
|
|
+ @scrolltolower="loadMore"
|
|
|
+ >
|
|
|
+ <view v-for="(item, index) in selectorList" :key="index"
|
|
|
+ class="selector-item"
|
|
|
+ :class="{ 'selected': isStorageOrderSelected(item) }"
|
|
|
+ @click="toggleStorageOrderSelection(item)">
|
|
|
+ <view class="selector-item-content">
|
|
|
+ <!-- 入库单显示复选框 -->
|
|
|
+ <view v-if="selectorType === 'storageOrder'" class="checkbox-wrapper">
|
|
|
+ <text class="checkbox-icon">{{ isStorageOrderSelected(item) ? '✓' : '' }}</text>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="item-info">
|
|
|
+ <!-- 名称(合同名称/采购订单名称/入库单名称) -->
|
|
|
+ <text class="item-name">{{ getSelectorItemName(item) }}</text>
|
|
|
+
|
|
|
+ <!-- 编号(合同编号/采购订单编号/入库单编号) -->
|
|
|
+ <text v-if="getItemCode(item)" class="item-code">{{ getItemCode(item) }}</text>
|
|
|
+
|
|
|
+ <!-- 供应商(采购订单/入库单) -->
|
|
|
+ <text v-if="getItemVendor(item)" class="item-vendor">{{ getItemVendor(item) }}</text>
|
|
|
+
|
|
|
+ <!-- 总金额(采购订单/入库单) -->
|
|
|
+ <text v-if="getItemAmount(item)" class="item-amount">金额:¥{{ getItemAmount(item) }}</text>
|
|
|
+
|
|
|
+ <!-- 单据状态(采购订单/入库单) -->
|
|
|
+ <text v-if="getItemStatus(item)" class="item-status" :class="getStatusClass(item)">{{ getItemStatus(item) }}</text>
|
|
|
+
|
|
|
+ <!-- 创建时间(采购订单/入库单) -->
|
|
|
+ <text v-if="getItemCreateTime(item)" class="item-time">{{ getItemCreateTime(item) }}</text>
|
|
|
+
|
|
|
+ <!-- 合同类型显示(仅合同) -->
|
|
|
+ <text v-if="selectorType === 'contract' && getContractTypeName(item)" class="item-type">
|
|
|
+ 【{{ getContractTypeName(item) }}】
|
|
|
+ </text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view v-if="isLoading && selectorList.length > 0" class="loading-text">
|
|
|
+ <uni-load-more status="loading" />
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view v-else-if="!hasMore && selectorList.length > 0" class="no-more-text">
|
|
|
+ <text>没有更多了</text>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view v-if="selectorList.length === 0 && !isLoading" class="empty-data">
|
|
|
+ <text>{{ searchKeyword ? '暂无相关数据' : '暂无数据' }}</text>
|
|
|
+ </view>
|
|
|
+ </scroll-view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 入库单确认按钮(固定在底部) -->
|
|
|
+ <view v-if="selectorType === 'storageOrder'" class="popup-footer-fixed">
|
|
|
+ <button class="cancel-btn" @click="closePopup">取消</button>
|
|
|
+ <button class="confirm-btn" @click="confirmStorageOrderSelection">确定</button>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </uni-popup>
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup lang="ts">
|
|
|
+import { ref, watch, computed, nextTick, onMounted } from 'vue'
|
|
|
+import { useUserStore } from '@/store/user.js'
|
|
|
+import config from '@/config.js'
|
|
|
+import { uploadSignatureBoardImg, getSeal } from '@/api/process.js'
|
|
|
+import { getSupplierList, getContractListForPayment, getPurchaseOrderList, getStorageOrderList } from '@/api/payment.js'
|
|
|
+import $modal from '@/plugins/modal.js'
|
|
|
+
|
|
|
+const userStore = useUserStore()
|
|
|
+
|
|
|
+const props = defineProps({
|
|
|
+ formData: {
|
|
|
+ type: Object,
|
|
|
+ default: () => ({})
|
|
|
+ },
|
|
|
+ formElements: {
|
|
|
+ type: Array,
|
|
|
+ default: () => []
|
|
|
+ },
|
|
|
+ repeatingForm: {
|
|
|
+ type: Object,
|
|
|
+ default: () => ({ elementItem: [], elements: [] })
|
|
|
+ },
|
|
|
+ isInitiate: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false
|
|
|
+ },
|
|
|
+ editableFields: {
|
|
|
+ type: Array,
|
|
|
+ default: () => []
|
|
|
+ },
|
|
|
+ currentTacheOpinion: {
|
|
|
+ type: Object,
|
|
|
+ default: null
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+const emits = defineEmits(['update', 'signature-change'])
|
|
|
+
|
|
|
+// 表单数据
|
|
|
+const baseForm = ref<any>({
|
|
|
+ payerName: '',
|
|
|
+ payeeName: '',
|
|
|
+ vendorCode: '',
|
|
|
+ contractId: '',
|
|
|
+ contractNumber: '',
|
|
|
+ contractName: '',
|
|
|
+ purchaseOrderNo: '',
|
|
|
+ storageOrderNo: '',
|
|
|
+ orderIdFromMes: '',
|
|
|
+ amountLower: '',
|
|
|
+ amountUpper: '',
|
|
|
+ paymentType: '',
|
|
|
+ paymentTypeName: '',
|
|
|
+ paymentMethod: '',
|
|
|
+ paymentDate: '',
|
|
|
+ purpose: '',
|
|
|
+ payeeBankAccount: '',
|
|
|
+ bankName: '',
|
|
|
+ bankAccount: '',
|
|
|
+ accountId: '',
|
|
|
+ accountName: '',
|
|
|
+ applyDate: '',
|
|
|
+ initiator: '',
|
|
|
+ department: '',
|
|
|
+ depid: null,
|
|
|
+ operator: '',
|
|
|
+ operatorId: ''
|
|
|
+})
|
|
|
+
|
|
|
+const baseFormRules = ref({
|
|
|
+ payerName: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ errorMessage: '请输入单位'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ payeeName: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ errorMessage: '请选择收款单位'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ amountLower: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ errorMessage: '请输入付款金额'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ paymentType: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ errorMessage: '请选择付款类型'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ paymentMethod: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ errorMessage: '请输入付款方式'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ paymentDate: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ errorMessage: '请选择付款日期'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ purpose: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ errorMessage: '请输入用途或理由'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ payeeBankAccount: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ errorMessage: '请输入开户行及账号'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ operator: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ errorMessage: '请选择经办人'
|
|
|
+ }
|
|
|
+ ]
|
|
|
+})
|
|
|
+
|
|
|
+const signaturePopup = ref(null)
|
|
|
+const signatureRef = ref(null)
|
|
|
+const signatureImg = ref('')
|
|
|
+const currentApprovalText = ref('')
|
|
|
+const approvals = ref<any[]>([])
|
|
|
+const signaturePopupShow = ref(false)
|
|
|
+const isLandscape = ref(false)
|
|
|
+
|
|
|
+// 获取指定的审批意见元素
|
|
|
+const getApprovalElement = (fieldName: string) => {
|
|
|
+ if (!props.formElements || !Array.isArray(props.formElements)) {
|
|
|
+ return null
|
|
|
+ }
|
|
|
+ // 从 formElements 中找到对应的字段
|
|
|
+ const elem = props.formElements.find(e => e.tableField === fieldName || e.elementName.includes(fieldName.replace(/_/g, '')))
|
|
|
+ return elem || null
|
|
|
+}
|
|
|
+
|
|
|
+const deptApproverElem = computed(() => getApprovalElement('dept_approver'))
|
|
|
+const accountantElem = computed(() => getApprovalElement('accountant'))
|
|
|
+const financeManagerElem = computed(() => getApprovalElement('finance_manager'))
|
|
|
+const deputyManagerDeptElem = computed(() => getApprovalElement('deputy_manager_dept'))
|
|
|
+const deputyManagerAuditElem = computed(() => getApprovalElement('deputy_manager_audit'))
|
|
|
+const generalManagerElem = computed(() => getApprovalElement('general_manager'))
|
|
|
+const chairmanElem = computed(() => getApprovalElement('chairman'))
|
|
|
+
|
|
|
+const isSeModel = computed(() => props.isInitiate)
|
|
|
+
|
|
|
+const isApprovalFieldEditable = (elem: any) => {
|
|
|
+ if (!elem) return false
|
|
|
+ return props.editableFields && props.editableFields.includes(elem.tableField)
|
|
|
+}
|
|
|
+
|
|
|
+let lastFormInsId = ''
|
|
|
+
|
|
|
+const getFieldEditable = (fieldName: string) => {
|
|
|
+ if (!props.editableFields || props.editableFields.length === 0) {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ return props.editableFields.includes(fieldName)
|
|
|
+}
|
|
|
+
|
|
|
+const isInitiateOrFieldEditable = (fieldName: string) => {
|
|
|
+ return props.isInitiate || getFieldEditable(fieldName)
|
|
|
+}
|
|
|
+
|
|
|
+// 监听表单数据变化
|
|
|
+watch(() => props.formData, (newVal) => {
|
|
|
+ if (!newVal || Object.keys(newVal).length === 0) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const currentFormInsId = newVal.lFormInsId || newVal.universalid || ''
|
|
|
+
|
|
|
+ if (currentFormInsId && currentFormInsId !== lastFormInsId) {
|
|
|
+ lastFormInsId = currentFormInsId
|
|
|
+
|
|
|
+ baseForm.value = {
|
|
|
+ payerName: newVal.payerName || '',
|
|
|
+ payeeName: newVal.payeeName || '',
|
|
|
+ vendorCode: newVal.vendorCode || '',
|
|
|
+ contractId: newVal.contractId || '',
|
|
|
+ contractNumber: newVal.contractNumber || '',
|
|
|
+ contractName: newVal.contractName || '',
|
|
|
+ purchaseOrderNo: newVal.purchaseOrderNo || '',
|
|
|
+ storageOrderNo: newVal.storageOrderNo || '',
|
|
|
+ orderIdFromMes: newVal.orderIdFromMes || '',
|
|
|
+ amountLower: (newVal.amountLower !== undefined && newVal.amountLower !== null) ? String(newVal.amountLower) : '',
|
|
|
+ amountUpper: newVal.amountUpper || '',
|
|
|
+ paymentType: newVal.paymentType || '',
|
|
|
+ paymentTypeName: getPaymentTypeName(newVal.paymentType),
|
|
|
+ paymentMethod: newVal.paymentMethod || '',
|
|
|
+ paymentDate: newVal.paymentDate || '',
|
|
|
+ purpose: newVal.purpose || '',
|
|
|
+ payeeBankAccount: newVal.payeeBankAccount || '',
|
|
|
+ bankName: newVal.bankName || '',
|
|
|
+ bankAccount: newVal.bankAccount || '',
|
|
|
+ accountId: newVal.accountId || '',
|
|
|
+ accountName: newVal.accountName || '',
|
|
|
+ applyDate: newVal.applyDate || '',
|
|
|
+ initiator: newVal.initiator || '',
|
|
|
+ department: newVal.department || '',
|
|
|
+ depid: newVal.depid || null,
|
|
|
+ operator: newVal.operator || '',
|
|
|
+ operatorId: newVal.operatorId || ''
|
|
|
+ }
|
|
|
+ }
|
|
|
+}, { immediate: true, deep: true })
|
|
|
+
|
|
|
+// 监听收款单位变化,如果手动修改则清空关联信息
|
|
|
+let lastPayeeName = ''
|
|
|
+watch(() => baseForm.value.payeeName, (newVal, oldVal) => {
|
|
|
+ // 只在发起或字段可编辑时生效
|
|
|
+ if (!isInitiateOrFieldEditable('payee_name')) return
|
|
|
+
|
|
|
+ // 如果有合同ID,不允许手动修改
|
|
|
+ if (baseForm.value.contractId) return
|
|
|
+
|
|
|
+ // 如果是从有值变为空,不处理
|
|
|
+ if (!newVal && oldVal) return
|
|
|
+
|
|
|
+ // 如果是通过选择器选择的(有vendorCode),不处理
|
|
|
+ if (baseForm.value.vendorCode) return
|
|
|
+
|
|
|
+ // 手动输入时,清空所有关联信息和供应商编码
|
|
|
+ clearRelatedOrders()
|
|
|
+ baseForm.value.vendorCode = ''
|
|
|
+})
|
|
|
+
|
|
|
+// 收款单位输入处理
|
|
|
+function onPayeeInputChange(value: string) {
|
|
|
+ // 如果有合同ID,不允许手动修改
|
|
|
+ if (baseForm.value.contractId) return
|
|
|
+
|
|
|
+ // 手动输入时,立即清空所有关联信息和供应商编码
|
|
|
+ clearRelatedOrders()
|
|
|
+ baseForm.value.vendorCode = ''
|
|
|
+}
|
|
|
+
|
|
|
+function getPaymentTypeName(type: string): string {
|
|
|
+ const typeMap: any = {
|
|
|
+ '1': '预付款',
|
|
|
+ '2': '到付款'
|
|
|
+ }
|
|
|
+ return typeMap[type] || type || '-'
|
|
|
+}
|
|
|
+
|
|
|
+// 打开合同选择器
|
|
|
+async function openContractSelector() {
|
|
|
+ if (!isInitiateOrFieldEditable('contract_number')) return
|
|
|
+ // 检查是否已选择采购订单或入库单
|
|
|
+ if (baseForm.value.purchaseOrderNo || baseForm.value.storageOrderNo) {
|
|
|
+ $modal.msg('已选择采购单或入库单,不能同时选择合同!请先清除。')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ selectorType.value = 'contract'
|
|
|
+ selectedContractType.value = '' // 重置合同类型筛选
|
|
|
+ searchKeyword.value = ''
|
|
|
+ currentPage.value = 1
|
|
|
+ hasMore.value = true
|
|
|
+ selectorList.value = []
|
|
|
+ await loadContracts(1, false)
|
|
|
+ selectorPopup.value.open()
|
|
|
+}
|
|
|
+
|
|
|
+// 打开采购订单选择器
|
|
|
+async function openPurchaseOrderSelector() {
|
|
|
+ if (!isInitiateOrFieldEditable('purchase_order_no')) return
|
|
|
+ // 检查是否已选择合同或入库单
|
|
|
+ if (baseForm.value.contractId || baseForm.value.storageOrderNo) {
|
|
|
+ $modal.msg('已选择合同或入库单,不能同时选择采购订单!请先清除。')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!baseForm.value.vendorCode) {
|
|
|
+ $modal.msg('请先选择收款单位(供应商)!')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ selectorType.value = 'purchaseOrder'
|
|
|
+ searchKeyword.value = ''
|
|
|
+ currentPage.value = 1
|
|
|
+ hasMore.value = true
|
|
|
+ selectorList.value = []
|
|
|
+ await loadPurchaseOrders(1, false)
|
|
|
+ selectorPopup.value.open()
|
|
|
+}
|
|
|
+
|
|
|
+// 打开入库单选择器
|
|
|
+async function openStorageOrderSelector() {
|
|
|
+ if (!isInitiateOrFieldEditable('storage_order_no')) return
|
|
|
+ // 检查是否已选择合同或采购订单
|
|
|
+ if (baseForm.value.contractId || baseForm.value.purchaseOrderNo) {
|
|
|
+ $modal.msg('已选择合同或采购订单,不能同时选择入库单!请先清除。')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!baseForm.value.vendorCode) {
|
|
|
+ $modal.msg('请先选择收款单位(供应商)!')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ selectorType.value = 'storageOrder'
|
|
|
+ selectedStorageOrders.value = [] // 重置多选列表
|
|
|
+ searchKeyword.value = ''
|
|
|
+ currentPage.value = 1
|
|
|
+ hasMore.value = true
|
|
|
+ selectorList.value = []
|
|
|
+ await loadStorageOrders(1, false)
|
|
|
+ selectorPopup.value.open()
|
|
|
+}
|
|
|
+
|
|
|
+// 打开经办人选择器
|
|
|
+async function openOperatorSelector() {
|
|
|
+ if (!isInitiateOrFieldEditable('operator')) return
|
|
|
+ $modal.msg('人员选择功能待实现')
|
|
|
+}
|
|
|
+
|
|
|
+// 付款类型变化
|
|
|
+function onPaymentTypeChange(e: any) {
|
|
|
+ const index = e.detail.value
|
|
|
+ baseForm.value.paymentType = paymentTypeList.value[index].value
|
|
|
+ baseForm.value.paymentTypeName = paymentTypeList.value[index].name
|
|
|
+
|
|
|
+ // 根据付款类型切换显示字段并清空被隐藏的字段
|
|
|
+ togglePaymentFields(baseForm.value.paymentType)
|
|
|
+}
|
|
|
+
|
|
|
+// 根据付款类型切换显示字段
|
|
|
+function togglePaymentFields(paymentType: string) {
|
|
|
+ if (paymentType === '1') { // 预付款
|
|
|
+ // 清空入库单编号
|
|
|
+ baseForm.value.storageOrderNo = ''
|
|
|
+ baseForm.value.orderIdFromMes = ''
|
|
|
+ } else if (paymentType === '2') { // 到付款
|
|
|
+ // 清空采购订单编号
|
|
|
+ baseForm.value.purchaseOrderNo = ''
|
|
|
+ baseForm.value.orderIdFromMes = ''
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 付款日期变化
|
|
|
+function onPaymentDateChange(e: any) {
|
|
|
+ baseForm.value.paymentDate = e.detail.value
|
|
|
+}
|
|
|
+
|
|
|
+// 金额小写输入
|
|
|
+function onAmountLowerInput(value: string) {
|
|
|
+ // 限制只能输入数字和小数点(参考PC端restrictToNumber函数)
|
|
|
+ const restricted = restrictToNumber(value)
|
|
|
+ // 如果值被修改了,更新表单值
|
|
|
+ if (restricted !== value) {
|
|
|
+ baseForm.value.amountLower = restricted
|
|
|
+ }
|
|
|
+ // 转换为大写
|
|
|
+ convertToChinese()
|
|
|
+}
|
|
|
+
|
|
|
+// 限制输入框只能输入数字和小数点(参考PC端)
|
|
|
+function restrictToNumber(value: string): string {
|
|
|
+ if (!value) return value
|
|
|
+
|
|
|
+ // 只允许数字、小数点,且小数点只能有一个
|
|
|
+ let newValue = value.replace(/[^0-9.]/g, '')
|
|
|
+
|
|
|
+ // 确保小数点不超过一个
|
|
|
+ const dotIndex = newValue.indexOf('.')
|
|
|
+ if (dotIndex !== -1) {
|
|
|
+ newValue = newValue.substring(0, dotIndex + 1) + newValue.substring(dotIndex + 1).replace(/\./g, '')
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果第一个字符是小数点,则在前面加0
|
|
|
+ if (newValue.charAt(0) === '.') {
|
|
|
+ newValue = '0' + newValue
|
|
|
+ }
|
|
|
+
|
|
|
+ return newValue
|
|
|
+}
|
|
|
+
|
|
|
+// 金额转大写
|
|
|
+function convertToChinese() {
|
|
|
+ // 先清理输入值
|
|
|
+ if (baseForm.value.amountLower) {
|
|
|
+ baseForm.value.amountLower = restrictToNumber(baseForm.value.amountLower)
|
|
|
+ }
|
|
|
+
|
|
|
+ const amount = parseFloat(baseForm.value.amountLower)
|
|
|
+ if (isNaN(amount) || amount <= 0) {
|
|
|
+ baseForm.value.amountUpper = ''
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ const cnNums = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']
|
|
|
+ const cnIntRadice = ['', '拾', '佰', '仟']
|
|
|
+ const cnIntUnits = ['', '万', '亿', '兆']
|
|
|
+ const cnDecUnits = ['角', '分']
|
|
|
+ const cnInteger = '整'
|
|
|
+ const cnIntLast = '元'
|
|
|
+
|
|
|
+ let integerNum = Math.floor(amount)
|
|
|
+ let decimalNum = Math.round((amount - integerNum) * 100)
|
|
|
+
|
|
|
+ let chineseStr = ''
|
|
|
+
|
|
|
+ if (integerNum === 0) {
|
|
|
+ chineseStr = cnNums[0] + cnIntLast
|
|
|
+ } else {
|
|
|
+ let intLen = integerNum.toString().length
|
|
|
+ let zeroCount = 0
|
|
|
+ for (let i = 0; i < intLen; i++) {
|
|
|
+ let n = integerNum.toString().charAt(i)
|
|
|
+ let p = intLen - i - 1
|
|
|
+ let q = Math.floor(p / 4)
|
|
|
+ let m = p % 4
|
|
|
+
|
|
|
+ if (n === '0') {
|
|
|
+ zeroCount++
|
|
|
+ } else {
|
|
|
+ if (zeroCount > 0) {
|
|
|
+ chineseStr += cnNums[0]
|
|
|
+ }
|
|
|
+ zeroCount = 0
|
|
|
+ chineseStr += cnNums[parseInt(n)] + cnIntRadice[m]
|
|
|
+ }
|
|
|
+
|
|
|
+ if (m === 0 && zeroCount < 4) {
|
|
|
+ chineseStr += cnIntUnits[q]
|
|
|
+ }
|
|
|
+ }
|
|
|
+ chineseStr += cnIntLast
|
|
|
+ }
|
|
|
+
|
|
|
+ if (decimalNum !== 0) {
|
|
|
+ let jiao = Math.floor(decimalNum / 10)
|
|
|
+ let fen = decimalNum % 10
|
|
|
+
|
|
|
+ if (jiao !== 0) {
|
|
|
+ chineseStr += cnNums[jiao] + cnDecUnits[0]
|
|
|
+ }
|
|
|
+ if (fen !== 0) {
|
|
|
+ chineseStr += cnNums[fen] + cnDecUnits[1]
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ chineseStr += cnInteger
|
|
|
+ }
|
|
|
+
|
|
|
+ baseForm.value.amountUpper = chineseStr
|
|
|
+}
|
|
|
+
|
|
|
+// 打开供应商选择器
|
|
|
+async function openSupplierSelector() {
|
|
|
+ if (baseForm.value.contractId) {
|
|
|
+ $modal.msg('已选择合同,收款单位由合同自动填充,如需修改请先清除合同!')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ selectorType.value = 'supplier'
|
|
|
+ selectorList.value = []
|
|
|
+ searchKeyword.value = ''
|
|
|
+ await loadSuppliers(1, false)
|
|
|
+ selectorPopup.value.open()
|
|
|
+}
|
|
|
+
|
|
|
+// 加载供应商列表
|
|
|
+async function loadSuppliers(page: number, append: boolean = false) {
|
|
|
+ if (isLoading.value) return
|
|
|
+
|
|
|
+ isLoading.value = true
|
|
|
+ if (page === 1) {
|
|
|
+ isRefreshing.value = true
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ const res = await getSupplierList(
|
|
|
+ userStore.user.useId,
|
|
|
+ page,
|
|
|
+ pageSize,
|
|
|
+ searchKeyword.value
|
|
|
+ )
|
|
|
+
|
|
|
+ if (res.returnCode === '1') {
|
|
|
+ const result = res.returnParams
|
|
|
+ const newList = result.list || []
|
|
|
+
|
|
|
+ if (append) {
|
|
|
+ selectorList.value = [...selectorList.value, ...newList]
|
|
|
+ } else {
|
|
|
+ selectorList.value = newList
|
|
|
+ }
|
|
|
+
|
|
|
+ hasMore.value = selectorList.value.length < result.total
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('加载供应商失败', error)
|
|
|
+ } finally {
|
|
|
+ isLoading.value = false
|
|
|
+ isRefreshing.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 加载合同列表
|
|
|
+async function loadContracts(page: number, append: boolean = false) {
|
|
|
+ if (isLoading.value) return
|
|
|
+
|
|
|
+ isLoading.value = true
|
|
|
+ if (page === 1) {
|
|
|
+ isRefreshing.value = true
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ const res = await getContractListForPayment(
|
|
|
+ userStore.user.useId,
|
|
|
+ page,
|
|
|
+ pageSize,
|
|
|
+ searchKeyword.value,
|
|
|
+ '', // supplierCode 不传,由后端根据其他条件筛选
|
|
|
+ selectedContractType.value // 合同类型筛选
|
|
|
+ )
|
|
|
+
|
|
|
+ if (res.returnCode === '1') {
|
|
|
+ const result = res.returnParams
|
|
|
+ const newList = result.list || []
|
|
|
+
|
|
|
+ if (append) {
|
|
|
+ selectorList.value = [...selectorList.value, ...newList]
|
|
|
+ } else {
|
|
|
+ selectorList.value = newList
|
|
|
+ }
|
|
|
+
|
|
|
+ hasMore.value = selectorList.value.length < result.total
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('加载合同失败', error)
|
|
|
+ } finally {
|
|
|
+ isLoading.value = false
|
|
|
+ isRefreshing.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 加载采购订单列表
|
|
|
+async function loadPurchaseOrders(page: number, append: boolean = false) {
|
|
|
+ if (isLoading.value) return
|
|
|
+
|
|
|
+ isLoading.value = true
|
|
|
+ if (page === 1) {
|
|
|
+ isRefreshing.value = true
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ const res = await getPurchaseOrderList(
|
|
|
+ userStore.user.useId,
|
|
|
+ page,
|
|
|
+ pageSize,
|
|
|
+ baseForm.value.vendorCode
|
|
|
+ )
|
|
|
+
|
|
|
+ if (res.returnCode === '1') {
|
|
|
+ const result = res.returnParams
|
|
|
+ const newList = result.list || []
|
|
|
+
|
|
|
+ if (append) {
|
|
|
+ selectorList.value = [...selectorList.value, ...newList]
|
|
|
+ } else {
|
|
|
+ selectorList.value = newList
|
|
|
+ }
|
|
|
+
|
|
|
+ hasMore.value = selectorList.value.length < result.total
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('加载采购订单失败', error)
|
|
|
+ } finally {
|
|
|
+ isLoading.value = false
|
|
|
+ isRefreshing.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 加载入库单列表
|
|
|
+async function loadStorageOrders(page: number, append: boolean = false) {
|
|
|
+ if (isLoading.value) return
|
|
|
+
|
|
|
+ isLoading.value = true
|
|
|
+ if (page === 1) {
|
|
|
+ isRefreshing.value = true
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ const res = await getStorageOrderList(
|
|
|
+ userStore.user.useId,
|
|
|
+ page,
|
|
|
+ pageSize,
|
|
|
+ baseForm.value.vendorCode
|
|
|
+ )
|
|
|
+
|
|
|
+ if (res.returnCode === '1') {
|
|
|
+ const result = res.returnParams
|
|
|
+ const newList = result.list || []
|
|
|
+
|
|
|
+ if (append) {
|
|
|
+ selectorList.value = [...selectorList.value, ...newList]
|
|
|
+ } else {
|
|
|
+ selectorList.value = newList
|
|
|
+ }
|
|
|
+
|
|
|
+ hasMore.value = selectorList.value.length < result.total
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('加载入库单失败', error)
|
|
|
+ } finally {
|
|
|
+ isLoading.value = false
|
|
|
+ isRefreshing.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 付款类型列表
|
|
|
+const paymentTypeList = ref([
|
|
|
+ { value: '1', name: '预付款' },
|
|
|
+ { value: '2', name: '到付款' }
|
|
|
+])
|
|
|
+
|
|
|
+const paymentTypeIndex = computed(() => {
|
|
|
+ const index = paymentTypeList.value.findIndex(item => item.value === baseForm.value.paymentType)
|
|
|
+ return index >= 0 ? index : 0
|
|
|
+})
|
|
|
+
|
|
|
+// 选择器相关
|
|
|
+const selectorPopup = ref(null)
|
|
|
+const selectorType = ref('supplier') // supplier, contract, purchaseOrder, storageOrder
|
|
|
+const selectorList = ref<any[]>([])
|
|
|
+const currentPage = ref(1)
|
|
|
+const pageSize = 20
|
|
|
+const hasMore = ref(true)
|
|
|
+const isLoading = ref(false)
|
|
|
+const isRefreshing = ref(false)
|
|
|
+const searchKeyword = ref('')
|
|
|
+
|
|
|
+// 入库单多选相关
|
|
|
+const selectedStorageOrders = ref<any[]>([])
|
|
|
+
|
|
|
+// 合同类型相关
|
|
|
+const contractTypeList = ref([
|
|
|
+ { value: '', name: '全部' },
|
|
|
+ { value: '1', name: '销售合同' },
|
|
|
+ { value: '2', name: '采购合同' },
|
|
|
+ { value: '3', name: '技术服务合同' }
|
|
|
+])
|
|
|
+const selectedContractType = ref('')
|
|
|
+const selectedContractTypeName = computed(() => {
|
|
|
+ if (!selectedContractType.value) return ''
|
|
|
+ const type = contractTypeList.value.find(t => t.value === selectedContractType.value)
|
|
|
+ return type ? type.name : ''
|
|
|
+})
|
|
|
+
|
|
|
+// 选择器标题
|
|
|
+const selectorTitle = computed(() => {
|
|
|
+ const titles: Record<string, string> = {
|
|
|
+ supplier: '选择供应商',
|
|
|
+ contract: '选择合同',
|
|
|
+ purchaseOrder: '选择采购订单',
|
|
|
+ storageOrder: '选择入库单'
|
|
|
+ }
|
|
|
+ return titles[selectorType.value] || '选择'
|
|
|
+})
|
|
|
+
|
|
|
+// 搜索框提示
|
|
|
+const searchPlaceholder = computed(() => {
|
|
|
+ const placeholders: Record<string, string> = {
|
|
|
+ supplier: '输入供应商名称搜索',
|
|
|
+ contract: '输入合同名称搜索',
|
|
|
+ purchaseOrder: '输入采购订单编号搜索',
|
|
|
+ storageOrder: '输入入库单编号搜索'
|
|
|
+ }
|
|
|
+ return placeholders[selectorType.value] || '请输入搜索内容'
|
|
|
+})
|
|
|
+
|
|
|
+function closePopup() {
|
|
|
+ selectorPopup.value.close()
|
|
|
+}
|
|
|
+
|
|
|
+function handleSearch() {
|
|
|
+ currentPage.value = 1
|
|
|
+ if (selectorType.value === 'supplier') {
|
|
|
+ loadSuppliers(1, false)
|
|
|
+ } else if (selectorType.value === 'contract') {
|
|
|
+ loadContracts(1, false)
|
|
|
+ } else if (selectorType.value === 'purchaseOrder') {
|
|
|
+ loadPurchaseOrders(1, false)
|
|
|
+ } else if (selectorType.value === 'storageOrder') {
|
|
|
+ loadStorageOrders(1, false)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function onRefresh() {
|
|
|
+ currentPage.value = 1
|
|
|
+ if (selectorType.value === 'supplier') {
|
|
|
+ loadSuppliers(1, false)
|
|
|
+ } else if (selectorType.value === 'contract') {
|
|
|
+ loadContracts(1, false)
|
|
|
+ } else if (selectorType.value === 'purchaseOrder') {
|
|
|
+ loadPurchaseOrders(1, false)
|
|
|
+ } else if (selectorType.value === 'storageOrder') {
|
|
|
+ loadStorageOrders(1, false)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function loadMore() {
|
|
|
+ if (!hasMore.value || isLoading.value) return
|
|
|
+ currentPage.value++
|
|
|
+
|
|
|
+ if (selectorType.value === 'supplier') {
|
|
|
+ loadSuppliers(currentPage.value, true)
|
|
|
+ } else if (selectorType.value === 'contract') {
|
|
|
+ loadContracts(currentPage.value, true)
|
|
|
+ } else if (selectorType.value === 'purchaseOrder') {
|
|
|
+ loadPurchaseOrders(currentPage.value, true)
|
|
|
+ } else if (selectorType.value === 'storageOrder') {
|
|
|
+ loadStorageOrders(currentPage.value, true)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 合同类型变化
|
|
|
+function onContractTypeChange(e: any) {
|
|
|
+ const selectedIndex = e.detail.value
|
|
|
+ selectedContractType.value = contractTypeList.value[selectedIndex].value
|
|
|
+ // 重新加载合同列表
|
|
|
+ loadContracts(1, false)
|
|
|
+}
|
|
|
+
|
|
|
+// 获取选择器项名称
|
|
|
+function getSelectorItemName(item: any): string {
|
|
|
+ if (selectorType.value === 'supplier') {
|
|
|
+ return item.vendorName || item.name || ''
|
|
|
+ } else if (selectorType.value === 'contract') {
|
|
|
+ return item.contract_name || item.contractName || ''
|
|
|
+ } else if (selectorType.value === 'purchaseOrder') {
|
|
|
+ return item.purchaseCode || item.purchase_code || ''
|
|
|
+ } else if (selectorType.value === 'storageOrder') {
|
|
|
+ return item.recptCode || item.recpt_code || ''
|
|
|
+ }
|
|
|
+ return ''
|
|
|
+}
|
|
|
+
|
|
|
+function getItemCode(item: any): string {
|
|
|
+ if (selectorType.value === 'supplier') {
|
|
|
+ return item.vendorCode || item.code || ''
|
|
|
+ } else if (selectorType.value === 'contract') {
|
|
|
+ return item.contract_number || item.contractNumber || ''
|
|
|
+ }
|
|
|
+ return ''
|
|
|
+}
|
|
|
+
|
|
|
+// 获取供应商名称(采购订单/入库单)
|
|
|
+function getItemVendor(item: any): string {
|
|
|
+ if (selectorType.value === 'purchaseOrder' || selectorType.value === 'storageOrder') {
|
|
|
+ return item.vendorName || item.vendor_name || ''
|
|
|
+ }
|
|
|
+ return ''
|
|
|
+}
|
|
|
+
|
|
|
+// 获取总金额(采购订单/入库单)
|
|
|
+function getItemAmount(item: any): string {
|
|
|
+ if (selectorType.value === 'purchaseOrder' || selectorType.value === 'storageOrder') {
|
|
|
+ const amount = item.totalAmount || item.total_amount
|
|
|
+ if (amount) {
|
|
|
+ return Number(amount).toFixed(2)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return ''
|
|
|
+}
|
|
|
+
|
|
|
+// 获取单据状态(采购订单/入库单)
|
|
|
+function getItemStatus(item: any): string {
|
|
|
+ if (selectorType.value === 'purchaseOrder' || selectorType.value === 'storageOrder') {
|
|
|
+ const status = item.status
|
|
|
+ if (status === 'CONFIRMED') {
|
|
|
+ return '已确认'
|
|
|
+ } else if (status === 'FINISHED') {
|
|
|
+ return '已完成'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return ''
|
|
|
+}
|
|
|
+
|
|
|
+// 获取状态样式类
|
|
|
+function getStatusClass(item: any): string {
|
|
|
+ const status = item.status
|
|
|
+ if (status === 'CONFIRMED') {
|
|
|
+ return 'status-confirmed'
|
|
|
+ } else if (status === 'FINISHED') {
|
|
|
+ return 'status-finished'
|
|
|
+ }
|
|
|
+ return ''
|
|
|
+}
|
|
|
+
|
|
|
+// 获取创建时间(采购订单/入库单)
|
|
|
+function getItemCreateTime(item: any): string {
|
|
|
+ if (selectorType.value === 'purchaseOrder' || selectorType.value === 'storageOrder') {
|
|
|
+ return item.createTime || item.create_time || ''
|
|
|
+ }
|
|
|
+ return ''
|
|
|
+}
|
|
|
+
|
|
|
+// 获取合同类型名称(根据 contract_type 值)
|
|
|
+function getContractTypeName(item: any): string {
|
|
|
+ const type = item.contract_type
|
|
|
+ if (!type) return ''
|
|
|
+
|
|
|
+ const typeMap: Record<string, string> = {
|
|
|
+ '1': '销售合同',
|
|
|
+ '2': '采购合同',
|
|
|
+ '3': '技术服务合同'
|
|
|
+ }
|
|
|
+
|
|
|
+ // 优先使用后端返回的 contract_type_name,如果没有则根据 contract_type 转换
|
|
|
+ return item.contract_type_name || typeMap[String(type)] || ''
|
|
|
+}
|
|
|
+
|
|
|
+// 检查入库单是否已选中
|
|
|
+function isStorageOrderSelected(item: any): boolean {
|
|
|
+ if (selectorType.value !== 'storageOrder') return false
|
|
|
+ return selectedStorageOrders.value.some(order =>
|
|
|
+ order.recptCode === (item.recptCode || item.recpt_code)
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+// 切换入库单选择状态
|
|
|
+function toggleStorageOrderSelection(item: any) {
|
|
|
+ if (selectorType.value !== 'storageOrder') {
|
|
|
+ // 非入库单类型,直接选择并关闭
|
|
|
+ selectItem(item)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ const recptCode = item.recptCode || item.recpt_code
|
|
|
+ const index = selectedStorageOrders.value.findIndex(order => order.recptCode === recptCode)
|
|
|
+
|
|
|
+ if (index > -1) {
|
|
|
+ // 已选中,取消选择
|
|
|
+ selectedStorageOrders.value.splice(index, 1)
|
|
|
+ } else {
|
|
|
+ // 未选中,添加到选择列表
|
|
|
+ selectedStorageOrders.value.push({
|
|
|
+ recptCode: recptCode,
|
|
|
+ recptId: item.recptId || item.recpt_id,
|
|
|
+ recptName: item.recptName || item.recpt_name,
|
|
|
+ vendorName: item.vendorName || item.vendor_name,
|
|
|
+ totalAmount: item.totalAmount || item.total_amount
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 确认入库单选择
|
|
|
+function confirmStorageOrderSelection() {
|
|
|
+ if (selectedStorageOrders.value.length === 0) {
|
|
|
+ $modal.msg('请至少选择一个入库单!')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将选中的入库单编号拼接(用逗号分隔)
|
|
|
+ const storageOrderNos = selectedStorageOrders.value.map(order => order.recptCode).join(',')
|
|
|
+ const storageOrderIds = selectedStorageOrders.value.map(order => order.recptId).join(',')
|
|
|
+
|
|
|
+ baseForm.value.storageOrderNo = storageOrderNos
|
|
|
+ baseForm.value.orderIdFromMes = storageOrderIds
|
|
|
+
|
|
|
+ // 清空合同、采购订单
|
|
|
+ baseForm.value.contractId = ''
|
|
|
+ baseForm.value.contractNumber = ''
|
|
|
+ baseForm.value.contractName = ''
|
|
|
+ baseForm.value.purchaseOrderNo = ''
|
|
|
+
|
|
|
+ closePopup()
|
|
|
+}
|
|
|
+
|
|
|
+function selectItem(item: any) {
|
|
|
+ // 入库单使用多选逻辑,不走这里
|
|
|
+ if (selectorType.value === 'storageOrder') return
|
|
|
+
|
|
|
+ if (selectorType.value === 'supplier') {
|
|
|
+ baseForm.value.payeeName = item.vendorName || item.name || ''
|
|
|
+ baseForm.value.vendorCode = item.vendorCode || item.code || ''
|
|
|
+ // 清空合同、采购订单、入库单
|
|
|
+ clearRelatedOrders()
|
|
|
+ } else if (selectorType.value === 'contract') {
|
|
|
+ // 检查合同类型,只允许采购合同(2)和技术服务合同(3)
|
|
|
+ const contractType = item.contract_type
|
|
|
+ if (contractType !== 2 && contractType !== 3) {
|
|
|
+ $modal.msg('只能选择采购合同或技术服务合同!')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ baseForm.value.contractId = item.universalid || item.id || ''
|
|
|
+ baseForm.value.contractNumber = item.contract_number || item.contractNumber || ''
|
|
|
+ baseForm.value.contractName = item.contract_name || item.contractName || ''
|
|
|
+ // 回填供应商信息
|
|
|
+ baseForm.value.payeeName = item.supplierName || item.supplier_name || ''
|
|
|
+ baseForm.value.vendorCode = item.supplierCode || item.supplier_code || ''
|
|
|
+ // 清空采购订单、入库单
|
|
|
+ baseForm.value.purchaseOrderNo = ''
|
|
|
+ baseForm.value.storageOrderNo = ''
|
|
|
+ baseForm.value.orderIdFromMes = ''
|
|
|
+ } else if (selectorType.value === 'purchaseOrder') {
|
|
|
+ baseForm.value.purchaseOrderNo = item.purchaseCode || item.purchase_code || ''
|
|
|
+ baseForm.value.orderIdFromMes = item.purchaseId || item.purchase_id || ''
|
|
|
+ // 清空合同、入库单
|
|
|
+ baseForm.value.contractId = ''
|
|
|
+ baseForm.value.contractNumber = ''
|
|
|
+ baseForm.value.contractName = ''
|
|
|
+ baseForm.value.storageOrderNo = ''
|
|
|
+ }
|
|
|
+
|
|
|
+ closePopup()
|
|
|
+}
|
|
|
+
|
|
|
+// 清除合同
|
|
|
+function clearContract() {
|
|
|
+ baseForm.value.contractId = ''
|
|
|
+ baseForm.value.contractNumber = ''
|
|
|
+ baseForm.value.contractName = ''
|
|
|
+ // 注意:不清空收款单位和供应商编码
|
|
|
+}
|
|
|
+
|
|
|
+// 清除采购订单
|
|
|
+function clearPurchaseOrder() {
|
|
|
+ baseForm.value.purchaseOrderNo = ''
|
|
|
+ baseForm.value.orderIdFromMes = ''
|
|
|
+}
|
|
|
+
|
|
|
+// 清除入库单
|
|
|
+function clearStorageOrder() {
|
|
|
+ baseForm.value.storageOrderNo = ''
|
|
|
+ baseForm.value.orderIdFromMes = ''
|
|
|
+ // 清空多选列表
|
|
|
+ selectedStorageOrders.value = []
|
|
|
+}
|
|
|
+
|
|
|
+// 清空所有关联信息
|
|
|
+function clearRelatedOrders() {
|
|
|
+ baseForm.value.contractId = ''
|
|
|
+ baseForm.value.contractNumber = ''
|
|
|
+ baseForm.value.contractName = ''
|
|
|
+ baseForm.value.purchaseOrderNo = ''
|
|
|
+ baseForm.value.storageOrderNo = ''
|
|
|
+ baseForm.value.orderIdFromMes = ''
|
|
|
+}
|
|
|
+
|
|
|
+// 处理审批意见签名
|
|
|
+const currentApprovalFieldName = ref('')
|
|
|
+const approvalSealInfo = ref<Record<string, any>>({})
|
|
|
+
|
|
|
+function handleApprovalSignature(fieldName: string) {
|
|
|
+ currentApprovalFieldName.value = fieldName
|
|
|
+ signaturePopupShow.value = false
|
|
|
+ nextTick(() => {
|
|
|
+ signaturePopupShow.value = true
|
|
|
+ })
|
|
|
+ signaturePopup.value.open()
|
|
|
+}
|
|
|
+
|
|
|
+function handleAutoSeal(fieldName: string) {
|
|
|
+ const elem = getApprovalElement(fieldName)
|
|
|
+ if (elem) {
|
|
|
+ getSeal(userStore.user.useId).then(({ returnParams }) => {
|
|
|
+ const elem = getApprovalElement(fieldName)
|
|
|
+ elem.defaultValue = returnParams.sealFileId.universalid
|
|
|
+ elem.sealImgPath = returnParams.sealFileId.path
|
|
|
+ approvalSealInfo.value[fieldName] = {
|
|
|
+ sealInsId: returnParams.sealFileId.universalid,
|
|
|
+ sealFileId: returnParams.sealFileId.universalid,
|
|
|
+ left: 0,
|
|
|
+ top: 0
|
|
|
+ }
|
|
|
+ }).catch(err => {
|
|
|
+ $modal.msgError('获取签名失败:' + err)
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function initSignature() {
|
|
|
+ signaturePopupShow.value = false
|
|
|
+ setTimeout(() => {
|
|
|
+ signaturePopupShow.value = true
|
|
|
+ }, 100)
|
|
|
+}
|
|
|
+
|
|
|
+function onclickSignatureButton(event: string) {
|
|
|
+ switch (event) {
|
|
|
+ case 'undo':
|
|
|
+ signatureRef.value.undo()
|
|
|
+ break
|
|
|
+ case 'clear':
|
|
|
+ signatureRef.value.clear()
|
|
|
+ break
|
|
|
+ case 'save':
|
|
|
+ signatureRef.value.canvasToTempFilePath({
|
|
|
+ success: (res: any) => {
|
|
|
+ if (res.isEmpty) {
|
|
|
+ $modal.msgError('签名不能为空!')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (res.tempFilePath.substring(0, 'data:image/png;base64,'.length) == 'data:image/png;base64,') {
|
|
|
+ const _fileData = res.tempFilePath
|
|
|
+ uploadSignatureBoardImg(userStore.user.useId, _fileData, getApprovalElement(currentApprovalFieldName.value).tableField)
|
|
|
+ .then(({ returnParams }) => {
|
|
|
+ const elem = getApprovalElement(currentApprovalFieldName.value)
|
|
|
+ elem.defaultValue = returnParams.sealInsID
|
|
|
+ elem.sealImgPath = returnParams.path
|
|
|
+ // 保存印章信息(用于后端处理)
|
|
|
+ // sealInsID 是手写签名的实例 ID,但 imgval 需要使用印章模板 ID
|
|
|
+ // 对于手写签名,印章模板 ID 与签名实例 ID 相同
|
|
|
+ approvalSealInfo.value[currentApprovalFieldName.value] = {
|
|
|
+ sealInsId: returnParams.sealInsID, // 签名实例 ID
|
|
|
+ sealFileId: returnParams.sealInsID, // 印章模板 ID(手写签名时与实例 ID 相同)
|
|
|
+ left: 0, // 默认左边距为 0
|
|
|
+ top: 0 // 默认上边距为 0
|
|
|
+ }
|
|
|
+ currentApprovalFieldName.value = ''
|
|
|
+ signaturePopupShow.value = false
|
|
|
+ signaturePopup.value.close()
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ uni.getFileSystemManager().readFile({
|
|
|
+ filePath: res.tempFilePath,
|
|
|
+ encoding: 'base64',
|
|
|
+ success: (fileData: any) => {
|
|
|
+ const _fileData = 'data:image/png;base64,' + fileData.data
|
|
|
+ uploadSignatureBoardImg(userStore.user.useId, _fileData, getApprovalElement(currentApprovalFieldName.value).tableField)
|
|
|
+ .then(({ returnParams }) => {
|
|
|
+ const elem = getApprovalElement(currentApprovalFieldName.value)
|
|
|
+ elem.defaultValue = returnParams.sealInsID
|
|
|
+ elem.sealImgPath = returnParams.path
|
|
|
+ // 保存印章信息(用于后端处理)
|
|
|
+ // sealInsID 是手写签名的实例 ID,但 imgval 需要使用印章模板 ID
|
|
|
+ // 对于手写签名,印章模板 ID 与签名实例 ID 相同
|
|
|
+ approvalSealInfo.value[currentApprovalFieldName.value] = {
|
|
|
+ sealInsId: returnParams.sealInsID, // 签名实例 ID
|
|
|
+ sealFileId: returnParams.sealInsID, // 印章模板 ID(手写签名时与实例 ID 相同)
|
|
|
+ left: 0, // 默认左边距为 0
|
|
|
+ top: 0 // 默认上边距为 0
|
|
|
+ }
|
|
|
+ currentApprovalFieldName.value = ''
|
|
|
+ signaturePopupShow.value = false
|
|
|
+ signaturePopup.value.close()
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ break
|
|
|
+ case 'landscape':
|
|
|
+ isLandscape.value = !isLandscape.value
|
|
|
+ initSignature()
|
|
|
+ break
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function clearSignature() {
|
|
|
+ onclickSignatureButton('clear')
|
|
|
+}
|
|
|
+
|
|
|
+function saveSignature() {
|
|
|
+ onclickSignatureButton('save')
|
|
|
+}
|
|
|
+
|
|
|
+function closeSignature() {
|
|
|
+ signaturePopupShow.value = false
|
|
|
+ signaturePopup.value.close()
|
|
|
+}
|
|
|
+
|
|
|
+// 暴露验证方法给父组件
|
|
|
+defineExpose({
|
|
|
+ validate: async () => {
|
|
|
+ if (!baseForm.value.payerName) {
|
|
|
+ return Promise.reject(new Error('请输入单位'))
|
|
|
+ }
|
|
|
+ if (!baseForm.value.payeeName) {
|
|
|
+ return Promise.reject(new Error('请选择收款单位'))
|
|
|
+ }
|
|
|
+ if (!baseForm.value.amountLower || Number(baseForm.value.amountLower) <= 0) {
|
|
|
+ return Promise.reject(new Error('请输入有效的付款金额'))
|
|
|
+ }
|
|
|
+ if (!baseForm.value.paymentType) {
|
|
|
+ return Promise.reject(new Error('请选择付款类型'))
|
|
|
+ }
|
|
|
+ if (!baseForm.value.paymentMethod) {
|
|
|
+ return Promise.reject(new Error('请输入付款方式'))
|
|
|
+ }
|
|
|
+ if (!baseForm.value.paymentDate) {
|
|
|
+ return Promise.reject(new Error('请选择付款日期'))
|
|
|
+ }
|
|
|
+ if (!baseForm.value.purpose) {
|
|
|
+ return Promise.reject(new Error('请输入用途或理由'))
|
|
|
+ }
|
|
|
+ if (!baseForm.value.payeeBankAccount) {
|
|
|
+ return Promise.reject(new Error('请输入开户行及账号'))
|
|
|
+ }
|
|
|
+ if (!baseForm.value.operator) {
|
|
|
+ return Promise.reject(new Error('请选择经办人'))
|
|
|
+ }
|
|
|
+ if (!baseForm.value.accountId) {
|
|
|
+ return Promise.reject(new Error('没有默认付款账户!请检查是否已设置默认账户。'))
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证审批意见字段
|
|
|
+ const approvalFields = [
|
|
|
+ { fieldName: 'dept_approver', msg: '部门负责人签名' },
|
|
|
+ { fieldName: 'accountant', msg: '经办会计签名' },
|
|
|
+ { fieldName: 'finance_manager', msg: '财务经理签名' },
|
|
|
+ { fieldName: 'deputy_manager_dept', msg: '分管副总部门签名' },
|
|
|
+ { fieldName: 'deputy_manager_audit', msg: '分管副总审计签名' },
|
|
|
+ { fieldName: 'general_manager', msg: '公司总经理签名' },
|
|
|
+ { fieldName: 'chairman', msg: '董事长签名' }
|
|
|
+ ]
|
|
|
+
|
|
|
+ for (const field of approvalFields) {
|
|
|
+ const elem = getApprovalElement(field.fieldName)
|
|
|
+ if (elem) {
|
|
|
+ if (props.editableFields && props.editableFields.includes(field.fieldName)) {
|
|
|
+ if (!elem.defaultValue || elem.defaultValue === '') {
|
|
|
+ return Promise.reject(new Error(field.msg + '不能为空!'))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return Promise.resolve()
|
|
|
+ },
|
|
|
+ getFormElements: () => {
|
|
|
+ const formElements: any[] = []
|
|
|
+
|
|
|
+ Object.keys(baseForm.value).forEach(key => {
|
|
|
+ const value = baseForm.value[key]
|
|
|
+ if (value !== undefined && value !== null) {
|
|
|
+ formElements.push({
|
|
|
+ name: key,
|
|
|
+ value: String(value),
|
|
|
+ type: '0'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ const approvalFields = ['dept_approver', 'accountant', 'finance_manager', 'deputy_manager_dept', 'deputy_manager_audit', 'general_manager', 'chairman']
|
|
|
+ approvalFields.forEach(fieldName => {
|
|
|
+ const elem = getApprovalElement(fieldName)
|
|
|
+ if (elem) {
|
|
|
+ formElements.push({
|
|
|
+ name: fieldName,
|
|
|
+ value: elem.defaultValue || '',
|
|
|
+ type: elem.type || '0'
|
|
|
+ })
|
|
|
+ // 添加签名图片的 imgval 值(用于后端处理)
|
|
|
+ // 格式:sealFileId_left_top(必须使用印章模板 ID,而不是签名实例 ID)
|
|
|
+ if (approvalSealInfo.value[fieldName]) {
|
|
|
+ const sealInfo = approvalSealInfo.value[fieldName]
|
|
|
+ formElements.push({
|
|
|
+ name: fieldName + '_imgval',
|
|
|
+ value: `${sealInfo.sealFileId}_${sealInfo.left}_${sealInfo.top}`,
|
|
|
+ type: '0'
|
|
|
+ })
|
|
|
+ } else if (elem.sealImgPath && elem.defaultValue) {
|
|
|
+ // 兼容旧数据:如果有 sealImgPath 和 defaultValue,提取 sealId 构建 imgval
|
|
|
+ // sealImgPath 格式:/shares/document/seal/593268258724500.png
|
|
|
+ const sealIdMatch = elem.sealImgPath.match(/\/seal\/(\d+)\.png$/)
|
|
|
+ if (sealIdMatch) {
|
|
|
+ const sealId = sealIdMatch[1]
|
|
|
+ formElements.push({
|
|
|
+ name: fieldName + '_imgval',
|
|
|
+ value: `${sealId}_0_0`,
|
|
|
+ type: '0'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ return formElements
|
|
|
+ },
|
|
|
+ getFormData: () => {
|
|
|
+ const formData: any = {
|
|
|
+ ...baseForm.value
|
|
|
+ }
|
|
|
+
|
|
|
+ const approvalFields = ['dept_approver', 'accountant', 'finance_manager', 'deputy_manager_dept', 'deputy_manager_audit', 'general_manager', 'chairman']
|
|
|
+ approvalFields.forEach(fieldName => {
|
|
|
+ const elem = getApprovalElement(fieldName)
|
|
|
+ if (elem) {
|
|
|
+ formData[fieldName] = elem.defaultValue || ''
|
|
|
+ // 添加签名图片的 imgval 值(用于后端处理)
|
|
|
+ // 格式:sealFileId_left_top(必须使用印章模板 ID,而不是签名实例 ID)
|
|
|
+ if (approvalSealInfo.value[fieldName]) {
|
|
|
+ const sealInfo = approvalSealInfo.value[fieldName]
|
|
|
+ formData[fieldName + '_imgval'] = `${sealInfo.sealFileId}_${sealInfo.left}_${sealInfo.top}`
|
|
|
+ } else if (elem.sealImgPath && elem.defaultValue) {
|
|
|
+ // 兼容旧数据:如果有 sealImgPath 和 defaultValue,提取 sealId 构建 imgval
|
|
|
+ // sealImgPath 格式:/shares/document/seal/593268258724500.png
|
|
|
+ const sealIdMatch = elem.sealImgPath.match(/\/seal\/(\d+)\.png$/)
|
|
|
+ if (sealIdMatch) {
|
|
|
+ const sealId = sealIdMatch[1]
|
|
|
+ formData[fieldName + '_imgval'] = `${sealId}_0_0`
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ return formData
|
|
|
+ }
|
|
|
+})
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.payment-form-component {
|
|
|
+ ::v-deep .uni-forms {
|
|
|
+ .uni-forms-item__content {
|
|
|
+ .uni-easyinput__content-input {
|
|
|
+ font-size: calc(14px + 1.2*(1rem - 16px)) !important;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #333;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .selector-wrapper {
|
|
|
+ padding: 8px 10px;
|
|
|
+ border: 1px solid #e5e5e5;
|
|
|
+ border-radius: 4px;
|
|
|
+ min-height: 36px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ cursor: pointer;
|
|
|
+
|
|
|
+ &:active {
|
|
|
+ background-color: #f5f5f5;
|
|
|
+ }
|
|
|
+
|
|
|
+ .placeholder {
|
|
|
+ color: #999;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 收款单位输入框和按钮的布局样式
|
|
|
+ .payee-input-wrapper {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 8px;
|
|
|
+
|
|
|
+ ::v-deep .uni-easyinput {
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+
|
|
|
+ .select-supplier-btn {
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .picker-wrapper {
|
|
|
+ padding: 8px 10px;
|
|
|
+ border: 1px solid #e5e5e5;
|
|
|
+ border-radius: 4px;
|
|
|
+ min-height: 36px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+
|
|
|
+ .placeholder {
|
|
|
+ color: #999;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .textarea-input {
|
|
|
+ width: 100%;
|
|
|
+ min-height: 80px;
|
|
|
+ padding: 8px 10px;
|
|
|
+ border: 1px solid #e5e5e5;
|
|
|
+ border-radius: 4px;
|
|
|
+ font-size: 14px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .textarea-display {
|
|
|
+ width: 100%;
|
|
|
+ min-height: 36px;
|
|
|
+ padding: 8px 10px;
|
|
|
+ border: 1px solid #e5e5e5;
|
|
|
+ border-radius: 4px;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #333;
|
|
|
+ line-height: 1.5;
|
|
|
+ }
|
|
|
+
|
|
|
+ .element_value_container {
|
|
|
+ .signature_img {
|
|
|
+ width: 180px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .signature_container {
|
|
|
+ background-color: #f5f5f5;
|
|
|
+ height: 40vh;
|
|
|
+ width: 90vw;
|
|
|
+
|
|
|
+ .signature_content {
|
|
|
+ height: 80%;
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+
|
|
|
+ .signature_button_container {
|
|
|
+ height: 20%;
|
|
|
+ width: 100%;
|
|
|
+
|
|
|
+ button {
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .signature_container_landscape {
|
|
|
+ height: 100vh;
|
|
|
+ width: 100vw;
|
|
|
+
|
|
|
+ .signature_content {
|
|
|
+ height: 85%;
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+
|
|
|
+ .signature_button_container {
|
|
|
+ margin-top: 10%;
|
|
|
+ height: 15%;
|
|
|
+ width: 100%;
|
|
|
+
|
|
|
+ button {
|
|
|
+ height: 100%;
|
|
|
+ width: 100%;
|
|
|
+ transform: rotate(90deg);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .selector-popup {
|
|
|
+ width: 90%;
|
|
|
+ max-width: 500px;
|
|
|
+ height: 60vh; // 固定高度
|
|
|
+ background-color: #fff;
|
|
|
+ border-radius: 12px;
|
|
|
+ overflow: hidden;
|
|
|
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
|
|
+
|
|
|
+ position: relative;
|
|
|
+ margin: 0 auto;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column; // 垂直布局
|
|
|
+
|
|
|
+ .popup-header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ padding: 15px;
|
|
|
+ border-bottom: 1px solid #e5e5e5;
|
|
|
+
|
|
|
+ .popup-title {
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .popup-content-wrapper {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ overflow: hidden;
|
|
|
+ padding-bottom: 50px; // 为固定底部按钮留出空间
|
|
|
+
|
|
|
+ .search-bar {
|
|
|
+ display: flex;
|
|
|
+ gap: 10px;
|
|
|
+ padding: 10px 15px;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .filter-bar {
|
|
|
+ padding: 10px 15px;
|
|
|
+ background-color: #fff;
|
|
|
+ border-bottom: 1px solid #e5e5e5;
|
|
|
+
|
|
|
+ .picker-filter {
|
|
|
+ padding: 8px 12px;
|
|
|
+ background-color: #f5f5f5;
|
|
|
+ border-radius: 4px;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #333;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .selected-tip {
|
|
|
+ padding: 10px 15px;
|
|
|
+ background-color: #f0f9eb;
|
|
|
+ border-bottom: 1px solid #e5e5e5;
|
|
|
+ color: #67c23a;
|
|
|
+ font-size: 13px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .popup-content {
|
|
|
+ flex: 1;
|
|
|
+ overflow-y: auto;
|
|
|
+
|
|
|
+ .selector-item {
|
|
|
+ padding: 10px 12px;
|
|
|
+ border-bottom: 1px solid #f0f0f0;
|
|
|
+
|
|
|
+ &:active {
|
|
|
+ background-color: #f5f5f5;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.selected {
|
|
|
+ background-color: #f0f9eb;
|
|
|
+ }
|
|
|
+
|
|
|
+ .selector-item-content {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+
|
|
|
+ // 入库单复选框样式
|
|
|
+ .checkbox-wrapper {
|
|
|
+ width: 24px;
|
|
|
+ height: 24px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ flex-shrink: 0;
|
|
|
+
|
|
|
+ .checkbox-icon {
|
|
|
+ font-size: 18px;
|
|
|
+ color: #4caf50;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .item-info {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ align-items: center;
|
|
|
+ gap: 4px;
|
|
|
+
|
|
|
+ .item-name {
|
|
|
+ font-size: 15px;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #333;
|
|
|
+ flex-basis: 100%;
|
|
|
+ margin-bottom: 4px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .item-code,
|
|
|
+ .item-spec {
|
|
|
+ font-size: 13px;
|
|
|
+ color: #666;
|
|
|
+ white-space: nowrap;
|
|
|
+ font-weight: 500;
|
|
|
+ }
|
|
|
+
|
|
|
+ .item-vendor {
|
|
|
+ font-size: 13px;
|
|
|
+ color: #999;
|
|
|
+ white-space: nowrap;
|
|
|
+ }
|
|
|
+
|
|
|
+ .item-amount {
|
|
|
+ font-size: 13px;
|
|
|
+ color: #f76560;
|
|
|
+ white-space: nowrap;
|
|
|
+ font-weight: 500;
|
|
|
+ }
|
|
|
+
|
|
|
+ .item-status {
|
|
|
+ font-size: 12px;
|
|
|
+ padding: 2px 8px;
|
|
|
+ border-radius: 4px;
|
|
|
+ white-space: nowrap;
|
|
|
+
|
|
|
+ &.status-confirmed {
|
|
|
+ background-color: #ffecdb;
|
|
|
+ color: #ff8800;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.status-finished {
|
|
|
+ background-color: #e8f5e9;
|
|
|
+ color: #4caf50;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .item-time {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #999;
|
|
|
+ white-space: nowrap;
|
|
|
+ flex-basis: 100%;
|
|
|
+ margin-top: 2px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .item-type {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #ff6b6b;
|
|
|
+ white-space: nowrap;
|
|
|
+ margin-left: 4px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .item-code::after {
|
|
|
+ content: ' | ';
|
|
|
+ margin: 0 4px;
|
|
|
+ color: #ddd;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .loading-text {
|
|
|
+ text-align: center;
|
|
|
+ padding: 12px;
|
|
|
+ color: #909399;
|
|
|
+ font-size: 13px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .no-more-text {
|
|
|
+ text-align: center;
|
|
|
+ padding: 12px;
|
|
|
+ color: #909399;
|
|
|
+ font-size: 13px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .empty-data {
|
|
|
+ text-align: center;
|
|
|
+ padding: 30px;
|
|
|
+ color: #909399;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 入库单多选提示
|
|
|
+ .selected-tip {
|
|
|
+ padding: 8px 12px;
|
|
|
+ background-color: #e8f5e9;
|
|
|
+ color: #4caf50;
|
|
|
+ font-size: 13px;
|
|
|
+ text-align: center;
|
|
|
+ border-bottom: 1px solid #c8e6c9;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 入库单确认按钮区域(固定在底部)
|
|
|
+ .popup-footer-fixed {
|
|
|
+ position: absolute;
|
|
|
+ bottom: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ padding: 12px;
|
|
|
+ border-top: 1px solid #e5e5e5;
|
|
|
+ background-color: #fff;
|
|
|
+ display: flex;
|
|
|
+ gap: 12px;
|
|
|
+ z-index: 10;
|
|
|
+ box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1);
|
|
|
+ }
|
|
|
+
|
|
|
+ .popup-footer-fixed .cancel-btn {
|
|
|
+ flex: 1 !important;
|
|
|
+ height: 44px !important;
|
|
|
+ line-height: 44px !important;
|
|
|
+ font-size: 16px !important;
|
|
|
+ background-color: #f5f5f5 !important;
|
|
|
+ color: #333 !important;
|
|
|
+ border: none !important;
|
|
|
+ border-radius: 8px !important;
|
|
|
+ margin: 0 !important;
|
|
|
+ padding: 0 !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .popup-footer-fixed .confirm-btn {
|
|
|
+ flex: 1 !important;
|
|
|
+ height: 44px !important;
|
|
|
+ line-height: 44px !important;
|
|
|
+ font-size: 16px !important;
|
|
|
+ background-color: #007aff !important;
|
|
|
+ color: #fff !important;
|
|
|
+ border: none !important;
|
|
|
+ border-radius: 8px !important;
|
|
|
+ margin: 0 !important;
|
|
|
+ padding: 0 !important;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 基本信息中的禁用字段样式优化(参考 edit/index.vue)
|
|
|
+::v-deep .uni-forms {
|
|
|
+ .uni-forms-item__content {
|
|
|
+ .uni-easyinput__content-input {
|
|
|
+ font-size: calc(14px + 1.2*(1rem - 16px)) !important;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #333;
|
|
|
+ }
|
|
|
+
|
|
|
+ .uni-date {
|
|
|
+ .uni-icons {
|
|
|
+ font-size: calc(22px + 1.2*(1rem - 16px)) !important;
|
|
|
+ font-weight: 500;
|
|
|
+ }
|
|
|
+
|
|
|
+ .uni-date__x-input {
|
|
|
+ height: auto;
|
|
|
+ font-size: calc(14px + 1.2*(1rem - 16px)) !important;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #333;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|