|
@@ -19,19 +19,35 @@
|
|
|
</v-card>
|
|
|
|
|
|
<CtDialog :visible="show" :widthType="3" titleClass="text-h6" :title="editId ? '编辑发票抬头' : '新增发票抬头'" @close="handleClose" @submit="handleSubmit">
|
|
|
- <CtForm ref="CtFormRef" :items="formItems"></CtForm>
|
|
|
+ <CtForm ref="CtFormRef" :items="formItems">
|
|
|
+ <template #certificationTip>
|
|
|
+ <div style="color:var(--color-999); font-size: 13px;margin-left: 108px;" class="mb-5">
|
|
|
+ <v-icon color="primary" size="20" class="mr-1">mdi-check-circle-outline</v-icon>
|
|
|
+ <span>企业实名认证账号,可开具普票和企业专票</span>
|
|
|
+ <span>
|
|
|
+ <span>查看</span>
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template #invoiceHeaderTip v-if="invoiceHeaderTip">
|
|
|
+ <div style="color:var(--color-999); font-size: 13px;" class="d-flex mr-10">
|
|
|
+ <v-icon color="primary" class="mr-1 mt-1">mdi-shield-check</v-icon>
|
|
|
+ <div>相关法律规定,专票抬头与实名认证主体必须一致, 若需开具其他主体专票,请变更企业实名认证</div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </CtForm>
|
|
|
</CtDialog>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
defineOptions({ name: 'invoiceHeader'})
|
|
|
-import { ref } from 'vue'
|
|
|
+import { nextTick, ref } from 'vue'
|
|
|
import { getEnterpriseBusiness } from '@/api/enterprise'
|
|
|
import { getInvoiceTitlePage, createInvoiceTitle, updateInvoiceTitle, deleteInvoiceTitle } from '@/api/recruit/enterprise/member/invoice'
|
|
|
import Snackbar from '@/plugins/snackbar'
|
|
|
import Confirm from '@/plugins/confirm'
|
|
|
import { useI18n } from '@/hooks/web/useI18n'
|
|
|
-import { checkPhone, checkEmail, checkUSCI } from '@/utils/validate'
|
|
|
+import { checkPhone, checkUSCI } from '@/utils/validate'
|
|
|
|
|
|
const { t } = useI18n()
|
|
|
const total = ref(0)
|
|
@@ -40,11 +56,11 @@ const headers = [
|
|
|
{ title: '抬头类型', key: 'category', sortable: false, value: item => item.category === 0 ? '个人' : '企业' },
|
|
|
{ title: '发票类型', key: 'type', sortable: false, value: item => item.type === 0 ? '增值税普通发票' : '增值税专用发票' },
|
|
|
{ title: '发票抬头', key: 'title', sortable: false },
|
|
|
- { title: '税号', key: 'code', sortable: false },
|
|
|
- { title: '联系邮箱', key: 'email', sortable: false },
|
|
|
- { title: '联系电话', key: 'phone', sortable: false },
|
|
|
- { title: '开户银行', key: 'enterpriseBankTitle', sortable: false },
|
|
|
- { title: '银行账号', key: 'enterpriseBankNo', sortable: false },
|
|
|
+ { title: '纳税人识别号', key: 'code', sortable: false },
|
|
|
+ { title: '基本开户银行', key: 'enterpriseBankTitle', sortable: false },
|
|
|
+ { title: '基本银行账号', key: 'enterpriseBankNo', sortable: false },
|
|
|
+ { title: '企业注册地址', key: 'enterpriseAddress', sortable: false },
|
|
|
+ { title: '企业注册电话', key: 'enterprisePhone', sortable: false },
|
|
|
{ title: '操作', key: 'actions', sortable: false }
|
|
|
]
|
|
|
|
|
@@ -56,123 +72,140 @@ const CtFormRef = ref()
|
|
|
const show = ref(false)
|
|
|
const editId = ref(null)
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+const personKeys = ['category', 'type', 'title']
|
|
|
+const enterpriseKeys = ['category', 'type', 'certificationTip', 'invoiceHeaderTip', 'title', 'code', 'enterpriseBankTitle', 'enterpriseBankNo', 'enterpriseAddress', 'enterprisePhone']
|
|
|
// 抬头类型
|
|
|
-const keys = ['enterpriseBankTitle', 'enterpriseBankNo']
|
|
|
-const handleChangeCategory = (e) => {
|
|
|
- const type = formItems.value.options.find(item => item.key === 'type').value
|
|
|
- const code = formItems.value.options.find(item => item.key === 'code')
|
|
|
- code.hide = e ? false : true
|
|
|
- if (e) setEntBusinessInfo()
|
|
|
- else setEntPersonBaseInfo()
|
|
|
- const title = formItems.value.options.find(item => item.key === 'title')
|
|
|
- if (title) title.disabled = e ? true : false
|
|
|
- keys.forEach(k => {
|
|
|
- const result = formItems.value.options.find(item => item.key === k)
|
|
|
- result.label = (e && type) || (!e && type) ? `${result.defaultLabel} *` : result.defaultLabel
|
|
|
- result.rules = (e && type) || (!e && type) ? [v => !!v || `请输入${result.defaultLabel}`] : []
|
|
|
+const handleChangeCategory = (categoryType) => { // 0: 个人, 1: 企业
|
|
|
+ formItems.value.options = []
|
|
|
+ const keyArr = categoryType ? enterpriseKeys : personKeys
|
|
|
+ const arr = keyArr.map(key => {
|
|
|
+ const optionsItem = { ...optionsBase[key] }
|
|
|
+ if (categoryType === 0) { // 个人
|
|
|
+ invoiceHeaderTip.value = false
|
|
|
+ if (optionsItem.key === 'type') optionsItem.items = [optionsItem.items[0]]
|
|
|
+ if (optionsItem.key === 'title') {
|
|
|
+ optionsItem.value = '个人'
|
|
|
+ optionsItem.disabled = true
|
|
|
+ }
|
|
|
+ } else { // 企业
|
|
|
+ if (optionsItem.key === 'category') optionsItem.value = 1
|
|
|
+ if (business.value[key]) optionsItem.value = business.value[key]
|
|
|
+ }
|
|
|
+ return optionsItem
|
|
|
+ })
|
|
|
+ nextTick(() => {
|
|
|
+ formItems.value.options = arr
|
|
|
})
|
|
|
}
|
|
|
|
|
|
-const handleChangeType = (e) => {
|
|
|
- keys.forEach(k => {
|
|
|
- const result = formItems.value.options.find(item => item.key === k)
|
|
|
- result.label = e ? `${result.defaultLabel} *` : result.defaultLabel
|
|
|
- result.rules = e ? [v => !!v || `请输入${result.defaultLabel}`] : []
|
|
|
+const invoiceHeaderTip = ref(false)
|
|
|
+const handleChangeType = (isVerified) => {
|
|
|
+ invoiceHeaderTip.value = isVerified
|
|
|
+ formItems.value.options.forEach(e => {
|
|
|
+ if (business.value[e.key]) e.value = business.value[e.key] // business.value
|
|
|
+ if (e.key === 'title') e.disabled = isVerified
|
|
|
+ if (e.rulesBaseLabel) {
|
|
|
+ e.label = isVerified ? `${e.rulesBaseLabel} *` : e.rulesBaseLabel
|
|
|
+ e.rules = isVerified ? [v => !!v || `请输入${e.rulesBaseLabel}`] : []
|
|
|
+ if (e.key === 'title') {
|
|
|
+ e.rules = [...e.rules, v => {if (v && checkPhone(v)) return true; return '企业注册电话'}]
|
|
|
+ }
|
|
|
+ }
|
|
|
})
|
|
|
}
|
|
|
|
|
|
-const formItems = ref({
|
|
|
- options: [
|
|
|
- {
|
|
|
- type: 'ifRadio',
|
|
|
- key: 'category',
|
|
|
- value: 0,
|
|
|
- label: '抬头类型 *',
|
|
|
- width: 90,
|
|
|
- items: [
|
|
|
- { label: '个人', value: 0 },
|
|
|
- { label: '企业', value: 1 }
|
|
|
- ],
|
|
|
- change: handleChangeCategory
|
|
|
- },
|
|
|
- {
|
|
|
- type: 'ifRadio',
|
|
|
- key: 'type',
|
|
|
- value: 0,
|
|
|
- label: '发票类型 *',
|
|
|
- width: 90,
|
|
|
- items: [
|
|
|
- { label: '增值税普通发票', value: 0 },
|
|
|
- { label: '增值税专用发票', value: 1 }
|
|
|
- ],
|
|
|
- change: handleChangeType
|
|
|
- },
|
|
|
- {
|
|
|
- type: 'text',
|
|
|
- key: 'title',
|
|
|
- value: '',
|
|
|
- label: '发票抬头 *',
|
|
|
- rules: [v => !!v || '请输入发票抬头'],
|
|
|
- },
|
|
|
- {
|
|
|
- type: 'text',
|
|
|
- key: 'code',
|
|
|
- value: '',
|
|
|
- label: '税号 *',
|
|
|
- hide: true,
|
|
|
- outlined: true,
|
|
|
- rules: [
|
|
|
- value => {
|
|
|
- if (value) return true
|
|
|
- return '请填写税号'
|
|
|
- },
|
|
|
- value => {
|
|
|
- if (checkUSCI(value)) return true
|
|
|
- return '请填写正确的税号'
|
|
|
- }
|
|
|
- ]
|
|
|
- },
|
|
|
- {
|
|
|
- type: 'phoneNumber',
|
|
|
- key: 'phone',
|
|
|
- value: null,
|
|
|
- label: '联系电话',
|
|
|
- outlined: true
|
|
|
- },
|
|
|
- {
|
|
|
- type: 'text',
|
|
|
- key: 'email',
|
|
|
- value: '',
|
|
|
- label: '联系邮箱 *',
|
|
|
- rules: [
|
|
|
- value => {
|
|
|
- if (value) return true
|
|
|
- return '请输入联系邮箱'
|
|
|
- },
|
|
|
- value => {
|
|
|
- if (checkEmail(value)) return true
|
|
|
- return '请输入正确的电子邮箱'
|
|
|
- }
|
|
|
- ]
|
|
|
- },
|
|
|
- {
|
|
|
- type: 'text',
|
|
|
- key: 'enterpriseBankTitle',
|
|
|
- value: null,
|
|
|
- label: '开户银行',
|
|
|
- defaultLabel: '开户银行',
|
|
|
- outlined: true
|
|
|
- },
|
|
|
- {
|
|
|
- type: 'number',
|
|
|
- key: 'enterpriseBankNo',
|
|
|
- value: null,
|
|
|
- label: '银行账号',
|
|
|
- defaultLabel: '银行账号',
|
|
|
- outlined: true
|
|
|
- }
|
|
|
- ]
|
|
|
-})
|
|
|
+const optionsBase = {
|
|
|
+ category: {
|
|
|
+ type: 'ifRadio',
|
|
|
+ key: 'category',
|
|
|
+ value: 0,
|
|
|
+ label: '抬头类型 *',
|
|
|
+ width: 90,
|
|
|
+ items: [
|
|
|
+ { label: '个人', value: 0 },
|
|
|
+ { label: '企业', value: 1 }
|
|
|
+ ],
|
|
|
+ change: handleChangeCategory
|
|
|
+ },
|
|
|
+ type: {
|
|
|
+ type: 'ifRadio',
|
|
|
+ key: 'type',
|
|
|
+ value: 0,
|
|
|
+ label: '发票类型 *',
|
|
|
+ width: 90,
|
|
|
+ hideDetails: true,
|
|
|
+ items: [
|
|
|
+ { label: '增值税普通发票', value: 0 },
|
|
|
+ { label: '增值税专用发票', value: 1 }
|
|
|
+ ],
|
|
|
+ change: handleChangeType
|
|
|
+ },
|
|
|
+ title: {
|
|
|
+ type: 'text',
|
|
|
+ key: 'title',
|
|
|
+ value: '',
|
|
|
+ label: '发票抬头 *',
|
|
|
+ rules: [v => !!v || '请输入发票抬头'],
|
|
|
+ },
|
|
|
+ code: {
|
|
|
+ type: 'text',
|
|
|
+ key: 'code',
|
|
|
+ value: '',
|
|
|
+ label: '纳税人识别号 *',
|
|
|
+ outlined: true,
|
|
|
+ rules: [
|
|
|
+ value => {
|
|
|
+ if (value && checkUSCI(value)) return true
|
|
|
+ return '纳税人识别号'
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ enterpriseBankTitle: {
|
|
|
+ type: 'text',
|
|
|
+ key: 'enterpriseBankTitle',
|
|
|
+ value: null,
|
|
|
+ label: '基本开户银行',
|
|
|
+ placeholder: '请填写开户许可证上的开户银行',
|
|
|
+ rulesBaseLabel: '基本开户银行',
|
|
|
+ outlined: true
|
|
|
+ },
|
|
|
+ enterpriseBankNo: {
|
|
|
+ type: 'number',
|
|
|
+ key: 'enterpriseBankNo',
|
|
|
+ value: null,
|
|
|
+ label: '基本银行账号',
|
|
|
+ placeholder: '请填写开户许可证上的银行账号',
|
|
|
+ rulesBaseLabel: '基本银行账号',
|
|
|
+ outlined: true
|
|
|
+ },
|
|
|
+ enterpriseAddress: {
|
|
|
+ type: 'text',
|
|
|
+ key: 'enterpriseAddress',
|
|
|
+ value: null,
|
|
|
+ label: '企业注册地址',
|
|
|
+ placeholder: '请填写开户许可证上的企业注册地址',
|
|
|
+ rulesBaseLabel: '企业注册地址',
|
|
|
+ outlined: true
|
|
|
+ },
|
|
|
+ enterprisePhone: {
|
|
|
+ type: 'phoneNumber',
|
|
|
+ key: 'enterprisePhone',
|
|
|
+ value: null,
|
|
|
+ label: '企业注册电话',
|
|
|
+ placeholder: '请填写开户许可证上的企业注册电话',
|
|
|
+ rulesBaseLabel: '企业注册电话',
|
|
|
+ outlined: true
|
|
|
+ },
|
|
|
+ certificationTip: {
|
|
|
+ slotName: 'certificationTip',
|
|
|
+ },
|
|
|
+ invoiceHeaderTip: {
|
|
|
+ slotName: 'invoiceHeaderTip',
|
|
|
+ },
|
|
|
+}
|
|
|
+const formItems = ref({ options: [] })
|
|
|
|
|
|
// 获取列表
|
|
|
const getList =async () => {
|
|
@@ -187,60 +220,27 @@ const handleChangePage = (e) => {
|
|
|
getList()
|
|
|
}
|
|
|
|
|
|
-// // // 根据企业名称模糊搜索企业营业执照信息-填充发票抬头
|
|
|
-// const getEntBusinessInfoByName = async (name) => {
|
|
|
-// if (!name) return
|
|
|
-// const data = await getEnterpriseBusinessByName({ name })
|
|
|
-// if (!data?.length || !Object.keys(data[0]).length) return
|
|
|
-// const info = {
|
|
|
-// ...data[0],
|
|
|
-// title: data[0].name,
|
|
|
-// }
|
|
|
-// formItems.value.options.forEach(e => e.value = info[e.key])
|
|
|
-// }
|
|
|
-
|
|
|
-
|
|
|
// 获取企业工商信息
|
|
|
const business = ref({})
|
|
|
const getEnterpriseBusinessInfo = async () => {
|
|
|
const data = await getEnterpriseBusiness()
|
|
|
if (!data || !Object.keys(data).length) return
|
|
|
- data.category = 1
|
|
|
- data.title = data.name
|
|
|
- business.value = data
|
|
|
+ console.log(1, 'business', data)
|
|
|
+ business.value = {
|
|
|
+ title: data.name,
|
|
|
+ code: data.code,
|
|
|
+ enterpriseAddress: data.address,
|
|
|
+ }
|
|
|
}
|
|
|
getEnterpriseBusinessInfo()
|
|
|
|
|
|
-// 填充企业信息
|
|
|
-const setEntBusinessInfo = () => {
|
|
|
- const info = business.value
|
|
|
- formItems.value.options.forEach(e => {
|
|
|
- if (e.key === 'type') return
|
|
|
- if ((info[e.key] || info[e.key] === 0) && e.key !== 'type') e.value = info[e.key]
|
|
|
- else e.value = null
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-// 填充个人信息
|
|
|
-const setEntPersonBaseInfo = () => {
|
|
|
- const info = JSON.parse(localStorage.getItem('entBaseInfo')) || {}
|
|
|
- info.title = info.name
|
|
|
- info.category = 0
|
|
|
- formItems.value.options.forEach(e => {
|
|
|
- if (e.key === 'type') return
|
|
|
- if ((info[e.key] || info[e.key] === 0) && e.key !== 'type') e.value = info[e.key]
|
|
|
- else e.value = null
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
// 新增
|
|
|
const handleAdd = () => {
|
|
|
// 初始化表单
|
|
|
handleChangeCategory(0)
|
|
|
handleChangeType(0)
|
|
|
// 赋值
|
|
|
- setEntPersonBaseInfo()
|
|
|
+ // setEntPersonBaseInfo()
|
|
|
show.value = true
|
|
|
editId.value = null
|
|
|
}
|
|
@@ -284,7 +284,6 @@ const handleSubmit = async () => {
|
|
|
obj[item.key] = item.value
|
|
|
})
|
|
|
if (obj.type === undefined || obj.type === null || obj.type === '') return Snackbar.warning('请选择发票类型')
|
|
|
- if (obj.phone && !checkPhone(obj.phone)) return Snackbar.warning(t('login.correctPhoneNumber'))
|
|
|
if (editId.value) obj.id = editId.value
|
|
|
const api = editId.value ? updateInvoiceTitle : createInvoiceTitle
|
|
|
await api(obj)
|