Files
hfb_sys/frontend/src/views/public/ListingDetailView.vue
T

133 lines
3.9 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.
<script setup lang="ts">
import { ElMessage } from "element-plus";
import { onMounted, ref } from "vue";
import { useRoute, useRouter } from "vue-router";
import { fetchListing, type Listing } from "@/api/listings";
import { createOrder } from "@/api/orders";
const route = useRoute();
const router = useRouter();
const loading = ref(false);
const ordering = ref(false);
const rentHours = ref(1);
const listing = ref<Listing | null>(null);
onMounted(async () => {
loading.value = true;
try {
listing.value = await fetchListing(String(route.params.id));
} finally {
loading.value = false;
}
});
async function handleCreateOrder() {
if (!listing.value) return;
ordering.value = true;
try {
const order = await createOrder(listing.value.id, rentHours.value);
ElMessage.success("订单已创建,账号已锁定");
await router.push(`/orders/${order.id}`);
} catch (error) {
ElMessage.error(readError(error, "下单失败"));
} finally {
ordering.value = false;
}
}
function readError(error: unknown, fallback: string) {
if (typeof error === "object" && error && "response" in error) {
const response = (error as { response?: { data?: { message?: string } } })
.response;
return response?.data?.message || fallback;
}
return fallback;
}
</script>
<template>
<section class="pc-detail page" v-loading="loading">
<div class="anti-fraud-strip compact">
<span
>防骗提示下单后请按平台交接流程确认收号与归还不要私下交易</span
>
</div>
<div v-if="listing" class="pc-detail-layout">
<section class="pc-detail-main">
<div class="detail-cover">
<img
v-if="listing.screenshot_urls?.[0]"
:src="listing.screenshot_urls[0]"
:alt="listing.title"
/>
<span v-else>HFB ACCOUNT</span>
</div>
<div class="page-header detail-title">
<p class="eyebrow">
{{ listing.server_region }} / {{ listing.login_platform }}
</p>
<h1>{{ listing.title }}</h1>
<p>{{ listing.description || "号主暂未填写详细说明。" }}</p>
</div>
<div class="detail-grid">
<div class="metric-card">
<span>哈夫币</span>
<strong>{{ listing.haf_coin_amount }}</strong>
</div>
<div class="metric-card">
<span>时租</span>
<strong>¥{{ listing.price_hourly }}</strong>
</div>
<div class="metric-card">
<span>日租</span>
<strong>¥{{ listing.price_daily }}</strong>
</div>
<div class="metric-card">
<span>押金</span>
<strong>¥{{ listing.deposit_amount }}</strong>
</div>
</div>
</section>
<aside class="order-panel pc-order-card">
<h2>立即租用</h2>
<p class="order-safe-text">
平台托管订单与押金租期 {{ listing.min_rent_hours }}-{{
listing.max_rent_hours
}}
小时
</p>
<el-form label-position="top">
<el-form-item label="租用时长">
<el-input-number
v-model="rentHours"
:min="listing.min_rent_hours"
:max="listing.max_rent_hours"
class="full-control"
/>
</el-form-item>
<div class="order-total-box">
<span>预计租金</span>
<strong
>¥{{ (listing.price_hourly * rentHours).toFixed(2) }}</strong
>
<em>押金 ¥{{ listing.deposit_amount }}</em>
</div>
<el-button
type="warning"
size="large"
:loading="ordering"
class="full-control"
@click="handleCreateOrder"
>
立即下单并锁定账号
</el-button>
</el-form>
</aside>
</div>
</section>
</template>