Files
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

111 lines
3.8 KiB
Vue
Raw Permalink 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">
<div>
<h1 class="text-2xl font-bold text-gray-900">标书中心</h1>
<p class="text-sm text-gray-500">汇聚各类采购项目选择您需要的标书进行购买</p>
</div>
<HjcUserBar />
</div>
<!-- 搜索 + 分类 -->
<div class="mb-6 flex flex-col sm:flex-row gap-3">
<input
v-model="keywords"
class="flex-1 rounded-md border border-gray-300 px-4 py-2 text-sm"
placeholder="搜索项目名称 / 采购编号"
@keyup.enter="load()"
/>
<select v-model="category" class="rounded-md border border-gray-300 px-4 py-2 text-sm">
<option value="">全部项目</option>
<option value="服务类">服务类</option>
<option value="工程类">工程类</option>
<option value="货物类">货物类</option>
</select>
<button
class="rounded-md bg-blue-600 px-5 py-2 text-sm text-white hover:bg-blue-700"
@click="load()"
>
搜索
</button>
</div>
<!-- 列表 -->
<div v-if="items.length" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
<NuxtLink
v-for="item in items"
:key="item.id"
:to="`/tender/${item.id}`"
class="group rounded-lg border border-gray-200 p-5 hover:shadow-md transition"
>
<div class="text-xs text-gray-400 mb-1">项目编号{{ item.projectNo }}</div>
<h2 class="text-base font-semibold text-gray-900 group-hover:text-blue-600 line-clamp-2">
{{ item.projectName }}
</h2>
<div class="mt-3 flex items-center gap-2 text-xs text-gray-500">
<span class="rounded bg-gray-100 px-2 py-0.5">{{ item.category || '未分类' }}</span>
<span>截止{{ item.deadlineTime?.slice(0, 19)?.replace('T', ' ') || '-' }}</span>
</div>
<div class="mt-4 flex items-end justify-between">
<div class="text-blue-600">
<span class="text-xl font-bold">¥{{ formatMoney(item.tenderPrice) }}</span>
<span class="text-xs text-gray-400 ml-1">信息服务费</span>
</div>
<span class="text-sm text-blue-600 group-hover:underline">查看详情</span>
</div>
</NuxtLink>
</div>
<div v-else-if="loaded" class="py-16 text-center text-gray-500">暂无标书项目</div>
<SiteLoading v-show="!loaded" />
<!-- 加载更多 -->
<div v-if="items.length < count" class="mt-8 text-center">
<button class="rounded-md border border-gray-300 px-6 py-2 text-sm" @click="loadMore()">
加载更多
</button>
</div>
</div>
</template>
<script setup lang="ts">
import type { Tender } from '~/types/tender'
const keywords = ref('')
const category = ref('')
const page = ref(1)
const limit = 12
const loaded = ref(false)
const listState = shallowRef<Tender[]>([])
const items = computed(() => listState.value)
const count = computed(() => (listState as any).__count || 0)
async function load() {
page.value = 1
const res: any = await $fetch('/api/tender/list', {
query: { page: page.value, limit, keywords: keywords.value || undefined, category: category.value || undefined }
})
listState.value = res?.list || []
;(listState as any).__count = res?.count || 0
loaded.value = true
}
async function loadMore() {
page.value += 1
const res: any = await $fetch('/api/tender/list', {
query: { page: page.value, limit, keywords: keywords.value || undefined, category: category.value || undefined }
})
const next = res?.list || []
listState.value = [...listState.value, ...next]
;(listState as any).__count = res?.count || 0
}
function formatMoney(n?: number | string) {
if (n === undefined || n === null) return '0.00'
return Number(n).toFixed(2)
}
await load()
</script>