优化目录
This commit is contained in:
1 parent
4e343cccf1
commit
2b18fe9991
46 files changed
+1061
-1308
No files matched your search
@@ -4,7 +4,15 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/com
|
||||
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 {
|
||||
Calculator,
|
||||
Check,
|
||||
ChevronDown,
|
||||
Download,
|
||||
FolderKanban,
|
||||
X,
|
||||
Zap
|
||||
} from 'lucide-vue-next'
|
||||
import { industryTypeList } from '@/sql'
|
||||
import { initializeProjectFactorStates } from '@/lib/projectWorkspace'
|
||||
import {
|
||||
@@ -57,7 +65,7 @@ interface ProjectInfoState {
|
||||
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 DEFAULT_PROJECT_NAME = 'xxx 造价咨询服务'
|
||||
const PROJECT_INIT_CHANGED_EVENT = 'xm-project-init-changed'
|
||||
|
||||
const tabStore = useTabStore()
|
||||
@@ -69,6 +77,10 @@ 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()
|
||||
@@ -83,8 +95,9 @@ const enterProjectCalc = () => {
|
||||
tabStore.enterWorkspace({
|
||||
id: PROJECT_TAB_ID,
|
||||
title: '项目计算',
|
||||
componentName: PROJECT_TAB_ID
|
||||
componentName: 'XmView'
|
||||
})
|
||||
tabStore.hasCompletedSetup = true
|
||||
}
|
||||
|
||||
const loadProjectDefaults = async () => {
|
||||
@@ -187,7 +200,6 @@ const confirmQuickCalc = async () => {
|
||||
QUICK_MAJOR_FACTOR_KEY
|
||||
)
|
||||
|
||||
writeWorkspaceMode('quick')
|
||||
tabStore.enterWorkspace({
|
||||
id: `contract-${QUICK_CONTRACT_ID}`,
|
||||
title: contractName,
|
||||
@@ -201,6 +213,7 @@ const confirmQuickCalc = async () => {
|
||||
projectMajorFactorKey: QUICK_MAJOR_FACTOR_KEY
|
||||
}
|
||||
})
|
||||
tabStore.hasCompletedSetup = true
|
||||
} finally {
|
||||
quickSubmitting.value = false
|
||||
quickDialogOpen.value = false
|
||||
@@ -219,6 +232,10 @@ const handleHomeImportChange = (event: Event) => {
|
||||
input.value = ''
|
||||
}
|
||||
|
||||
const openHomeImport = () => {
|
||||
homeImportInputRef.value?.click()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
void loadProjectDefaults()
|
||||
void loadQuickDefaults()
|
||||
@@ -226,104 +243,133 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<input id="home-import-input" type="file" accept=".zw" class="sr-only" @change="handleHomeImportChange" />
|
||||
<div class="flex min-h-full items-center justify-center px-4 py-8">
|
||||
<div class="w-full max-w-5xl">
|
||||
<div class="mx-auto max-w-2xl text-center">
|
||||
<p class="text-sm font-medium tracking-[0.28em] text-muted-foreground">JGJS 2026</p>
|
||||
<h1 class="mt-4 text-4xl font-semibold tracking-tight text-foreground">选择计算入口</h1>
|
||||
<p class="mt-3 text-sm leading-6 text-muted-foreground">
|
||||
首页支持三种入口:继续项目计算、快速单合同测算,或直接导入已有数据包。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="mt-10 grid items-stretch gap-5 md:grid-cols-3">
|
||||
<Card
|
||||
role="button"
|
||||
tabindex="0"
|
||||
class="flex h-full cursor-pointer flex-col border-border/70 bg-card/90 shadow-[0_18px_48px_rgba(15,23,42,0.08)] transition hover:-translate-y-0.5 hover:shadow-[0_22px_56px_rgba(15,23,42,0.12)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
||||
@click="openProjectCalc"
|
||||
@keydown.enter.prevent="openProjectCalc"
|
||||
@keydown.space.prevent="openProjectCalc"
|
||||
<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)]"
|
||||
>
|
||||
<CardHeader class="flex min-h-[184px] flex-col space-y-4 pb-4">
|
||||
<div class="inline-flex h-12 w-12 items-center justify-center rounded-2xl bg-slate-900 text-white">
|
||||
<FolderKanban class="h-6 w-6" />
|
||||
</div>
|
||||
<div class="min-h-[88px]">
|
||||
<CardTitle class="text-2xl">项目计算</CardTitle>
|
||||
<CardDescription class="mt-2 text-sm leading-6">
|
||||
继续使用当前项目卡片、流程线、合同段管理和整项目导入导出能力。
|
||||
</CardDescription>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent class="mt-auto flex flex-1 flex-col justify-end space-y-4">
|
||||
<div class="flex min-h-[72px] items-center rounded-2xl border border-border/60 bg-muted/35 p-4 text-sm text-muted-foreground">
|
||||
适合多合同段、项目级系数维护、整项目报表和批量导入导出。
|
||||
</div>
|
||||
<Button class="w-full justify-between" @click.stop="openProjectCalc">
|
||||
进入项目计算
|
||||
<Calculator class="h-4 w-4" />
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<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>
|
||||
|
||||
<Card
|
||||
role="button"
|
||||
tabindex="0"
|
||||
class="flex h-full cursor-pointer flex-col border-border/70 bg-[linear-gradient(135deg,rgba(15,23,42,0.05),rgba(148,163,184,0.12))] shadow-[0_18px_48px_rgba(15,23,42,0.08)] transition hover:-translate-y-0.5 hover:shadow-[0_22px_56px_rgba(15,23,42,0.12)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
||||
@click="openQuickCalcDialog"
|
||||
@keydown.enter.prevent="openQuickCalcDialog"
|
||||
@keydown.space.prevent="openQuickCalcDialog"
|
||||
>
|
||||
<CardHeader class="flex min-h-[184px] flex-col space-y-4 pb-4">
|
||||
<div class="inline-flex h-12 w-12 items-center justify-center rounded-2xl bg-amber-500 text-slate-950">
|
||||
<Zap class="h-6 w-6" />
|
||||
</div>
|
||||
<div class="min-h-[88px]">
|
||||
<CardTitle class="text-2xl">快速计算</CardTitle>
|
||||
<CardDescription class="mt-2 text-sm leading-6">
|
||||
先填写工程行业和合同名称,再直接进入单合同预算费用测算页面。
|
||||
</CardDescription>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent class="mt-auto flex flex-1 flex-col justify-end space-y-4">
|
||||
<div class="flex min-h-[72px] items-center rounded-2xl border border-border/60 bg-background/80 p-4 text-sm text-muted-foreground">
|
||||
适合快速试算、单合同预算复核和不需要项目级合同段管理的场景。
|
||||
</div>
|
||||
<Button variant="outline" class="w-full justify-between" @click.stop="openQuickCalcDialog">
|
||||
进入快速计算
|
||||
<Zap class="h-4 w-4" />
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<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>
|
||||
|
||||
<label for="home-import-input" class="block h-full cursor-pointer">
|
||||
<Card
|
||||
class="flex h-full flex-col border-border/70 bg-[linear-gradient(135deg,rgba(14,116,144,0.08),rgba(186,230,253,0.26))] shadow-[0_18px_48px_rgba(15,23,42,0.08)] transition hover:-translate-y-0.5 hover:shadow-[0_22px_56px_rgba(15,23,42,0.12)]"
|
||||
>
|
||||
<CardHeader class="flex min-h-[184px] flex-col space-y-4 pb-4">
|
||||
<div class="inline-flex h-12 w-12 items-center justify-center rounded-2xl bg-cyan-600 text-white">
|
||||
<Download class="h-6 w-6" />
|
||||
</div>
|
||||
<div class="min-h-[88px]">
|
||||
<CardTitle class="text-2xl">导入数据</CardTitle>
|
||||
<CardDescription class="mt-2 text-sm leading-6">
|
||||
直接导入已有 `.zw` 数据包,恢复项目计算或快速计算的本地工作区状态。
|
||||
</CardDescription>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent class="mt-auto flex flex-1 flex-col justify-end space-y-4">
|
||||
<div class="flex min-h-[72px] items-center rounded-2xl border border-border/60 bg-background/80 p-4 text-sm text-muted-foreground">
|
||||
适合继续上次工作、切换设备恢复数据,或直接打开别人发来的测算包。
|
||||
</div>
|
||||
<div class="inline-flex h-10 w-full items-center justify-between rounded-md border border-input bg-secondary px-4 text-sm font-medium text-secondary-foreground shadow-xs transition-colors">
|
||||
<span>选择导入文件</span>
|
||||
<Download class="h-4 w-4" />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</label>
|
||||
<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>
|
||||
@@ -398,8 +444,8 @@ onMounted(() => {
|
||||
<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>
|
||||
<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" />
|
||||
@@ -447,18 +493,16 @@ onMounted(() => {
|
||||
<input
|
||||
v-model="quickContractName"
|
||||
type="text"
|
||||
maxlength="40"
|
||||
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="请输入合同名称"
|
||||
class="h-10 w-full rounded-md border bg-background px-3 text-sm outline-none transition focus-visible:ring-2 focus-visible:ring-ring"
|
||||
@keydown.enter="confirmQuickCalc"
|
||||
/>
|
||||
>
|
||||
</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 || !quickIndustry || !quickContractName.trim()" @click="confirmQuickCalc">
|
||||
{{ quickSubmitting ? '进入中...' : '进入快速计算' }}
|
||||
<Button :disabled="quickSubmitting || !quickContractName" @click="confirmQuickCalc">
|
||||
{{ quickSubmitting ? '进入中...' : '进入计算' }}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user