225 lines
5.9 KiB
Vue
225 lines
5.9 KiB
Vue
<!-- 页面:需求提报(Demand) -->
|
||
<script setup lang="ts">
|
||
// 需求提报(单页三段卡片 + 底部固定操作条,数据全部走真实接口)
|
||
// 页面 → store → api;页面不直接 import api
|
||
import { onMounted } from 'vue'
|
||
import { storeToRefs } from 'pinia'
|
||
import { useDemandStore } from '@/stores/modules/demand'
|
||
import type { Demand, DemandAttachment } from '@/types/business/demand'
|
||
import DemandActionBar from './cpns/DemandActionBar.vue'
|
||
import DemandBizTypes from './cpns/DemandBizTypes.vue'
|
||
import DemandConfirmForm from './cpns/DemandConfirmForm.vue'
|
||
import DemandInfoForm from './cpns/DemandInfoForm.vue'
|
||
|
||
const demandStore = useDemandStore()
|
||
const {
|
||
form,
|
||
bizTypeOptions,
|
||
budgetOptions,
|
||
loading,
|
||
saving,
|
||
submitting,
|
||
uploading,
|
||
} = storeToRefs(demandStore)
|
||
|
||
function onBizType(value: string): void {
|
||
demandStore.patchForm({ bizType: value })
|
||
}
|
||
|
||
function onUpdate(partial: Partial<Demand>): void {
|
||
demandStore.patchForm(partial)
|
||
}
|
||
|
||
function onUpload(file: File): void {
|
||
void demandStore.addAttachment(file)
|
||
}
|
||
|
||
function onRemoveFile(file: DemandAttachment): void {
|
||
demandStore.removeAttachment(file)
|
||
}
|
||
|
||
function onSaveDraft(): void {
|
||
void demandStore.saveDraft()
|
||
}
|
||
|
||
function onReset(): void {
|
||
void demandStore.reset()
|
||
}
|
||
|
||
async function onSubmit(): Promise<void> {
|
||
await demandStore.submit()
|
||
}
|
||
|
||
onMounted(() => {
|
||
void demandStore.init()
|
||
})
|
||
</script>
|
||
|
||
<template>
|
||
<div class="demand-page" :class="{ 'is-loading': loading }">
|
||
<!-- 设计稿:导航下方 1920×179 白色通栏页头(标题 36/700 @x112,副标题 24/500 @y171) -->
|
||
<header class="demand-page__hero">
|
||
<div class="container demand-page__hero-inner">
|
||
<h1 class="demand-page__title">
|
||
需求提报
|
||
</h1>
|
||
<p class="demand-page__subtitle">
|
||
填写您的需求信息,专业顾问将快速与您联系
|
||
</p>
|
||
</div>
|
||
</header>
|
||
|
||
<!-- 设计稿:三段内容同处一张 1780×2186 白卡(矩形 148286 @(70,271)) -->
|
||
<div class="container">
|
||
<div class="demand">
|
||
<!-- ① 选择业务类型 -->
|
||
<section class="demand__section">
|
||
<h2 class="demand__heading">
|
||
<span class="demand__index">01</span>
|
||
<span class="demand__label">选择业务类型<span class="demand__required">*</span></span>
|
||
</h2>
|
||
<DemandBizTypes
|
||
:options="bizTypeOptions"
|
||
:model-value="form.bizType"
|
||
@update:model-value="onBizType"
|
||
/>
|
||
</section>
|
||
|
||
<!-- ② 填写需求信息 -->
|
||
<section class="demand__section">
|
||
<h2 class="demand__heading">
|
||
<span class="demand__index">02</span>
|
||
<span class="demand__label">填写需求信息<span class="demand__required">*</span></span>
|
||
</h2>
|
||
<DemandInfoForm
|
||
:demand="form"
|
||
:budget-options="budgetOptions"
|
||
:uploading="uploading"
|
||
@update="onUpdate"
|
||
@upload="onUpload"
|
||
@remove-file="onRemoveFile"
|
||
/>
|
||
</section>
|
||
|
||
<!-- ③ 确认信息并补充备注 -->
|
||
<section class="demand__section">
|
||
<h2 class="demand__heading">
|
||
<span class="demand__index">03</span>
|
||
<span class="demand__label">确认信息并补充备注</span>
|
||
</h2>
|
||
<DemandConfirmForm
|
||
:demand="form"
|
||
@update="onUpdate"
|
||
/>
|
||
</section>
|
||
</div>
|
||
</div>
|
||
|
||
<DemandActionBar
|
||
:saving="saving"
|
||
:submitting="submitting"
|
||
@save-draft="onSaveDraft"
|
||
@reset="onReset"
|
||
@submit="onSubmit"
|
||
/>
|
||
</div>
|
||
</template>
|
||
|
||
<style lang="less" scoped>
|
||
.demand-page {
|
||
// 固定底条 72px + 呼吸间距
|
||
padding-bottom: 104px;
|
||
|
||
&.is-loading .demand {
|
||
opacity: 0.6;
|
||
pointer-events: none;
|
||
}
|
||
|
||
// 设计稿:白色通栏页头 @(0,72) 1920×179,文案 36/700 @(112,104)、24/500 @(112,171)
|
||
&__hero {
|
||
height: 179px;
|
||
box-sizing: border-box;
|
||
padding-top: 32px;
|
||
background: @white;
|
||
}
|
||
|
||
&__hero-inner {
|
||
padding-left: 42px; // 文案 x112 = 内容区 x70 + 42
|
||
}
|
||
|
||
&__title {
|
||
margin: 0;
|
||
font-size: 36px;
|
||
font-weight: 700;
|
||
line-height: 52px;
|
||
color: @demand-ink;
|
||
}
|
||
|
||
&__subtitle {
|
||
margin: 15px 0 0;
|
||
font-size: 24px;
|
||
font-weight: 500;
|
||
line-height: 35px;
|
||
color: @demand-subtitle;
|
||
}
|
||
}
|
||
|
||
// 设计稿:白卡 @(70,271) 1780×2186;三段标题序号 x134、标题文字 x194
|
||
.demand {
|
||
margin-top: 20px; // 271 − (72+179) = 20
|
||
padding: 48px 56px 111px; // 序号顶 319 − 271 = 48
|
||
background: @white;
|
||
|
||
&__heading {
|
||
.flex(row, flex-start, center);
|
||
gap: 15px;
|
||
margin: 0 0 50px; // 01:序号块底 389 → 业务卡顶 439
|
||
padding-left: 8px; // 序号落 x134 = 卡内 x70+64 → 64-56 = 8
|
||
}
|
||
|
||
&__index {
|
||
flex-shrink: 0;
|
||
font-size: 48px; // 设计稿 48/500 #024FFF
|
||
font-weight: 500;
|
||
line-height: 70px;
|
||
font-variant-numeric: tabular-nums;
|
||
color: @demand-accent;
|
||
}
|
||
|
||
&__label {
|
||
font-size: 28px; // 设计稿 28/500 #333333
|
||
font-weight: 500;
|
||
line-height: 41px;
|
||
color: @demand-heading;
|
||
}
|
||
|
||
&__required {
|
||
margin-left: 2px;
|
||
color: @danger-color;
|
||
}
|
||
|
||
// 表单列对齐标题文字 x194 = 卡内 x70 + 124(序号行宽 55 + gap 15 + 序号内缩 8 = 78,再补 46)
|
||
&__heading + * {
|
||
margin-left: 46px;
|
||
}
|
||
|
||
// 段间距(设计稿实测):01 区底 645 → 02 序号顶 705 = 60;02 区底 1639 → 03 序号顶 1689 = 50
|
||
&__section + &__section {
|
||
margin-top: 60px;
|
||
}
|
||
|
||
&__section + &__section:last-of-type {
|
||
margin-top: 50px;
|
||
}
|
||
|
||
// ② ③ 段:标题块(70) 与首个表单标签间距更紧(序号顶 705/1689 → 标签顶 789/1779 = 84/90)
|
||
&__section + &__section &__heading {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
&__section + &__section &__heading + * {
|
||
margin-top: 14px;
|
||
}
|
||
}
|
||
</style>
|