Files
hjc-web/app/pages/tender/qualification.vue
T
weicw1996 802b73b555 feat(tender): 阶段3c 我的订单 + 企业资质中心 + 登录态导航
- /tender/orders:我的订单列表(状态/金额/下单时间)
- /tender/qualification:企业资质(信息+证件URL+提交审核+审核状态/驳回原因)
- HjcUserBar:登录/注册或 我的订单/企业资质/退出(列表/详情页已接入)
- 代理:tender/my-orders.get, enterprise.get, enterprise/save.post
2026-09-08 22:48:17 +08:00

143 lines
5.7 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">
<Field label="企业名称"><input v-model="form.name" class="field" /></Field>
<Field label="纳税人识别号"><input v-model="form.creditCode" class="field" /></Field>
<Field label="企业联系电话"><input v-model="form.contactPhone" class="field" /></Field>
<Field label="企业邮箱"><input v-model="form.contactEmail" type="email" class="field" /></Field>
<Field label="企业地址"><input v-model="form.address" class="field" /></Field>
<Field label="经办人姓名"><input v-model="form.agentName" class="field" /></Field>
<Field label="经办人邮箱"><input v-model="form.agentEmail" type="email" class="field" /></Field>
<Field label="经办人手机号"><input v-model="form.agentPhone" class="field" /></Field>
<Field label="授权到期时间"><input v-model="form.authorizeExpire" type="datetime-local" class="field" /></Field>
<div class="space-y-3">
<Field label="经办人身份证正面 URL"><input v-model="materials.idcard_front" class="field" placeholder="/upload/xxx.jpg" /></Field>
<Field label="经办人身份证反面 URL"><input v-model="materials.idcard_back" class="field" placeholder="/upload/xxx.jpg" /></Field>
<Field label="授权委托书 URL"><input v-model="materials.handbook" class="field" placeholder="/upload/xxx.pdf" /></Field>
<Field label="营业执照 URL"><input v-model="materials.license" class="field" placeholder="/upload/xxx.jpg" /></Field>
</div>
<button type="submit" class="w-full rounded-md bg-blue-600 py-3 text-white font-medium 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">
import { defineComponent, h } from 'vue'
const Field = defineComponent({
props: { label: String },
setup(props, { slots }) {
return () => h('div', { class: 'space-y-1' }, [
h('label', { class: 'block text-sm text-gray-600' }, props.label),
slots.default?.()
])
}
})
const { isLoggedIn } = useHjcAuth()
const loggedIn = ref(false)
const authStatus = ref(0)
const rejectReason = ref('')
const submitting = ref(false)
const error = ref('')
const tip = ref('')
const form = reactive({
name: '', creditCode: '', contactPhone: '', contactEmail: '', address: '',
agentName: '', agentEmail: '', agentPhone: '', authorizeExpire: ''
})
const materials = reactive({ idcard_front: '', idcard_back: '', handbook: '', license: '' })
const authStatusText = computed(() => ({ 0: '待审核', 1: '已通过', 2: '已驳回' } as any)[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'
})
async function load() {
const res: any = await $fetch('/api/tender/enterprise')
if (res) {
authStatus.value = res.authStatus ?? 0
rejectReason.value = res.rejectReason || ''
form.name = res.name || ''
form.creditCode = res.creditCode || ''
form.contactPhone = res.contactPhone || ''
form.contactEmail = res.contactEmail || ''
form.address = res.address || ''
form.agentName = res.agentName || ''
form.agentEmail = res.agentEmail || ''
form.agentPhone = res.agentPhone || ''
form.authorizeExpire = res.authorizeExpire ? res.authorizeExpire.slice(0, 16) : ''
const ms: any[] = res.materials || []
for (const m of ms) {
if (m.materialType && (materials as any)[m.materialType] === '') {
(materials as any)[m.materialType] = m.fileUrl || ''
}
}
}
}
async function submit() {
error.value = ''
tip.value = ''
submitting.value = true
const materialList = Object.entries(materials)
.filter(([, url]) => url)
.map(([type, url]) => ({ materialType: type, materialName: type, fileUrl: url }))
try {
await $fetch('/api/tender/enterprise/save', {
method: 'POST',
body: { ...form, materials: materialList }
})
tip.value = '提交成功,等待平台审核'
await load()
} catch (e: any) {
error.value = e?.data?.message || e?.message || '提交失败'
} finally {
submitting.value = false
}
}
loggedIn.value = isLoggedIn()
if (loggedIn.value) {
await load()
}
</script>
<style scoped>
.field {
width: 100%;
border-radius: 6px;
border: 1px solid #d1d5db;
padding: 8px 16px;
font-size: 14px;
}
</style>