diff --git a/shot-login-sms.png b/shot-login-sms.png deleted file mode 100644 index c2313fe..0000000 Binary files a/shot-login-sms.png and /dev/null differ diff --git a/shot-login.png b/shot-login.png deleted file mode 100644 index b2e5799..0000000 Binary files a/shot-login.png and /dev/null differ diff --git a/shot-register.png b/shot-register.png deleted file mode 100644 index e4de305..0000000 Binary files a/shot-register.png and /dev/null differ diff --git a/shot-reset-password.png b/shot-reset-password.png deleted file mode 100644 index 054c016..0000000 Binary files a/shot-reset-password.png and /dev/null differ diff --git a/src/layout/index.vue b/src/layout/index.vue index e3e0cdb..9cd4919 100644 --- a/src/layout/index.vue +++ b/src/layout/index.vue @@ -1,5 +1,11 @@ @@ -8,7 +14,7 @@ import { AppFooter, AppHeader, FilePreviewDialog } from '@/components' - + @@ -16,12 +22,19 @@ import { AppFooter, AppHeader, FilePreviewDialog } from '@/components' diff --git a/src/router/routes.ts b/src/router/routes.ts index aaf8f13..7d71227 100644 --- a/src/router/routes.ts +++ b/src/router/routes.ts @@ -15,13 +15,13 @@ const layoutRoutes: RouteRecordRaw = { { path: 'cases', name: 'Cases', component: () => import('@/views/cases'), meta: { title: '成功案例库' } }, { path: 'cases/:id', name: 'CaseDetail', component: () => import('@/views/cases/detail.vue'), meta: { title: '案例详情' } }, // 需求提报依赖登录态:字典 / 业务类型 / 草稿 / 上传 / 提交接口匿名实测均 401 - { path: 'demand', name: 'Demand', component: () => import('@/views/demand'), meta: { title: '需求提报', requiresAuth: true } }, + { path: 'demand', name: 'Demand', component: () => import('@/views/demand'), meta: { title: '需求提报', requiresAuth: true, noFooter: true } }, // ── 登录区 ── { path: 'project', name: 'Project', component: () => import('@/views/project'), meta: { title: '项目中心', requiresAuth: true } }, { path: 'project/:id', name: 'ProjectDetail', component: () => import('@/views/project/detail.vue'), meta: { title: '项目详情', requiresAuth: true } }, { path: 'project/:id/after-sales', name: 'AfterSales', component: () => import('@/views/project/after-sales.vue'), meta: { title: '申请售后', requiresAuth: true } }, - { path: 'contract', name: 'Contract', component: () => import('@/views/contract'), meta: { title: '合同中心', requiresAuth: true } }, + { path: 'contract', name: 'Contract', component: () => import('@/views/contract'), meta: { title: '合同中心', requiresAuth: true, noFooter: true } }, { path: 'contract/:id', name: 'ContractDetail', component: () => import('@/views/contract/detail.vue'), meta: { title: '合同详情', requiresAuth: true } }, { path: 'contract/:id/sign', name: 'ContractSign', component: () => import('@/views/contract/sign.vue'), meta: { title: '签署合同', requiresAuth: true } }, { path: 'finance', name: 'Finance', component: () => import('@/views/finance'), meta: { title: '财务中心', requiresAuth: true } }, diff --git a/src/stores/modules/home.ts b/src/stores/modules/home.ts index e254f76..a148970 100644 --- a/src/stores/modules/home.ts +++ b/src/stores/modules/home.ts @@ -3,6 +3,8 @@ import { computed, ref } from 'vue' import type { BusinessType } from '@/types/api' import type { Case } from '@/types/business/cases' import type { + Banner, + BannerVo, BusinessLine, HomeStats, ProjectStatusCount, @@ -14,6 +16,7 @@ import type { } from '@/types/business/home' import type { PortalEntryGroup, PortalEntryVo } from '@/types/business/home' import { + getCarouselList, getPortalEntryList, getProjectStatusCount, getServiceTypeDetail, @@ -52,6 +55,17 @@ function stripHtml(html: string): string { .trim() } +/** 后端轮播 VO → 页面 Banner(仅启用项,按 sort 升序) */ +function toBanners(list: BannerVo[]): Banner[] { + return list + .filter((item) => item.enabled !== false && Boolean(item.imageUrl)) + .sort((a, b) => (a.sort ?? 0) - (b.sort ?? 0)) + .map((item) => ({ + id: item.id ?? 0, + imageUrl: item.imageUrl ?? '', + })) +} + /** 后端「项目提报」→ 业务线卡片 / 业务详情 */ function toBusinessLine(vo: ProjectSubmissionVo): BusinessLine { const serviceTypes: ServiceType[] = (vo.serviceTypes ?? []).map((item) => ({ @@ -130,6 +144,7 @@ export const useHomeStore = defineStore('home', () => { const casesStore = useCasesStore() const stats = ref({ pending: 0, inProgress: 0, total: 0 }) + const banners = ref([]) const businessLines = ref([]) const featuredCases = ref([]) const currentBusiness = ref(null) @@ -185,10 +200,11 @@ export const useHomeStore = defineStore('home', () => { /** 首页初始化:看板 + 轮播图 + 业务服务线 + 案例精选 */ async function fetchHomeData(): Promise { - const [statusCount, submissionList, cases] = await Promise.all([ + const [statusCount, submissionList, cases, carouselList] = await Promise.all([ getProjectStatusCount(), getServiceTypeList(), getFeaturedCasesApi(), + getCarouselList().catch(() => [] as BannerVo[]), // 案例标签需要「提报 id → 类型名」字典,与首页其余数据并行取(幂等,已加载则不发请求) casesStore.ensureCategories(), ]) @@ -201,6 +217,7 @@ export const useHomeStore = defineStore('home', () => { submissions.value = submissionList businessLines.value = submissionList.map(toBusinessLine) featuredCases.value = cases.map((vo) => toCase(vo, casesStore.typeNameById)) + banners.value = toBanners(carouselList ?? []) // 入口个性化接口失败已被内部吞掉,不会影响上面的首页数据 await fetchPortalEntries() } @@ -240,6 +257,7 @@ export const useHomeStore = defineStore('home', () => { return { stats, + banners, businessLines, featuredCases, currentBusiness, diff --git a/src/types/business/home.d.ts b/src/types/business/home.d.ts index 3eee878..1d30bde 100644 --- a/src/types/business/home.d.ts +++ b/src/types/business/home.d.ts @@ -16,6 +16,12 @@ export interface HomeStats { total: number } +/** 首页头图轮播(VIEW 层,由 BannerVo 映射) */ +export interface Banner { + id: number + imageUrl: string +} + /** 快捷入口(VIEW 层占位,实际入口由门户接口驱动) */ export interface QuickLink { label: string diff --git a/src/views/home/cpns/HomeAppDialog.vue b/src/views/home/cpns/HomeAppDialog.vue index 80dff70..46512db 100644 --- a/src/views/home/cpns/HomeAppDialog.vue +++ b/src/views/home/cpns/HomeAppDialog.vue @@ -166,12 +166,13 @@ function onClose(): void { &__panel { .flex(column, flex-start, stretch); width: 560px; - max-width: calc(100vw - 32px); - max-height: calc(100vh - 64px); + max-width: calc((100vw - 32px) / 1.5); + max-height: calc((100vh - 64px) / 1.5); padding: @spacing-lg; border-radius: @radius-lg; background: @white; box-shadow: @shadow-lg; + zoom: 1.5; } &__head { diff --git a/src/views/home/cpns/HomeBanner.vue b/src/views/home/cpns/HomeBanner.vue index df3c4b1..9ac6511 100644 --- a/src/views/home/cpns/HomeBanner.vue +++ b/src/views/home/cpns/HomeBanner.vue @@ -1,10 +1,24 @@ + + + + + + + + 虫子智造研发一体化平台 一站式智能软硬件研发与量产综合服务商 @@ -29,36 +83,66 @@ function goCases(): void { 案例中心 + - - - + + diff --git a/src/views/home/index.vue b/src/views/home/index.vue index 2b87192..c089ffa 100644 --- a/src/views/home/index.vue +++ b/src/views/home/index.vue @@ -12,7 +12,7 @@ import HomeBusinessCards from './cpns/HomeBusinessCards.vue' import HomeCaseShowcase from './cpns/HomeCaseShowcase.vue' const homeStore = useHomeStore() -const { stats, businessLines, featuredCases } = storeToRefs(homeStore) +const { banners, stats, businessLines, featuredCases } = storeToRefs(homeStore) const todaySummary = computed(() => `今天有${stats.value.inProgress}个项目正在进行`) @@ -27,8 +27,8 @@ onMounted(() => { - - + +
一站式智能软硬件研发与量产综合服务商