| | |
| | | <template> |
| | | <view class="account-detail"> |
| | | <van-nav-bar |
| | | title="编辑开票台账" |
| | | left-text="返回" |
| | | left-arrow |
| | | @click-left="goBack" |
| | | fixed |
| | | placeholder |
| | | /> |
| | | |
| | | <van-form @submit="submitForm" ref="formRef" label-width="110px" input-align="right" error-message-align="right" scroll-to-error scroll-to-error-position="center"> |
| | | <van-cell-group title="基本信息" inset> |
| | | <van-field v-model="form.salesContractNo" label="销售合同号" readonly /> |
| | | <van-field v-model="form.customerName" label="客户名称" readonly /> |
| | | <van-field v-model="form.invoiceNo" label="发票号" placeholder="请输入" required :rules="[{ required: true, message: '请输入发票号' }]" /> |
| | | <van-field v-model="form.invoiceTotal" label="发票金额(元)" type="number" placeholder="请输入" required :rules="[{ required: true, message: '请输入发票金额' }]" /> |
| | | <view class="tip-text" v-if="form.taxInclusiveTotalPrice">合同总额:{{ formatAmount(form.taxInclusiveTotalPrice) }} 元</view> |
| | | <van-field v-model="form.invoicePerson" label="开票人" readonly /> |
| | | <van-field v-model="form.invoiceDate" label="开票日期" readonly placeholder="请选择" @click="showInvoiceDatePicker = true" required :rules="[{ required: true, message: '请选择开票日期' }]" /> |
| | | </van-cell-group> |
| | | |
| | | <van-cell-group title="附件材料(仅支持 pdf)" inset> |
| | | <van-uploader |
| | | accept=".pdf" |
| | | multiple |
| | | :after-read="afterReadUpload" |
| | | :before-read="beforeReadPdf" |
| | | > |
| | | <van-button class="upload-btn" icon="plus" type="primary" block>上传文件</van-button> |
| | | </van-uploader> |
| | | <view class="uploaded-list" v-if="fileList.length"> |
| | | <view class="uploaded-item" v-for="(f, idx) in fileList" :key="idx"> |
| | | <text class="file-name">{{ f.name || getFileNameFromUrl(f.url) }}</text> |
| | | <van-button size="mini" type="danger" plain @click="removeUploaded(idx)">移除</van-button> |
| | | </view> |
| | | </view> |
| | | </van-cell-group> |
| | | |
| | | <view class="account-view"> |
| | | <!-- 使用通用页面头部组件 --> |
| | | <PageHeader title="发票详情" @back="goBack" /> |
| | | |
| | | <!-- 表单内容 --> |
| | | <u-form @submit="submitForm" ref="formRef" label-width="110" input-align="right" error-message-align="right"> |
| | | <u-cell-group title="基本信息"> |
| | | <u-form-item label="销售合同号" border-bottom> |
| | | <u-input v-model="form.salesContractNo" readonly /> |
| | | </u-form-item> |
| | | <u-form-item label="客户名称" border-bottom> |
| | | <u-input v-model="form.customerName" readonly /> |
| | | </u-form-item> |
| | | <u-form-item label="发票号" prop="invoiceNo" required border-bottom> |
| | | <u-input v-model="form.invoiceNo" placeholder="请输入" /> |
| | | </u-form-item> |
| | | <u-form-item label="发票金额(元)" prop="invoiceTotal" required border-bottom> |
| | | <u-input v-model="form.invoiceTotal" type="number" placeholder="请输入" /> |
| | | </u-form-item> |
| | | <u-form-item label="开票人" border-bottom> |
| | | <u-input v-model="form.invoicePerson" readonly /> |
| | | </u-form-item> |
| | | <u-form-item label="开票日期" prop="invoiceDate" required border-bottom> |
| | | <u-input v-model="form.invoiceDate" readonly placeholder="请选择" @click="showInvoiceDatePicker = true" /> |
| | | </u-form-item> |
| | | </u-cell-group> |
| | | |
| | | <!-- <u-cell-group title="附件材料(仅支持 pdf)">--> |
| | | <!-- <u-upload--> |
| | | <!-- accept=".pdf"--> |
| | | <!-- multiple--> |
| | | <!-- :afterRead="afterReadUpload"--> |
| | | <!-- :beforeRead="beforeReadPdf"--> |
| | | <!-- >--> |
| | | <!-- <u-button class="upload-btn" type="primary">--> |
| | | <!-- 上传文件--> |
| | | <!-- </u-button>--> |
| | | <!-- </u-upload>--> |
| | | <!-- <view class="uploaded-list" v-if="fileList.length">--> |
| | | <!-- <view class="uploaded-item" v-for="(f, idx) in fileList" :key="idx">--> |
| | | <!-- <text class="file-name">{{ f.name || getFileNameFromUrl(f.url) }}</text>--> |
| | | <!-- <u-button size="mini" type="error" plain @click="removeUploaded(idx)">移除</u-button>--> |
| | | <!-- </view>--> |
| | | <!-- </view>--> |
| | | <!-- </u-cell-group>--> |
| | | |
| | | <!-- 提交按钮 --> |
| | | <view class="footer-btns"> |
| | | <van-button class="cancel-btn" @click="goBack">取消</van-button> |
| | | <van-button class="save-btn" native-type="submit" form-type="submit">保存</van-button> |
| | | <u-button class="cancel-btn" @click="goBack">取消</u-button> |
| | | <u-button class="save-btn" type="primary" @click="submitForm">保存</u-button> |
| | | </view> |
| | | </van-form> |
| | | </u-form> |
| | | |
| | | <van-popup v-model:show="showInvoiceDatePicker" position="bottom"> |
| | | <van-date-picker |
| | | v-model="currentInvoiceDate" |
| | | <!-- 开票日期选择器 --> |
| | | <u-popup v-model="showInvoiceDatePicker" mode="bottom"> |
| | | <u-datetime-picker |
| | | v-model="invoiceDateValue" |
| | | title="选择开票日期" |
| | | @confirm="onInvoiceDateConfirm" |
| | | @cancel="showInvoiceDatePicker = false" |
| | | /> |
| | | </van-popup> |
| | | </u-popup> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | |
| | | // 替换 toast 方法 |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | |
| | | const showLoadingToast = (message) => { |
| | | uni.showLoading({ |
| | | title: message || '加载中...' |
| | | }) |
| | | } |
| | | |
| | | const closeToast = () => { |
| | | uni.hideLoading() |
| | | } |
| | | |
| | | import { ref, onMounted } from 'vue' |
| | | import { showToast, showLoadingToast, closeToast } from 'vant' |
| | | import dayjs from 'dayjs' |
| | | import { formatDateToYMD } from '@/utils/ruoyi' |
| | | import useUserStore from '@/store/modules/user' |
| | | import { getToken } from '@/utils/auth' |
| | | import { invoiceLedgerProductInfo, invoiceLedgerSaveOrUpdate } from '@/api/salesManagement/invoiceLedger.js' |
| | |
| | | return num.toFixed(2) |
| | | } |
| | | |
| | | const onInvoiceDateConfirm = ({ selectedValues }) => { |
| | | form.value.invoiceDate = selectedValues.join('-') |
| | | currentInvoiceDate.value = selectedValues |
| | | showInvoiceDatePicker.value = false |
| | | // 日期确认事件 |
| | | const onInvoiceDateConfirm = (e) => { |
| | | form.value.invoiceDate = formatDateToYMD(e.value) |
| | | currentInvoiceDate.value = formatDateToYMD(e.value) |
| | | showInvoiceDatePicker.value = false; |
| | | } |
| | | |
| | | // 上传前校验(兼容 Vant Uploader 的 file/fileList 结构) |
| | |
| | | |
| | | const uploadSingleFile = async (fileObj) => { |
| | | return new Promise((resolve, reject) => { |
| | | showLoadingToast({ message: '正在上传...' }) |
| | | showLoadingToast('正在上传...') |
| | | const baseUrl = config.baseUrl + '/invoiceLedger/uploadFile' |
| | | |
| | | const filePath = fileObj?.url || fileObj?.tempFilePath || fileObj?.file?.path |
| | |
| | | |
| | | const loadDetail = async (id) => { |
| | | try { |
| | | showLoadingToast({ message: '加载中...' }) |
| | | showLoadingToast('加载中...') |
| | | const res = await invoiceLedgerProductInfo({ id }) |
| | | const data = res?.data || res |
| | | form.value = { ...data } |
| | |
| | | if (!form.value.invoiceNo) { showToast('请输入发票号'); return } |
| | | if (!form.value.invoiceTotal) { showToast('请输入发票金额'); return } |
| | | if (!form.value.invoiceDate) { showToast('请选择开票日期'); return } |
| | | showLoadingToast({ message: '提交中...' }) |
| | | showLoadingToast('提交中...') |
| | | form.value.fileList = fileList.value |
| | | await invoiceLedgerSaveOrUpdate(form.value) |
| | | closeToast() |
| | |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .account-detail { |
| | | @import '@/static/scss/form-common.scss'; |
| | | .account-view { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 5rem; |
| | | } |
| | | |
| | | .info-section { |
| | | background: #fff; |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .info-grid { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | padding: 16px; |
| | | } |
| | | |
| | | .info-item { |
| | | display: flex; |
| | | width: 100%; |
| | | margin-bottom: 12px; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .info-label { |
| | | font-size: 14px; |
| | | color: #999; |
| | | min-width: 100px; |
| | | } |
| | | |
| | | .info-value { |
| | | font-size: 14px; |
| | | color: #333; |
| | | flex: 1; |
| | | } |
| | | |
| | | .info-value.highlight { |
| | | color: #2979ff; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .info-value.medium { |
| | | font-size: 16px; |
| | | } |
| | | } |
| | | |
| | | .uploaded-list { padding: 8px 16px 0 16px; } |
| | | .uploaded-item { display: flex; align-items: center; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid #f5f5f5; } |
| | | .file-name { font-size: 12px; color: #333; margin-right: 8px; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } |
| | | .tip-text { padding: 4px 16px 0 16px; font-size: 12px; color: #888; } |
| | | .footer-btns { position: fixed; left: 0; right: 0; bottom: 0; background: #fff; display: flex; justify-content: space-around; align-items: center; padding: 0.75rem 0; box-shadow: 0 -0.125rem 0.5rem rgba(0,0,0,0.05); z-index: 1000; } |
| | | .cancel-btn { font-weight: 400; font-size: 1rem; color: #FFFFFF; width: 6.375rem; background: #C7C9CC; box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; } |
| | | .save-btn { font-weight: 400; font-size: 1rem; color: #FFFFFF; width: 14rem; background: linear-gradient( 140deg, #00BAFF 0%, #006CFB 100%); box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; } |
| | | .footer-btns { |
| | | position: fixed; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background: #fff; |
| | | display: flex; |
| | | justify-content: space-around; |
| | | align-items: center; |
| | | padding: 0.75rem 0; |
| | | box-shadow: 0 -0.125rem 0.5rem rgba(0,0,0,0.05); |
| | | z-index: 1000; |
| | | } |
| | | .cancel-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #FFFFFF; |
| | | width: 6.375rem; |
| | | background: #C7C9CC; |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | .save-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #FFFFFF; |
| | | width: 14rem; |
| | | background: linear-gradient( 140deg, #00BAFF 0%, #006CFB 100%); |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | </style> |
| | | |