511 lines
20 KiB
Vue
511 lines
20 KiB
Vue
<script setup lang="ts">
|
||
import { onMounted, ref } from 'vue'
|
||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
|
||
import { Button } from '@/components/ui/button'
|
||
import { useTabStore } from '@/pinia/tab'
|
||
import { useKvStore } from '@/pinia/kv'
|
||
import {
|
||
Calculator,
|
||
Check,
|
||
ChevronDown,
|
||
Download,
|
||
FolderKanban,
|
||
X,
|
||
Zap
|
||
} from 'lucide-vue-next'
|
||
import { industryTypeList } from '@/sql'
|
||
import { initializeProjectFactorStates } from '@/lib/projectWorkspace'
|
||
import {
|
||
SelectContent,
|
||
SelectIcon,
|
||
SelectItem,
|
||
SelectItemIndicator,
|
||
SelectItemText,
|
||
SelectPortal,
|
||
SelectRoot,
|
||
SelectTrigger,
|
||
SelectValue,
|
||
SelectViewport
|
||
} from 'reka-ui'
|
||
import {
|
||
PROJECT_TAB_ID,
|
||
QUICK_CONSULT_CATEGORY_FACTOR_KEY,
|
||
QUICK_CONTRACT_FALLBACK_NAME,
|
||
QUICK_CONTRACT_ID,
|
||
QUICK_CONTRACT_META_KEY,
|
||
QUICK_MAJOR_FACTOR_KEY,
|
||
QUICK_PROJECT_INFO_KEY,
|
||
writeWorkspaceMode
|
||
} from '@/lib/workspace'
|
||
|
||
interface QuickProjectInfoState {
|
||
projectIndustry?: string
|
||
projectName?: string
|
||
preparedBy?: string
|
||
reviewedBy?: string
|
||
preparedCompany?: string
|
||
preparedDate?: string
|
||
}
|
||
|
||
interface QuickContractMetaState {
|
||
id?: string
|
||
name?: string
|
||
updatedAt?: string
|
||
}
|
||
|
||
interface ProjectInfoState {
|
||
projectIndustry?: string
|
||
projectName?: string
|
||
preparedBy?: string
|
||
reviewedBy?: string
|
||
preparedCompany?: string
|
||
preparedDate?: string
|
||
}
|
||
|
||
const PROJECT_INFO_KEY = 'xm-base-info-v1'
|
||
const PROJECT_CONSULT_CATEGORY_FACTOR_KEY = 'xm-consult-category-factor-v1'
|
||
const PROJECT_MAJOR_FACTOR_KEY = 'xm-major-factor-v1'
|
||
const DEFAULT_PROJECT_NAME = 'xxx 造价咨询服务'
|
||
const PROJECT_INIT_CHANGED_EVENT = 'xm-project-init-changed'
|
||
|
||
const tabStore = useTabStore()
|
||
const kvStore = useKvStore()
|
||
const projectDialogOpen = ref(false)
|
||
const projectIndustry = ref(String(industryTypeList[0]?.id || ''))
|
||
const projectSubmitting = ref(false)
|
||
const quickDialogOpen = ref(false)
|
||
const quickIndustry = ref(String(industryTypeList[0]?.id || ''))
|
||
const quickContractName = ref(QUICK_CONTRACT_FALLBACK_NAME)
|
||
const quickSubmitting = ref(false)
|
||
const homeImportInputRef = ref<HTMLInputElement | null>(null)
|
||
const projectIconAvailable = ref(false)
|
||
const quickIconAvailable = ref(false)
|
||
const importIconAvailable = ref(false)
|
||
|
||
const getTodayDateString = () => {
|
||
const now = new Date()
|
||
const year = String(now.getFullYear())
|
||
const month = String(now.getMonth() + 1).padStart(2, '0')
|
||
const day = String(now.getDate()).padStart(2, '0')
|
||
return `${year}-${month}-${day}`
|
||
}
|
||
|
||
const enterProjectCalc = () => {
|
||
writeWorkspaceMode('project')
|
||
tabStore.enterWorkspace({
|
||
id: PROJECT_TAB_ID,
|
||
title: '项目计算',
|
||
componentName: 'XmView'
|
||
})
|
||
tabStore.hasCompletedSetup = true
|
||
}
|
||
|
||
const loadProjectDefaults = async () => {
|
||
const savedInfo = await kvStore.getItem<ProjectInfoState>(PROJECT_INFO_KEY)
|
||
projectIndustry.value =
|
||
typeof savedInfo?.projectIndustry === 'string' && savedInfo.projectIndustry.trim()
|
||
? savedInfo.projectIndustry.trim()
|
||
: String(industryTypeList[0]?.id || '')
|
||
}
|
||
|
||
const openProjectCalc = async () => {
|
||
const savedInfo = await kvStore.getItem<ProjectInfoState>(PROJECT_INFO_KEY)
|
||
if (typeof savedInfo?.projectIndustry === 'string' && savedInfo.projectIndustry.trim()) {
|
||
enterProjectCalc()
|
||
return
|
||
}
|
||
await loadProjectDefaults()
|
||
projectDialogOpen.value = true
|
||
}
|
||
|
||
const closeProjectCalcDialog = () => {
|
||
projectDialogOpen.value = false
|
||
}
|
||
|
||
const confirmProjectCalc = async () => {
|
||
const industry = projectIndustry.value.trim()
|
||
if (!industry) return
|
||
|
||
projectSubmitting.value = true
|
||
try {
|
||
await kvStore.setItem<ProjectInfoState>(PROJECT_INFO_KEY, {
|
||
projectIndustry: industry,
|
||
projectName: DEFAULT_PROJECT_NAME,
|
||
preparedBy: '',
|
||
reviewedBy: '',
|
||
preparedCompany: '',
|
||
preparedDate: getTodayDateString()
|
||
})
|
||
await initializeProjectFactorStates(
|
||
kvStore,
|
||
industry,
|
||
PROJECT_CONSULT_CATEGORY_FACTOR_KEY,
|
||
PROJECT_MAJOR_FACTOR_KEY
|
||
)
|
||
window.dispatchEvent(new CustomEvent<boolean>(PROJECT_INIT_CHANGED_EVENT, { detail: true }))
|
||
enterProjectCalc()
|
||
} finally {
|
||
projectSubmitting.value = false
|
||
projectDialogOpen.value = false
|
||
}
|
||
}
|
||
|
||
const loadQuickDefaults = async () => {
|
||
const [savedInfo, savedMeta] = await Promise.all([
|
||
kvStore.getItem<QuickProjectInfoState>(QUICK_PROJECT_INFO_KEY),
|
||
kvStore.getItem<QuickContractMetaState>(QUICK_CONTRACT_META_KEY)
|
||
])
|
||
|
||
quickIndustry.value =
|
||
typeof savedInfo?.projectIndustry === 'string' && savedInfo.projectIndustry.trim()
|
||
? savedInfo.projectIndustry.trim()
|
||
: String(industryTypeList[0]?.id || '')
|
||
quickContractName.value =
|
||
typeof savedMeta?.name === 'string' && savedMeta.name.trim()
|
||
? savedMeta.name.trim()
|
||
: QUICK_CONTRACT_FALLBACK_NAME
|
||
}
|
||
|
||
const openQuickCalcDialog = async () => {
|
||
await loadQuickDefaults()
|
||
quickDialogOpen.value = true
|
||
}
|
||
|
||
const closeQuickCalcDialog = () => {
|
||
quickDialogOpen.value = false
|
||
}
|
||
|
||
const confirmQuickCalc = async () => {
|
||
const contractName = quickContractName.value.trim()
|
||
const industry = quickIndustry.value.trim()
|
||
if (!contractName || !industry) return
|
||
|
||
quickSubmitting.value = true
|
||
try {
|
||
const currentInfo = await kvStore.getItem<QuickProjectInfoState>(QUICK_PROJECT_INFO_KEY)
|
||
await kvStore.setItem(QUICK_PROJECT_INFO_KEY, {
|
||
...currentInfo,
|
||
projectIndustry: industry,
|
||
projectName: '快速计算'
|
||
})
|
||
await kvStore.setItem(QUICK_CONTRACT_META_KEY, {
|
||
id: QUICK_CONTRACT_ID,
|
||
name: contractName,
|
||
updatedAt: new Date().toISOString()
|
||
})
|
||
await initializeProjectFactorStates(
|
||
kvStore,
|
||
industry,
|
||
QUICK_CONSULT_CATEGORY_FACTOR_KEY,
|
||
QUICK_MAJOR_FACTOR_KEY
|
||
)
|
||
|
||
tabStore.enterWorkspace({
|
||
id: `contract-${QUICK_CONTRACT_ID}`,
|
||
title: contractName,
|
||
componentName: 'ContractDetailView',
|
||
props: {
|
||
contractId: QUICK_CONTRACT_ID,
|
||
contractName,
|
||
projectInfoKey: QUICK_PROJECT_INFO_KEY,
|
||
projectScaleKey: null,
|
||
projectConsultCategoryFactorKey: QUICK_CONSULT_CATEGORY_FACTOR_KEY,
|
||
projectMajorFactorKey: QUICK_MAJOR_FACTOR_KEY
|
||
}
|
||
})
|
||
tabStore.hasCompletedSetup = true
|
||
} finally {
|
||
quickSubmitting.value = false
|
||
quickDialogOpen.value = false
|
||
}
|
||
}
|
||
|
||
const handleHomeImportChange = (event: Event) => {
|
||
const input = event.target as HTMLInputElement
|
||
const file = input.files?.[0]
|
||
if (!file) return
|
||
window.dispatchEvent(new CustomEvent('home-import-selected', {
|
||
detail: {
|
||
file
|
||
}
|
||
}))
|
||
input.value = ''
|
||
}
|
||
|
||
const openHomeImport = () => {
|
||
homeImportInputRef.value?.click()
|
||
}
|
||
|
||
onMounted(() => {
|
||
void loadProjectDefaults()
|
||
void loadQuickDefaults()
|
||
})
|
||
</script>
|
||
|
||
<template>
|
||
<input ref="homeImportInputRef" type="file" accept=".zw" class="sr-only" @change="handleHomeImportChange" />
|
||
<div class="flex min-h-full items-center justify-center px-4 py-8 lg:py-10">
|
||
<div class="w-full max-w-[1240px]">
|
||
<div class="grid items-stretch gap-6 lg:grid-cols-[320px_1fr]">
|
||
<div
|
||
class="relative overflow-hidden rounded-2xl bg-[linear-gradient(145deg,#041c5f_0%,#0b2e86_50%,#354cc7_100%)] p-8 text-white shadow-[0_24px_60px_rgba(11,46,134,0.45)]"
|
||
>
|
||
<div class="pointer-events-none absolute -right-20 -top-16 h-56 w-56 rounded-full bg-white/12 blur-2xl" />
|
||
<div
|
||
class="pointer-events-none absolute inset-0 bg-[repeating-linear-gradient(140deg,rgba(255,255,255,0.06)_0,rgba(255,255,255,0.06)_1px,transparent_1px,transparent_20px)]"
|
||
/>
|
||
<div class="relative inline-flex h-12 w-12 items-center justify-center rounded-xl bg-white/15 ring-1 ring-white/35">
|
||
<Calculator class="h-6 w-6" />
|
||
</div>
|
||
<h2 class="relative mt-10 text-3xl font-semibold leading-tight tracking-tight">智能预算一键生成-></h2>
|
||
<p class="relative mt-3 text-base text-blue-100">助力《规范》高效落地</p>
|
||
</div>
|
||
|
||
<div class="flex flex-col justify-center">
|
||
<div class="text-center">
|
||
<h1 class="text-3xl font-semibold tracking-tight text-slate-900">计算入口</h1>
|
||
<p class="mt-2 text-sm text-slate-600">支持三种计算方式:项目计算 · 单项速算 · 导入数据</p>
|
||
</div>
|
||
<div class="mt-6 grid gap-4 md:grid-cols-2 xl:grid-cols-3">
|
||
<Card
|
||
role="button"
|
||
tabindex="0"
|
||
class="group flex cursor-pointer flex-col rounded-2xl border border-slate-200/80 bg-white/95 p-5 shadow-[0_10px_30px_rgba(15,23,42,0.08)] backdrop-blur-sm transition-all duration-200 hover:-translate-y-1 hover:shadow-[0_20px_45px_rgba(15,23,42,0.16)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-200"
|
||
@click="openProjectCalc"
|
||
@keydown.enter.prevent="openProjectCalc"
|
||
@keydown.space.prevent="openProjectCalc"
|
||
>
|
||
<CardHeader class="space-y-3 p-0">
|
||
<div>
|
||
<CardTitle class="text-2xl font-semibold text-slate-900">项目预算</CardTitle>
|
||
<CardDescription class="mt-2 text-sm leading-6 text-slate-500">
|
||
适用:多合同段、项目级整体计算
|
||
<br>
|
||
操作:支持当前项目及合同段卡片和流程线,可导出/导入完整项目数据
|
||
</CardDescription>
|
||
</div>
|
||
</CardHeader>
|
||
<CardContent class="mt-auto flex flex-col items-center p-0 pt-8">
|
||
<div
|
||
class="mt-4 inline-flex h-16 w-16 items-center justify-center rounded-full border border-blue-100 bg-[radial-gradient(circle_at_30%_30%,#ffffff,#eef4ff)] shadow-[0_10px_24px_rgba(27,76,176,0.18)]"
|
||
>
|
||
<img
|
||
v-if="projectIconAvailable"
|
||
:src="'/image_0.png'"
|
||
alt="项目预算"
|
||
class="h-8 w-8 object-contain"
|
||
@error="projectIconAvailable = false"
|
||
>
|
||
<FolderKanban v-else class="h-7 w-7 text-blue-700" />
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
<Card
|
||
role="button"
|
||
tabindex="0"
|
||
class="group flex cursor-pointer flex-col rounded-2xl border border-slate-200/80 bg-white/95 p-5 shadow-[0_10px_30px_rgba(15,23,42,0.08)] backdrop-blur-sm transition-all duration-200 hover:-translate-y-1 hover:shadow-[0_20px_45px_rgba(15,23,42,0.16)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-200"
|
||
@click="openQuickCalcDialog"
|
||
@keydown.enter.prevent="openQuickCalcDialog"
|
||
@keydown.space.prevent="openQuickCalcDialog"
|
||
>
|
||
<CardHeader class="space-y-3 p-0">
|
||
<div>
|
||
<CardTitle class="text-2xl font-semibold text-slate-900">单项速算</CardTitle>
|
||
<CardDescription class="mt-2 text-sm leading-6 text-slate-500">
|
||
适用:单合同段预算、单项试算
|
||
<br>
|
||
操作:选择行业与咨询类型,输入基数,秒出结果
|
||
</CardDescription>
|
||
</div>
|
||
</CardHeader>
|
||
<CardContent class="mt-auto flex flex-col items-center p-0 pt-8">
|
||
<div
|
||
class="mt-4 inline-flex h-16 w-16 items-center justify-center rounded-full border border-blue-100 bg-[radial-gradient(circle_at_30%_30%,#ffffff,#eef4ff)] shadow-[0_10px_24px_rgba(27,76,176,0.18)]"
|
||
>
|
||
<img
|
||
v-if="quickIconAvailable"
|
||
:src="'/image_1.png'"
|
||
alt="单项速算"
|
||
class="h-8 w-8 object-contain"
|
||
@error="quickIconAvailable = false"
|
||
>
|
||
<Zap v-else class="h-7 w-7 text-amber-500" />
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
<Card
|
||
role="button"
|
||
tabindex="0"
|
||
class="group flex cursor-pointer flex-col rounded-2xl border border-slate-200/80 bg-white/95 p-5 shadow-[0_10px_30px_rgba(15,23,42,0.08)] backdrop-blur-sm transition-all duration-200 hover:-translate-y-1 hover:shadow-[0_20px_45px_rgba(15,23,42,0.16)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-200"
|
||
@click="openHomeImport"
|
||
@keydown.enter.prevent="openHomeImport"
|
||
@keydown.space.prevent="openHomeImport"
|
||
>
|
||
<CardHeader class="space-y-3 p-0">
|
||
<div>
|
||
<CardTitle class="text-2xl font-semibold text-slate-900">导入数据</CardTitle>
|
||
<CardDescription class="mt-2 text-sm leading-6 text-slate-500">
|
||
适用:续未完成工作、跨设备恢复数据
|
||
<br>
|
||
操作:导入".zw"数据包,快速恢复项目计算状态
|
||
</CardDescription>
|
||
</div>
|
||
</CardHeader>
|
||
<CardContent class="mt-auto flex flex-col items-center p-0 pt-8">
|
||
<div
|
||
class="mt-4 inline-flex h-16 w-16 items-center justify-center rounded-full border border-blue-100 bg-[radial-gradient(circle_at_30%_30%,#ffffff,#eef4ff)] shadow-[0_10px_24px_rgba(27,76,176,0.18)]"
|
||
>
|
||
<img
|
||
v-if="importIconAvailable"
|
||
:src="'/image_2.png'"
|
||
alt="导入数据"
|
||
class="h-8 w-8 object-contain"
|
||
@error="importIconAvailable = false"
|
||
>
|
||
<Download v-else class="h-7 w-7 text-cyan-600" />
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div
|
||
v-if="projectDialogOpen"
|
||
class="fixed inset-0 z-[90] flex items-center justify-center bg-black/45 p-4"
|
||
@click.self="closeProjectCalcDialog"
|
||
>
|
||
<div class="w-full max-w-md rounded-xl border bg-background shadow-2xl">
|
||
<div class="flex items-center justify-between border-b px-5 py-4">
|
||
<div>
|
||
<h3 class="text-base font-semibold text-foreground">新建项目</h3>
|
||
<p class="mt-1 text-sm text-muted-foreground">选择工程行业后,直接进入项目计算页面。</p>
|
||
</div>
|
||
<Button variant="ghost" size="icon" class="h-8 w-8" @click="closeProjectCalcDialog">
|
||
<X class="h-4 w-4" />
|
||
</Button>
|
||
</div>
|
||
|
||
<div class="space-y-4 px-5 py-4">
|
||
<label class="block space-y-2">
|
||
<span class="text-sm font-medium text-foreground">工程行业</span>
|
||
<SelectRoot v-model="projectIndustry">
|
||
<SelectTrigger
|
||
class="inline-flex h-11 w-full items-center justify-between rounded-xl border border-border/70 bg-[linear-gradient(180deg,rgba(248,250,252,0.98),rgba(241,245,249,0.92))] px-4 text-sm text-foreground shadow-sm outline-none transition hover:border-border focus-visible:ring-2 focus-visible:ring-slate-300"
|
||
>
|
||
<SelectValue placeholder="请选择工程行业" />
|
||
<SelectIcon as-child>
|
||
<ChevronDown class="h-4 w-4 text-muted-foreground" />
|
||
</SelectIcon>
|
||
</SelectTrigger>
|
||
<SelectPortal>
|
||
<SelectContent
|
||
:side-offset="6"
|
||
position="popper"
|
||
class="z-[120] w-[var(--reka-select-trigger-width)] overflow-hidden rounded-xl border border-border bg-popover text-popover-foreground shadow-xl"
|
||
>
|
||
<SelectViewport class="p-1">
|
||
<SelectItem
|
||
v-for="item in industryTypeList"
|
||
:key="`project-${item.id}`"
|
||
:value="String(item.id)"
|
||
class="relative flex h-9 w-full cursor-default select-none items-center rounded-md pl-3 pr-8 text-sm outline-none data-[highlighted]:bg-muted data-[highlighted]:text-foreground data-[state=checked]:bg-slate-100"
|
||
>
|
||
<SelectItemText>{{ item.name }}</SelectItemText>
|
||
<SelectItemIndicator class="absolute right-2 inline-flex items-center text-slate-700">
|
||
<Check class="h-4 w-4" />
|
||
</SelectItemIndicator>
|
||
</SelectItem>
|
||
</SelectViewport>
|
||
</SelectContent>
|
||
</SelectPortal>
|
||
</SelectRoot>
|
||
</label>
|
||
</div>
|
||
|
||
<div class="flex items-center justify-end gap-2 border-t px-5 py-4">
|
||
<Button variant="outline" @click="closeProjectCalcDialog">取消</Button>
|
||
<Button :disabled="projectSubmitting || !projectIndustry" @click="confirmProjectCalc">
|
||
{{ projectSubmitting ? '进入中...' : '进入项目计算' }}
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div
|
||
v-if="quickDialogOpen"
|
||
class="fixed inset-0 z-[90] flex items-center justify-center bg-black/45 p-4"
|
||
@click.self="closeQuickCalcDialog"
|
||
>
|
||
<div class="w-full max-w-md rounded-xl border bg-background shadow-2xl">
|
||
<div class="flex items-center justify-between border-b px-5 py-4">
|
||
<div>
|
||
<h3 class="text-base font-semibold text-foreground">单项速算</h3>
|
||
<p class="mt-1 text-sm text-muted-foreground">输入合同名称后,进入单项速算页面。</p>
|
||
</div>
|
||
<Button variant="ghost" size="icon" class="h-8 w-8" @click="closeQuickCalcDialog">
|
||
<X class="h-4 w-4" />
|
||
</Button>
|
||
</div>
|
||
|
||
<div class="space-y-4 px-5 py-4">
|
||
<label class="block space-y-2">
|
||
<span class="text-sm font-medium text-foreground">工程行业</span>
|
||
<SelectRoot v-model="quickIndustry">
|
||
<SelectTrigger
|
||
class="inline-flex h-11 w-full items-center justify-between rounded-xl border border-border/70 bg-[linear-gradient(180deg,rgba(248,250,252,0.98),rgba(241,245,249,0.92))] px-4 text-sm text-foreground shadow-sm outline-none transition hover:border-border focus-visible:ring-2 focus-visible:ring-slate-300"
|
||
>
|
||
<SelectValue placeholder="请选择工程行业" />
|
||
<SelectIcon as-child>
|
||
<ChevronDown class="h-4 w-4 text-muted-foreground" />
|
||
</SelectIcon>
|
||
</SelectTrigger>
|
||
<SelectPortal>
|
||
<SelectContent
|
||
:side-offset="6"
|
||
position="popper"
|
||
class="z-[120] w-[var(--reka-select-trigger-width)] overflow-hidden rounded-xl border border-border bg-popover text-popover-foreground shadow-xl"
|
||
>
|
||
<SelectViewport class="p-1">
|
||
<SelectItem
|
||
v-for="item in industryTypeList"
|
||
:key="`quick-${item.id}`"
|
||
:value="String(item.id)"
|
||
class="relative flex h-9 w-full cursor-default select-none items-center rounded-md pl-3 pr-8 text-sm outline-none data-[highlighted]:bg-muted data-[highlighted]:text-foreground data-[state=checked]:bg-slate-100"
|
||
>
|
||
<SelectItemText>{{ item.name }}</SelectItemText>
|
||
<SelectItemIndicator class="absolute right-2 inline-flex items-center text-slate-700">
|
||
<Check class="h-4 w-4" />
|
||
</SelectItemIndicator>
|
||
</SelectItem>
|
||
</SelectViewport>
|
||
</SelectContent>
|
||
</SelectPortal>
|
||
</SelectRoot>
|
||
</label>
|
||
|
||
<label class="block space-y-2">
|
||
<span class="text-sm font-medium text-foreground">合同名称</span>
|
||
<input
|
||
v-model="quickContractName"
|
||
type="text"
|
||
class="inline-flex h-11 w-full items-center justify-between rounded-xl border border-border/70 bg-[linear-gradient(180deg,rgba(248,250,252,0.98),rgba(241,245,249,0.92))] px-4 text-sm text-foreground shadow-sm outline-none transition placeholder:text-slate-400 hover:border-border focus-visible:ring-2 focus-visible:ring-slate-300"
|
||
placeholder="请输入合同名称"
|
||
>
|
||
</label>
|
||
</div>
|
||
|
||
<div class="flex items-center justify-end gap-2 border-t px-5 py-4">
|
||
<Button variant="outline" @click="closeQuickCalcDialog">取消</Button>
|
||
<Button :disabled="quickSubmitting || !quickContractName" @click="confirmQuickCalc">
|
||
{{ quickSubmitting ? '进入中...' : '进入计算' }}
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|