mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2026-08-07 03:15:01 +08:00
feat(发票管理): 新增发票详情功能和优化发票信息展示
- 在会员API中添加获取发票详情的接口 - 更新发票模态框,支持电子普通发票和增值税专用发票的详细信息展示 - 在订单详情页和支付页面优化发票信息的显示逻辑 - 增加发票信息的校验和格式化处理
This commit is contained in:
@@ -1,39 +1,83 @@
|
||||
<template>
|
||||
<div class="invoice-modal">
|
||||
<Modal v-model="invoiceAvailable" width="600" footer-hide>
|
||||
<Modal v-model="invoiceAvailable" width="640" footer-hide>
|
||||
<p slot="header">
|
||||
<span>发票信息</span>
|
||||
</p>
|
||||
<!-- 普通发票 -->
|
||||
<div class="nav-content">
|
||||
<Form :model="invoiceForm" ref="form" label-position="left" :rules="ruleInline" :label-width="110">
|
||||
<Form :model="invoiceForm" ref="form" label-position="left" :rules="formRules" :label-width="118">
|
||||
<FormItem label="发票类型">
|
||||
<RadioGroup v-model="invoice" type="button" button-style="solid">
|
||||
<Radio @on-change="changeInvoice" :label="1">电子普通发票</Radio>
|
||||
<Radio :label="2" :disabled="true">增值税专用发票</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<FormItem label="发票抬头">
|
||||
<RadioGroup v-model="type" @on-change="changeInvoice" type="button" button-style="solid">
|
||||
<Radio :label="1">个人</Radio>
|
||||
<Radio :label="2">单位</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<FormItem label="个人名称" v-if="type === 1" prop="receiptTitle">
|
||||
<i-input v-model="invoiceForm.receiptTitle"></i-input>
|
||||
</FormItem>
|
||||
<FormItem label="单位名称" v-if="type === 2" prop="receiptTitle">
|
||||
<i-input v-model="invoiceForm.receiptTitle"></i-input>
|
||||
</FormItem>
|
||||
<FormItem label="纳税人识别号" v-if="type === 2" prop="taxpayerId">
|
||||
<i-input v-model="invoiceForm.taxpayerId"></i-input>
|
||||
</FormItem>
|
||||
<FormItem label="发票内容">
|
||||
<RadioGroup v-model="invoiceForm.receiptContent" type="button" button-style="solid">
|
||||
<Radio label="商品明细">商品明细</Radio>
|
||||
<Radio label="商品类别">商品类别</Radio>
|
||||
<RadioGroup v-model="invoice" type="button" button-style="solid" @on-change="onInvoiceKindChange">
|
||||
<Radio :label="1">电子普通发票</Radio>
|
||||
<Radio :label="2">增值税专用发票</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
|
||||
<!-- 电子普通发票 -->
|
||||
<div v-if="invoice === 1" key="invoice-normal">
|
||||
<FormItem label="发票抬头">
|
||||
<RadioGroup v-model="type" type="button" button-style="solid" @on-change="onHeaderTypeChange">
|
||||
<Radio :label="1">个人</Radio>
|
||||
<Radio :label="2">单位</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<FormItem :label="type === 1 ? '个人名称' : '单位名称'" :prop="type === 1 ? 'personalName' : 'companyName'">
|
||||
<i-input v-if="type === 1" v-model="invoiceForm.personalName"></i-input>
|
||||
<i-input v-else v-model="invoiceForm.companyName"></i-input>
|
||||
</FormItem>
|
||||
|
||||
<FormItem label="纳税人识别号" v-if="type === 2" prop="taxpayerId">
|
||||
<i-input v-model="invoiceForm.taxpayerId"></i-input>
|
||||
</FormItem>
|
||||
<FormItem label="发票内容">
|
||||
<RadioGroup v-model="invoiceForm.receiptContent" type="button" button-style="solid">
|
||||
<Radio label="商品明细">商品明细</Radio>
|
||||
<Radio label="商品类别">商品类别</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<FormItem label="收票人手机" prop="receiptPhone">
|
||||
<i-input v-model="invoiceForm.receiptPhone"></i-input>
|
||||
</FormItem>
|
||||
<FormItem label="收票人邮箱" prop="receiptEmail">
|
||||
<i-input v-model="invoiceForm.receiptEmail" placeholder="可选"></i-input>
|
||||
</FormItem>
|
||||
</div>
|
||||
|
||||
<!-- 增值税专用发票(固定为单位) -->
|
||||
<div v-else key="invoice-vat">
|
||||
<FormItem label="发票抬头">
|
||||
<span class="inv-title-fixed">单位</span>
|
||||
</FormItem>
|
||||
<FormItem label="单位名称" prop="companyName">
|
||||
<i-input v-model="invoiceForm.companyName" placeholder="与营业执照一致"></i-input>
|
||||
</FormItem>
|
||||
<FormItem label="纳税人识别号" prop="taxpayerId">
|
||||
<i-input v-model="invoiceForm.taxpayerId"></i-input>
|
||||
</FormItem>
|
||||
<FormItem label="单位地址" prop="companyAddress">
|
||||
<i-input v-model="invoiceForm.companyAddress" placeholder="注册地址"></i-input>
|
||||
</FormItem>
|
||||
<FormItem label="单位电话" prop="companyPhone">
|
||||
<i-input v-model="invoiceForm.companyPhone" placeholder="固话或手机"></i-input>
|
||||
</FormItem>
|
||||
<FormItem label="开户银行" prop="bankName">
|
||||
<i-input v-model="invoiceForm.bankName"></i-input>
|
||||
</FormItem>
|
||||
<FormItem label="银行账号" prop="bankAccount">
|
||||
<i-input v-model="invoiceForm.bankAccount"></i-input>
|
||||
</FormItem>
|
||||
<FormItem label="发票内容">
|
||||
<RadioGroup v-model="invoiceForm.receiptContent" type="button" button-style="solid">
|
||||
<Radio label="商品明细">商品明细</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<FormItem label="收票人手机" prop="receiptPhone">
|
||||
<i-input v-model="invoiceForm.receiptPhone"></i-input>
|
||||
</FormItem>
|
||||
<FormItem label="收票人邮箱" prop="receiptEmail">
|
||||
<i-input v-model="invoiceForm.receiptEmail" placeholder="可选"></i-input>
|
||||
</FormItem>
|
||||
</div>
|
||||
</Form>
|
||||
<div style="text-align: center">
|
||||
<Button type="primary" :loading="loading" @click="submit">保存发票信息</Button>
|
||||
@@ -45,106 +89,209 @@
|
||||
</template>
|
||||
<script>
|
||||
import { receiptSelect } from '@/api/cart.js';
|
||||
import { TINumber } from '@/plugins/RegExp.js';
|
||||
import { mobile, email } from '@/plugins/RegExp.js';
|
||||
|
||||
export default {
|
||||
name: 'invoiceModal',
|
||||
data () {
|
||||
return {
|
||||
invoice: 1, // 发票类型
|
||||
invoiceAvailable: false, // 模态框显隐
|
||||
loading: false, // 提交状态
|
||||
invoice: 1, // 1 电子普通发票 2 增值税专用发票
|
||||
invoiceAvailable: false,
|
||||
loading: false,
|
||||
invoiceForm: {
|
||||
// 普票表单
|
||||
receiptTitle: '', // 发票抬头
|
||||
taxpayerId: '', // 纳税人识别号
|
||||
receiptContent: '商品明细' // 发票内容
|
||||
receiptTitle: '',
|
||||
personalName: '',
|
||||
companyName: '',
|
||||
taxpayerId: '',
|
||||
receiptContent: '商品明细',
|
||||
receiptPhone: '',
|
||||
receiptEmail: '',
|
||||
companyAddress: '',
|
||||
companyPhone: '',
|
||||
bankName: '',
|
||||
bankAccount: ''
|
||||
},
|
||||
type: 1, // 1 个人 2 单位
|
||||
ruleInline: {
|
||||
taxpayerId: [
|
||||
{ required: true, message: '请填写纳税人识别号' },
|
||||
{ pattern: TINumber, message: '请填写正确的纳税人识别号' }
|
||||
]
|
||||
}
|
||||
type: 1
|
||||
};
|
||||
},
|
||||
props: ['invoiceData'],
|
||||
computed: {
|
||||
formRules () {
|
||||
const receiptPhoneRules = [
|
||||
{ required: true, message: '请填写收票人手机', trigger: 'blur' },
|
||||
{ pattern: mobile, message: '请填写正确的手机号码', trigger: 'blur' }
|
||||
];
|
||||
// 收票人邮箱可选:仅校验格式;提示文案须与手机区分,避免误用「请填写收票人手机」
|
||||
const receiptEmailRules = [
|
||||
{
|
||||
validator (rule, val, cb) {
|
||||
const s = val != null ? String(val).trim() : '';
|
||||
if (!s) {
|
||||
cb();
|
||||
return;
|
||||
}
|
||||
if (!email.test(s)) {
|
||||
cb(new Error('请填写正确的收票人邮箱'));
|
||||
return;
|
||||
}
|
||||
cb();
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
];
|
||||
|
||||
if (this.invoice === 2) {
|
||||
return {
|
||||
companyName: [{ required: true, message: '请填写单位名称', trigger: 'blur' }],
|
||||
taxpayerId: [{ required: true, message: '请填写纳税人识别号', trigger: 'blur' }],
|
||||
companyAddress: [{ required: true, message: '请填写单位地址', trigger: 'blur' }],
|
||||
companyPhone: [{ required: true, message: '请填写单位电话', trigger: 'blur' }],
|
||||
bankName: [{ required: true, message: '请填写开户银行', trigger: 'blur' }],
|
||||
bankAccount: [{ required: true, message: '请填写银行账号', trigger: 'blur' }],
|
||||
receiptPhone: receiptPhoneRules,
|
||||
receiptEmail: receiptEmailRules
|
||||
};
|
||||
}
|
||||
|
||||
const rules = {
|
||||
receiptPhone: receiptPhoneRules,
|
||||
receiptEmail: receiptEmailRules
|
||||
};
|
||||
if (this.type === 1) {
|
||||
rules.personalName = [{ required: true, message: '请填写个人名称', trigger: 'blur' }];
|
||||
} else {
|
||||
rules.companyName = [{ required: true, message: '请填写单位名称', trigger: 'blur' }];
|
||||
rules.taxpayerId = [{ required: true, message: '请填写纳税人识别号', trigger: 'blur' }];
|
||||
}
|
||||
return rules;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// 回显的发票信息
|
||||
invoiceData: {
|
||||
handler (val) {
|
||||
this.invoiceForm = { ...val };
|
||||
if (!val) return;
|
||||
this.invoiceForm = { ...this.invoiceForm, ...val };
|
||||
if (!this.invoiceForm.receiptPhone) this.invoiceForm.receiptPhone = '';
|
||||
if (!this.invoiceForm.receiptEmail) this.invoiceForm.receiptEmail = '';
|
||||
if (!this.invoiceForm.receiptContent) this.invoiceForm.receiptContent = '商品明细';
|
||||
if (!this.invoiceForm.companyAddress) this.invoiceForm.companyAddress = '';
|
||||
if (!this.invoiceForm.companyPhone) this.invoiceForm.companyPhone = '';
|
||||
if (!this.invoiceForm.bankName) this.invoiceForm.bankName = '';
|
||||
if (!this.invoiceForm.bankAccount) this.invoiceForm.bankAccount = '';
|
||||
if (!this.invoiceForm.personalName) this.invoiceForm.personalName = '';
|
||||
if (!this.invoiceForm.companyName) this.invoiceForm.companyName = '';
|
||||
|
||||
if (val.taxpayerId) {
|
||||
const rt = val.receiptType;
|
||||
if (rt === 2 || rt === '2' || val.invoiceKind === 'VAT_SPECIAL') {
|
||||
this.invoice = 2;
|
||||
this.type = 2;
|
||||
} else {
|
||||
this.type = 1;
|
||||
this.invoice = 1;
|
||||
if (val.taxpayerId) this.type = 2;
|
||||
else this.type = 1;
|
||||
}
|
||||
// 兼容后端 receiptTitle 存「个人/单位」,实际名称在 personalName/companyName;旧数据名称可能只在 receiptTitle
|
||||
const titleAsName = (t) => (t && t !== '个人' && t !== '单位' ? t : '');
|
||||
if (this.invoice === 2) {
|
||||
this.invoiceForm.companyName = val.companyName || titleAsName(val.receiptTitle) || '';
|
||||
} else if (this.type === 2) {
|
||||
this.invoiceForm.companyName = val.companyName || titleAsName(val.receiptTitle) || '';
|
||||
this.invoiceForm.personalName = val.personalName || '';
|
||||
} else {
|
||||
this.invoiceForm.personalName = val.personalName || titleAsName(val.receiptTitle) || '';
|
||||
this.invoiceForm.companyName = val.companyName || '';
|
||||
}
|
||||
if (this.invoice === 1) {
|
||||
this.invoiceForm.companyAddress = '';
|
||||
this.invoiceForm.companyPhone = '';
|
||||
this.invoiceForm.bankName = '';
|
||||
this.invoiceForm.bankAccount = '';
|
||||
}
|
||||
if (this.invoice === 2) {
|
||||
this.invoiceForm.personalName = '';
|
||||
}
|
||||
},
|
||||
deep: true,
|
||||
immeadite: true
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 选择发票抬头
|
||||
*/
|
||||
changeInvoice (val) {
|
||||
onHeaderTypeChange (val) {
|
||||
if (this.invoice === 1 && val === 1 && this.invoiceForm.personalName === '个人') {
|
||||
this.invoiceForm.personalName = '';
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this.type = val;
|
||||
if (this.$refs.form) this.$refs.form.clearValidate();
|
||||
});
|
||||
},
|
||||
onInvoiceKindChange (val) {
|
||||
this.type = val === 2 ? 2 : 1;
|
||||
this.invoiceForm = {
|
||||
receiptTitle: '',
|
||||
personalName: '',
|
||||
companyName: '',
|
||||
taxpayerId: '',
|
||||
receiptContent: '商品明细',
|
||||
receiptPhone: '',
|
||||
receiptEmail: '',
|
||||
companyAddress: '',
|
||||
companyPhone: '',
|
||||
bankName: '',
|
||||
bankAccount: ''
|
||||
};
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.form) this.$refs.form.clearValidate();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 保存判断
|
||||
*/
|
||||
save () {
|
||||
let flage = true;
|
||||
|
||||
// 保存分为两种类型,个人以及企业
|
||||
const { receiptTitle } = JSON.parse(
|
||||
JSON.stringify(this.invoiceForm)
|
||||
);
|
||||
// 判断是否填写发票抬头
|
||||
if (!receiptTitle) {
|
||||
this.$Message.error('请填写发票抬头!');
|
||||
flage = false;
|
||||
return false;
|
||||
async save () {
|
||||
if (this.invoice === 2) {
|
||||
this.invoiceForm.receiptContent = '商品明细';
|
||||
}
|
||||
|
||||
if (this.type === 2) {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (!valid) {
|
||||
flage = false;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
delete this.invoiceForm.taxpayerId;
|
||||
}
|
||||
|
||||
return flage;
|
||||
return await new Promise(resolve => {
|
||||
this.$refs.form.validate(valid => resolve(valid));
|
||||
});
|
||||
},
|
||||
// 保存发票信息
|
||||
async submit () {
|
||||
if (this.save()) {
|
||||
this.loading = true;
|
||||
let submit = {
|
||||
way: this.$route.query.way,
|
||||
...this.invoiceForm
|
||||
};
|
||||
let receipt = await receiptSelect(submit);
|
||||
if (receipt.success) {
|
||||
this.$emit('change', true);
|
||||
}
|
||||
|
||||
this.loading = false;
|
||||
async submit () {
|
||||
if (!await this.save()) return;
|
||||
this.loading = true;
|
||||
const raw = JSON.parse(JSON.stringify(this.invoiceForm));
|
||||
if (this.invoice === 1) {
|
||||
delete raw.companyAddress;
|
||||
delete raw.companyPhone;
|
||||
delete raw.bankName;
|
||||
delete raw.bankAccount;
|
||||
delete raw.invoiceAddress;
|
||||
if (this.type === 1) {
|
||||
delete raw.taxpayerId;
|
||||
}
|
||||
} else {
|
||||
delete raw.personalName;
|
||||
}
|
||||
const isCompanyTitle = this.invoice === 2 || this.type === 2;
|
||||
const titleName = isCompanyTitle
|
||||
? (raw.companyName != null ? String(raw.companyName).trim() : '')
|
||||
: (raw.personalName != null ? String(raw.personalName).trim() : '');
|
||||
const submit = {
|
||||
way: this.$route.query.way,
|
||||
...raw,
|
||||
receiptType: this.invoice,
|
||||
receiptTitle: isCompanyTitle ? '单位' : '个人',
|
||||
personalName: isCompanyTitle ? '' : titleName,
|
||||
companyName: isCompanyTitle ? titleName : ''
|
||||
};
|
||||
let receipt = await receiptSelect(submit);
|
||||
if (receipt.success) {
|
||||
this.$emit('change', true);
|
||||
}
|
||||
this.loading = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
/** 普票 */
|
||||
.inv-type {
|
||||
text-align: center;
|
||||
}
|
||||
@@ -158,7 +305,12 @@ export default {
|
||||
}
|
||||
|
||||
.nav-content {
|
||||
width: 500px;
|
||||
width: 520px;
|
||||
margin: 10px auto;
|
||||
}
|
||||
|
||||
.inv-title-fixed {
|
||||
line-height: 32px;
|
||||
color: #515a6e;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user