Files
hjc-web/app/pages/tender/qualification.vue
T
weicw-dshsa 3c6582c0ec feat(web): 注册与资质表单新增基本户信息与发票类型
- HjcEnterpriseForm.vue:新增账户名称/账号/开户银行/开户支行四个输入与发票类型单选
  (VAT_SPECIAL 电子专票 / VAT_NORMAL 电子普票,无默认值),模板 + validate + buildPayload + fill 四处同步
- 账号只做长度与字符校验(^[0-9]{8,32}$),与后端 validateRegister 一致,不加真实性校验
- 必填提示点名到具体项:请填写基本户账户名称 / 开户银行 / 开户支行,未选发票类型提示「请选择发票类型」
- register.vue、tender/qualification.vue 表单初值补齐 5 个字段
- 回显兼容 bank_account_name 与 bankAccountName 两种键名
2026-10-08 12:20:13 +08:00

154 lines
5.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="container mx-auto px-4 py-10">
<div class="mb-6 flex items-center justify-between">
<h1 class="text-2xl font-bold text-gray-900">企业资质</h1>
<HjcUserBar />
</div>
<div v-if="!loggedIn" class="py-20 text-center">
<p class="text-gray-500">请先登录后管理企业资质</p>
<NuxtLink
to="/login?redirect=/tender/qualification"
class="mt-4 inline-block rounded-md bg-blue-600 px-6 py-2 text-white hover:bg-blue-700"
>
去登录
</NuxtLink>
</div>
<div v-else class="mx-auto max-w-2xl rounded-lg border border-gray-200 p-6">
<!-- 审核状态 -->
<div class="mb-6 rounded-md bg-gray-50 p-4 text-sm">
<span class="text-gray-600">审核状态:</span>
<span :class="authStatusClass" class="rounded px-2 py-0.5 font-medium">{{ authStatusText }}</span>
<p v-if="authStatus === 2 && rejectReason" class="mt-2 text-red-500">驳回原因:{{ rejectReason }}</p>
<p class="mt-1 text-xs text-gray-400">资质审核通过后方可购买标书</p>
</div>
<form class="space-y-4" @submit.prevent="submit">
<HjcEnterpriseForm ref="entForm" v-model:form="form" v-model:materials="materials" :readonly="readonly" />
<p v-if="readonly" class="text-center text-xs text-gray-500">
资质审核中 / 已通过时不可修改;被驳回后可修改并重新提交。
</p>
<button
v-if="!readonly"
type="submit"
class="w-full rounded-md bg-blue-600 py-3 font-medium text-white hover:bg-blue-700 disabled:opacity-50"
:disabled="submitting"
>
{{ submitting ? '提交中...' : '提交审核' }}
</button>
<p v-if="error" class="text-center text-sm text-red-500">{{ error }}</p>
<p v-if="tip" class="text-center text-sm text-green-600">{{ tip }}</p>
</form>
</div>
</div>
</template>
<script setup lang="ts">
const { isLoggedIn, handleAuthCode } = useHjcAuth()
const loggedIn = ref(false)
const authStatus = ref(-1)
const rejectReason = ref('')
const submitting = ref(false)
const error = ref('')
const tip = ref('')
const entForm = ref<any>(null)
const form = ref<Record<string, any>>({
name: '',
creditCode: '',
contactPhone: '',
contactEmail: '',
address: '',
bankAccountName: '',
bankAccountNo: '',
bankName: '',
bankBranch: '',
// 发票类型:单选、无默认值(未选时提交被拦截)
invoiceType: '',
agentName: '',
idCardNo: '',
agentEmail: '',
agentPhone: '',
authorizeExpire: ''
})
const materials = ref<any[]>([
{ materialType: 'idcard_front', label: '身份证人像面', materialName: '身份证人像面', fileUrl: '' },
{ materialType: 'idcard_back', label: '身份证国徽面', materialName: '身份证国徽面', fileUrl: '' },
{ materialType: 'handbook', label: '授权委托书', materialName: '授权委托书', fileUrl: '' },
{ materialType: 'license', label: '营业执照', materialName: '营业执照', fileUrl: '' }
])
const authStatusText = computed(
() => ({ 0: '待审核', 1: '已通过', 2: '已驳回' } as Record<number, string>)[authStatus.value] ?? '未提交资质'
)
const authStatusClass = computed(() => {
if (authStatus.value === 1) return 'bg-green-100 text-green-700'
if (authStatus.value === 2) return 'bg-red-100 text-red-600'
return 'bg-amber-100 text-amber-700'
})
/** 审核中(0)/已通过(1) 只读;驳回(2)/未提交(-1) 可编辑重提(与 h5 一致) */
const readonly = computed(() => authStatus.value === 0 || authStatus.value === 1)
async function load() {
// 代理原样透传 ApiResult:按 body.code 判定(HTTP 状态码恒为 200,不可用于判定)
const res: any = await $fetch('/api/tender/enterprise')
const auth = await handleAuthCode(res, '/tender/qualification')
if (auth.handled) {
// 401 已清凭据并跳登录页;403 只提示「没有访问权限」,不清 token
error.value = auth.message || ''
loggedIn.value = isLoggedIn()
return
}
if (res?.code !== 0) {
error.value = res?.message || '资质信息加载失败'
return
}
const data = res.data
if (data) {
authStatus.value = data.authStatus ?? -1
rejectReason.value = data.rejectReason || ''
entForm.value?.fill(data)
}
}
async function submit() {
error.value = ''
tip.value = ''
if (!entForm.value?.validate()) return
submitting.value = true
try {
const res: any = await $fetch('/api/tender/enterprise/save', {
method: 'POST',
body: entForm.value.buildPayload()
})
const auth = await handleAuthCode(res, '/tender/qualification')
if (auth.handled) {
error.value = auth.message || ''
return
}
if (res?.code !== 0) {
error.value = res?.message || '提交失败'
return
}
tip.value = res?.message || '提交成功,等待平台审核'
await load()
} catch (e: any) {
error.value = e?.data?.statusMessage || e?.data?.message || e?.message || '提交失败'
} finally {
submitting.value = false
}
}
loggedIn.value = isLoggedIn()
onMounted(async () => {
loggedIn.value = isLoggedIn()
if (loggedIn.value) {
await load()
}
})
</script>