| | |
| | | <template> |
| | | <view class="equipment-detail"> |
| | | <view class="account-detail"> |
| | | <!-- 使用通用页面头部组件 --> |
| | | <PageHeader title="设备台账详情" @back="goBack" /> |
| | | |
| | | <!-- 表单内容 --> |
| | | <u-form @submit="sendForm" ref="formRef" label-width="110" input-align="right" error-message-align="right"> |
| | | <u-form @submit="sendForm" ref="formRef" :model="form" :rules="formRules" label-width="110"> |
| | | <!-- 基本信息 --> |
| | | <u-cell-group title="基本信息"> |
| | | <u-form-item label="设备名称" prop="deviceName" required border-bottom> |
| | |
| | | <u-form-item label="规格型号" prop="deviceModel" required border-bottom> |
| | | <u-input |
| | | v-model="form.deviceModel" |
| | | :disabled="(form.deviceModel != null && operationType === 'edit')" |
| | | placeholder="请输入规格型号" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="设备编号" prop="deviceNumber" required border-bottom> |
| | | <!-- <u-form-item label="设备品牌" prop="deviceBrand" required border-bottom> |
| | | <u-input |
| | | v-model="form.deviceNumber" |
| | | placeholder="请输入设备编号" |
| | | v-model="form.deviceBrand" |
| | | placeholder="请输入设备品牌" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="购买日期" prop="purchaseDate" required border-bottom> |
| | | </u-form-item> --> |
| | | <u-form-item label="供应商" prop="supplierName" required border-bottom> |
| | | <u-input |
| | | v-model="form.purchaseDate" |
| | | placeholder="请选择购买日期" |
| | | readonly |
| | | @click="showDatePicker" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="购买价格" prop="purchasePrice" required border-bottom> |
| | | <u-input |
| | | v-model="form.purchasePrice" |
| | | type="number" |
| | | placeholder="请输入购买价格" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="供应商" prop="supplier" required border-bottom> |
| | | <u-input |
| | | v-model="form.supplier" |
| | | v-model="form.supplierName" |
| | | placeholder="请输入供应商" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="使用部门" prop="department" required border-bottom> |
| | | <!-- <u-form-item label="存放位置" prop="storageLocation" required border-bottom> |
| | | <u-input |
| | | v-model="form.department" |
| | | placeholder="请输入使用部门" |
| | | v-model="form.storageLocation" |
| | | placeholder="请输入存放位置" |
| | | clearable |
| | | /> |
| | | </u-form-item> --> |
| | | <u-form-item label="单位" prop="unit" required border-bottom> |
| | | <u-input |
| | | v-model="form.unit" |
| | | placeholder="请输入单位" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="税率" prop="taxRate" required border-bottom> |
| | | <!-- <u-form-item label="启用折旧" prop="enableDepreciation" required border-bottom> |
| | | <u-switch |
| | | v-model="form.enableDepreciation" |
| | | :active-value="true" |
| | | :inactive-value="false" |
| | | /> |
| | | </u-form-item> --> |
| | | <u-form-item label="数量" prop="number" required border-bottom> |
| | | <u-input |
| | | v-model="form.number" |
| | | type="number" |
| | | placeholder="请输入数量" |
| | | clearable |
| | | @blur="mathNum" |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="含税单价" prop="taxIncludingPriceUnit" required border-bottom> |
| | | <u-input |
| | | v-model="form.taxIncludingPriceUnit" |
| | | type="number" |
| | | placeholder="请输入含税单价" |
| | | clearable |
| | | @blur="mathNum" |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="含税总价" prop="taxIncludingPriceTotal" required border-bottom> |
| | | <u-input |
| | | v-model="form.taxIncludingPriceTotal" |
| | | type="number" |
| | | placeholder="自动生成" |
| | | disabled |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="税率(%)" prop="taxRate" required border-bottom> |
| | | <u-input |
| | | v-model="form.taxRate" |
| | | placeholder="请选择税率" |
| | | readonly |
| | | @click="showTaxRatePicker" |
| | | clearable |
| | | @click="showTaxRatePicker = true" |
| | | /> |
| | | <template #right> |
| | | <u-icon name="arrow-right" @click="showTaxRatePicker = true"></u-icon> |
| | | </template> |
| | | <up-action-sheet |
| | | :show="showTaxRatePicker" |
| | | :actions="taxRateActionList" |
| | | title="选择税率" |
| | | @select="onTaxRateSelect" |
| | | @close="showTaxRatePicker = false" |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="使用状态" prop="status" required border-bottom> |
| | | <u-form-item label="不含税总价" prop="unTaxIncludingPriceTotal" required border-bottom> |
| | | <u-input |
| | | v-model="form.status" |
| | | placeholder="请输入使用状态" |
| | | clearable |
| | | v-model="form.unTaxIncludingPriceTotal" |
| | | type="number" |
| | | placeholder="自动生成" |
| | | disabled |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="备注" border-bottom> |
| | | <u-textarea |
| | | v-model="form.remark" |
| | | placeholder="请输入备注" |
| | | :maxlength="200" |
| | | count |
| | | :autoHeight="true" |
| | | <u-form-item label="录入日期" prop="createTime" required border-bottom> |
| | | <u-input |
| | | v-model="form.createTime" |
| | | placeholder="请选择录入日期" |
| | | readonly |
| | | @click="showDatePicker" |
| | | clearable |
| | | /> |
| | | <template #right> |
| | | <u-icon name="arrow-right" @click="showDatePicker"></u-icon> |
| | | </template> |
| | | </u-form-item> |
| | | </u-cell-group> |
| | | |
| | | <!-- 提交按钮 --> |
| | | <view class="footer-btns"> |
| | | <u-button class="cancel-btn" @click="goBack">取消</u-button> |
| | | <u-button class="save-btn" type="primary" @click="sendForm" :loading="loading">保存</u-button> |
| | | </view> |
| | | </u-form> |
| | | |
| | | <!-- 提交按钮 --> |
| | | <view class="footer-btns"> |
| | | <u-button class="cancel-btn" @click="goBack">取消</u-button> |
| | | <u-button class="save-btn" type="primary" @click="sendForm" :loading="loading">保存</u-button> |
| | | </view> |
| | | </u-form> |
| | | |
| | | <!-- 税率选择器 --> |
| | | <u-popup v-model="showTaxRate" mode="bottom"> |
| | | <u-picker |
| | | v-model="taxRatePickerValue" |
| | | :columns="taxRateOptions" |
| | | @confirm="onTaxRateConfirm" |
| | | @cancel="showTaxRate = false" |
| | | /> |
| | | </u-popup> |
| | | |
| | | <!-- 日期选择器 --> |
| | | <u-popup v-model="showDate" mode="bottom"> |
| | | <u-datetime-picker |
| | | v-model="currentDate" |
| | | title="选择日期" |
| | | <!-- 日期选择器 --> |
| | | <up-datetime-picker |
| | | :show="showDate" |
| | | v-model="pickerDateValue" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDate = false" |
| | | mode="date" |
| | | /> |
| | | </u-popup> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | // 替换 Vant 的 toast |
| | | // import { showToast } from 'vant'; |
| | | |
| | | // 替换 toast 方法 |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | |
| | | import { ref, computed, onMounted } from 'vue'; |
| | | import { onShow } from '@dcloudio/uni-app'; |
| | |
| | | calculateTaxIncludeTotalPrice, |
| | | calculateTaxExclusiveTotalPrice, |
| | | } from "@/utils/summarizeTable"; |
| | | import { showToast } from 'vant'; |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | |
| | | defineOptions({ |
| | | name: "设备台账表单", |
| | |
| | | const formRef = ref(null); |
| | | const operationType = ref(''); |
| | | const loading = ref(false); |
| | | const showTaxRate = ref(false); |
| | | const taxRatePickerValue = ref([]); |
| | | const showDate = ref(false); |
| | | const currentDate = ref([new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()]); |
| | | const pickerDateValue = ref(Date.now()); |
| | | const showTaxRatePicker = ref(false); |
| | | const taxRateActionList = ref([ |
| | | { name: '1', value: 1 }, |
| | | { name: '6', value: 6 }, |
| | | { name: '13', value: 13 } |
| | | ]); |
| | | |
| | | // 表单验证规则 |
| | | const formRules = { |
| | | deviceName: [{ required: true, trigger: "blur", message: "请输入" }], |
| | | deviceModel: [{ required: true, trigger: "blur", message: "请输入" }], |
| | | deviceBrand: [{ required: true, trigger: "blur", message: "请输入" }], |
| | | supplierName: [{ required: true, trigger: "blur", message: "请输入" }], |
| | | storageLocation: [{ required: true, trigger: "blur", message: "请输入" }], |
| | | unit: [{ required: true, trigger: "blur", message: "请输入" }], |
| | | number: [{ required: true, trigger: "blur", message: "请输入" }], |
| | | taxIncludingPriceUnit: [{ required: true, trigger: "blur", message: "请输入" }], |
| | | taxRate: [{ required: true, trigger: "change", message: "请输入" }], |
| | | // 数字类型字段需要特殊处理,确保有数值时不会触发必填校验 |
| | | number: [{ |
| | | required: true, |
| | | trigger: "blur", |
| | | message: "请输入", |
| | | validator: (rule, value, callback) => { |
| | | // 对于数字类型,检查是否为有效数字(包括0) |
| | | if (value !== undefined && value !== null && value !== '' && !isNaN(value)) { |
| | | callback(); |
| | | } else { |
| | | callback(new Error('请输入数量')); |
| | | } |
| | | } |
| | | }], |
| | | taxIncludingPriceUnit: [{ |
| | | required: true, |
| | | trigger: "blur", |
| | | message: "请输入", |
| | | validator: (rule, value, callback) => { |
| | | // 对于数字类型,检查是否为有效数字(包括0) |
| | | if (value !== undefined && value !== null && value !== '' && !isNaN(value)) { |
| | | callback(); |
| | | } else { |
| | | callback(new Error('请输入含税单价')); |
| | | } |
| | | } |
| | | }], |
| | | taxRate: [{ |
| | | required: true, |
| | | trigger: "change", |
| | | message: "请选择", |
| | | validator: (rule, value, callback) => { |
| | | // 检查税率是否为有效数字 |
| | | if (value !== undefined && value !== null && value !== '' && !isNaN(value)) { |
| | | callback(); |
| | | } else { |
| | | callback(new Error('请选择税率')); |
| | | } |
| | | } |
| | | }], |
| | | createTime: [{ required: true, trigger: "change", message: "请选择" }], |
| | | }; |
| | | |
| | | // 使用 ref 声明表单数据 |
| | | const form = ref({ |
| | | deviceName: undefined, // 设备名称 |
| | | deviceModel: undefined, // 规格型号 |
| | | deviceBrand: undefined, // 设备品牌 |
| | | supplierName: undefined, // 供应商 |
| | | storageLocation: undefined, // 存放位置 |
| | | unit: undefined, // 单位 |
| | | enableDepreciation: false, // 启用折旧 |
| | | number: undefined, // 数量 |
| | | taxIncludingPriceUnit: undefined, // 含税单价 |
| | | taxIncludingPriceTotal: undefined, // 含税总价 |
| | |
| | | createTime: dayjs().format("YYYY-MM-DD"), // 录入日期 |
| | | }); |
| | | |
| | | // 税率选项 |
| | | const taxRateOptions = computed(() => { |
| | | return [ |
| | | { text: '1', value: 1 }, |
| | | { text: '6', value: 6 }, |
| | | { text: '13', value: 13 } |
| | | ] |
| | | }); |
| | | |
| | | |
| | | // 加载表单数据 |
| | | const loadForm = async (id) => { |
| | |
| | | } |
| | | try { |
| | | const { code, data } = await getLedgerById(id); |
| | | console.log(data); |
| | | |
| | | if (code == 200) { |
| | | form.value.deviceName = data.deviceName; |
| | | form.value.deviceModel = data.deviceModel; |
| | | form.value.deviceBrand = data.deviceBrand || ''; |
| | | form.value.supplierName = data.supplierName; |
| | | form.value.storageLocation = data.storageLocation || ''; |
| | | form.value.unit = data.unit; |
| | | form.value.enableDepreciation = !!data.enableDepreciation; |
| | | form.value.number = data.number; |
| | | form.value.taxIncludingPriceUnit = data.taxIncludingPriceUnit; |
| | | form.value.taxIncludingPriceTotal = data.taxIncludingPriceTotal; |
| | | form.value.taxRate = data.taxRate; |
| | | form.value.unTaxIncludingPriceTotal = data.unTaxIncludingPriceTotal; |
| | | form.value.createTime = data.createTime; |
| | | |
| | | // 数据加载完成后,重置表单验证状态 |
| | | setTimeout(() => { |
| | | clearValidate(); |
| | | }, 100); |
| | | } |
| | | } catch (e) { |
| | | showToast('获取详情失败'); |
| | |
| | | |
| | | // 数学计算 |
| | | const mathNum = () => { |
| | | if (!form.value.taxIncludingPriceUnit) { |
| | | // 只有在新增模式或者字段确实为空时才显示提示 |
| | | if (operationType.value !== 'edit' || (form.value.taxIncludingPriceUnit === undefined || form.value.taxIncludingPriceUnit === '')) { |
| | | showToast("请输入单价"); |
| | | return; |
| | | } |
| | | if (!form.value.number) { |
| | | if (operationType.value !== 'edit' || (form.value.number === undefined || form.value.number === '')) { |
| | | showToast("请输入数量"); |
| | | return; |
| | | } |
| | |
| | | formRef.value?.clearValidate(); |
| | | }; |
| | | |
| | | // 重置表单数据和校验状态 |
| | | const resetForm = () => { |
| | | form.value = { |
| | | deviceName: undefined, |
| | | deviceModel: undefined, |
| | | supplierName: undefined, |
| | | unit: undefined, |
| | | number: undefined, |
| | | taxIncludingPriceUnit: undefined, |
| | | taxIncludingPriceTotal: undefined, |
| | | taxRate: undefined, |
| | | unTaxIncludingPriceTotal: undefined, |
| | | createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), |
| | | }; |
| | | }; |
| | | |
| | | const resetFormAndValidate = () => { |
| | | resetForm(); |
| | | clearValidate(); |
| | | }; |
| | | |
| | | // 提交表单 |
| | | const sendForm = async () => { |
| | | try { |
| | | // 手动验证表单 |
| | | await formRef.value?.validate(); |
| | | // 检查必填字段 |
| | | let isValid = true; |
| | | let errorMessage = ''; |
| | | |
| | | // 检查文本类型必填字段 |
| | | if (!form.value.deviceName || form.value.deviceName.trim() === '') { |
| | | isValid = false; |
| | | errorMessage = '请输入设备名称'; |
| | | } else if (!form.value.deviceModel || form.value.deviceModel.trim() === '') { |
| | | isValid = false; |
| | | errorMessage = '请输入规格型号'; |
| | | } else if (!form.value.deviceBrand || form.value.deviceBrand.trim() === '') { |
| | | isValid = false; |
| | | errorMessage = '请输入设备品牌'; |
| | | } else if (!form.value.supplierName || form.value.supplierName.trim() === '') { |
| | | isValid = false; |
| | | errorMessage = '请输入供应商'; |
| | | } else if (!form.value.storageLocation || form.value.storageLocation.trim() === '') { |
| | | isValid = false; |
| | | errorMessage = '请输入存放位置'; |
| | | } else if (!form.value.unit || form.value.unit.trim() === '') { |
| | | isValid = false; |
| | | errorMessage = '请输入单位'; |
| | | } |
| | | |
| | | // 检查数字类型必填字段 |
| | | else if (form.value.number === undefined || form.value.number === null || form.value.number === '' || isNaN(form.value.number)) { |
| | | isValid = false; |
| | | errorMessage = '请输入数量'; |
| | | } else if (form.value.taxIncludingPriceUnit === undefined || form.value.taxIncludingPriceUnit === null || form.value.taxIncludingPriceUnit === '' || isNaN(form.value.taxIncludingPriceUnit)) { |
| | | isValid = false; |
| | | errorMessage = '请输入含税单价'; |
| | | } else if (form.value.taxRate === undefined || form.value.taxRate === null || form.value.taxRate === '' || isNaN(form.value.taxRate)) { |
| | | isValid = false; |
| | | errorMessage = '请选择税率'; |
| | | } else if (!form.value.createTime || form.value.createTime.trim() === '') { |
| | | isValid = false; |
| | | errorMessage = '请选择录入日期'; |
| | | } |
| | | |
| | | // 如果验证失败,显示错误提示 |
| | | if (!isValid) { |
| | | showToast(errorMessage); |
| | | return; |
| | | } |
| | | |
| | | // 验证通过,显示提交中提示 |
| | | showToast('正在提交表单...'); |
| | | |
| | | loading.value = true; |
| | | const id = getPageId(); |
| | | |
| | | // 准备提交数据,createTime 加上当前时分秒 |
| | | const submitData = { ...form.value }; |
| | | if (submitData.createTime && !submitData.createTime.includes(':')) { |
| | | // 如果 createTime 只包含日期,添加当前时分秒 |
| | | submitData.createTime = submitData.createTime + ' ' + dayjs().format('HH:mm:ss'); |
| | | } |
| | | |
| | | const { code } = id |
| | | const { code, res } = id |
| | | ? await editLedger({ id: id, ...submitData }) |
| | | : await addLedger(submitData); |
| | | |
| | |
| | | }, 1500); |
| | | } else { |
| | | loading.value = false; |
| | | console.log(res); |
| | | } |
| | | } catch (e) { |
| | | loading.value = false; |
| | | showToast('表单验证失败'); |
| | | showToast('提交失败'); |
| | | } |
| | | }; |
| | | |
| | | // 返回上一页 |
| | | const goBack = () => { |
| | | // 使用后清除storage中的ID,避免数据残留 |
| | | uni.removeStorageSync('ledgerId'); |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // 获取页面参数 |
| | | const getPageParams = () => { |
| | | const pages = getCurrentPages(); |
| | | const currentPage = pages[pages.length - 1]; |
| | | const options = currentPage.options; |
| | | |
| | | if (options.id) { |
| | | // 编辑模式,获取详情 |
| | | loadForm(options.id); |
| | | } else { |
| | | // 新增模式 |
| | | try { |
| | | // 优先从storage中获取ID |
| | | const ledgerId = uni.getStorageSync('ledgerId'); |
| | | |
| | | if (ledgerId) { |
| | | // 编辑模式,获取详情 |
| | | loadForm(ledgerId); |
| | | } else { |
| | | // 新增模式 |
| | | operationType.value = 'add'; |
| | | } |
| | | } catch (e) { |
| | | operationType.value = 'add'; |
| | | } |
| | | }; |
| | | |
| | | // 获取页面ID |
| | | const getPageId = () => { |
| | | const pages = getCurrentPages(); |
| | | const currentPage = pages[pages.length - 1]; |
| | | const options = currentPage.options; |
| | | return options.id; |
| | | try { |
| | | // 优先从storage中获取ID |
| | | const ledgerId = uni.getStorageSync('ledgerId'); |
| | | |
| | | if (ledgerId) { |
| | | return ledgerId; |
| | | } |
| | | } catch (e) { |
| | | console.error('获取页面ID出错:', e); |
| | | } |
| | | return null; |
| | | }; |
| | | |
| | | // 显示税率选择器 |
| | | const showTaxRatePicker = () => { |
| | | showTaxRate.value = true; |
| | | }; |
| | | |
| | | // 确认税率选择 |
| | | const onTaxRateConfirm = ({ selectedValues, selectedOptions }) => { |
| | | form.value.taxRate = selectedOptions[0].value; |
| | | taxRatePickerValue.value = selectedValues; |
| | | showTaxRate.value = false; |
| | | // 选择税率 |
| | | const onTaxRateSelect = (e) => { |
| | | form.value.taxRate = e.value; |
| | | showTaxRatePicker.value = false; |
| | | mathNum(); // 重新计算 |
| | | }; |
| | | |
| | |
| | | }; |
| | | |
| | | // 确认日期选择 |
| | | const onDateConfirm = ({ selectedValues }) => { |
| | | const onDateConfirm = (e) => { |
| | | // 只保存年月日,不包含时分秒 |
| | | form.value.createTime = selectedValues.join('-'); |
| | | currentDate.value = selectedValues; |
| | | const date = new Date(e.value); |
| | | form.value.createTime = date.getFullYear() + '-' + |
| | | String(date.getMonth() + 1).padStart(2, '0') + '-' + |
| | | String(date.getDate()).padStart(2, '0'); |
| | | showDate.value = false; |
| | | }; |
| | | |
| | |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/static/scss/form-common.scss'; |
| | | .ledger-detail { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |