diff --git a/src/components/AppTabBar.vue b/src/components/AppTabBar.vue
index 28d7dba..d8b16ad 100644
--- a/src/components/AppTabBar.vue
+++ b/src/components/AppTabBar.vue
@@ -5,14 +5,18 @@ const props = defineProps<{
active: TabKey
}>()
-const tabs: Array<{ key: TabKey, label: string, icon: string, path: string }> = [
- { key: 'home', label: '首页', icon: '/static/icons/tab-home.svg', path: '/pages/home-index/index' },
- { key: 'case', label: '案例库', icon: '/static/icons/tab-case.svg', path: '/pages/case-library/index' },
- { key: 'message', label: '消息中心', icon: '/static/icons/tab-message.svg', path: '/pages/message-center/index' },
- { key: 'project', label: '项目中心', icon: '/static/icons/tab-project.svg', path: '/pages/project-center/index' },
- { key: 'personal', label: '个人中心', icon: '/static/icons/tab-personal.svg', path: '/pages/personal-center/index' },
+const tabs: Array<{ key: TabKey, label: string, icon: string, activeIcon: string, path: string }> = [
+ { key: 'home', label: '首页', icon: '/static/icons/tab-home.png', activeIcon: '/static/icons/tab-home-active.png', path: '/pages/home-index/index' },
+ { key: 'case', label: '案例库', icon: '/static/icons/tab-case.png', activeIcon: '/static/icons/tab-case-active.png', path: '/pages/case-library/index' },
+ { key: 'message', label: '消息中心', icon: '/static/icons/tab-message.png', activeIcon: '/static/icons/tab-message-active.png', path: '/pages/message-center/index' },
+ { key: 'project', label: '项目中心', icon: '/static/icons/tab-project.png', activeIcon: '/static/icons/tab-project-active.png', path: '/pages/project-center/index' },
+ { key: 'personal', label: '个人中心', icon: '/static/icons/tab-personal.png', activeIcon: '/static/icons/tab-personal-active.png', path: '/pages/personal-center/index' },
]
+function getTabIcon(tab: typeof tabs[number]) {
+ return tab.key === props.active ? tab.activeIcon : tab.icon
+}
+
function handleSwitch(path: string, key: TabKey) {
if (key === props.active)
return
@@ -30,8 +34,7 @@ function handleSwitch(path: string, key: TabKey) {
>
= {
+ software: {
+ id: 'software',
+ title: '互联网软件',
+ subtitle: '专业的软件定制开发服务,从需求到上线全流程保障',
+ icon: softwareIllus,
+ serviceTypes: [
+ { id: 'web', label: 'Web应用', icon: '/static/icons/service-web.png' },
+ { id: 'mini', label: '小程序', icon: '/static/icons/service-mini.png' },
+ { id: 'app', label: 'APP', icon: '/static/icons/service-app.png' },
+ { id: 'secondary', label: '二次开发', icon: '/static/icons/service-secondary.png' },
+ { id: 'desktop', label: '桌面工具', icon: '/static/icons/service-desktop.png' },
+ ],
+ contentTitle: '服务内容',
+ contentSections: [
+ '一、产品咨询与规划服务',
+ '1. 业务诊断与梳理:深入了解客户业务现状,梳理核心流程与痛点,输出业务诊断报告。',
+ '2. 竞品分析与市场调研:分析行业竞品功能与商业模式,为产品定位提供数据支撑。',
+ '3. 产品定位与MVP规划:明确产品核心价值,制定最小可行产品(MVP)路线图。',
+ '4. 技术可行性评估:评估技术实现路径、开发周期与成本,降低项目风险。',
+ '二、UI/UX 设计服务',
+ '1. 用户体验研究:通过用户访谈、可用性测试等方法,洞察用户需求与行为。',
+ '2. 交互原型设计:输出高保真交互原型,确保产品逻辑清晰、操作流畅。',
+ '3. 视觉界面设计:打造统一、美观、符合品牌调性的视觉设计体系。',
+ ],
+ },
+}
+
+export function getBusinessDetail(id: string) {
+ return BUSINESS_DETAIL_MAP[id]
+}
diff --git a/src/constants/business-types.ts b/src/constants/business-types.ts
new file mode 100644
index 0000000..478ee49
--- /dev/null
+++ b/src/constants/business-types.ts
@@ -0,0 +1,13 @@
+export const BUSINESS_TYPE_OPTIONS = [
+ '互联网软件',
+ '硬件电路',
+ '物联网全案',
+ '生产制造',
+]
+
+export const BUSINESS_TYPE_DETAIL_ID: Record = {
+ 互联网软件: 'software',
+ 硬件电路: 'hardware',
+ 物联网全案: 'iot',
+ 生产制造: 'production',
+}
diff --git a/src/constants/case-library.ts b/src/constants/case-library.ts
new file mode 100644
index 0000000..ee3903d
--- /dev/null
+++ b/src/constants/case-library.ts
@@ -0,0 +1,126 @@
+import type { CaseCategory, CaseFilterValues, CaseItem } from '@/types/case-library'
+
+export const CASE_CATEGORIES: CaseCategory[] = [
+ '全部',
+ '互联网软件',
+ '硬件电路',
+ '物联网全案',
+ '生产制造',
+]
+
+export const CASE_PAGE_SIZE = 4
+
+export const CASE_TOTAL_COUNT = 6
+
+export const CASE_FILTER_INDUSTRIES = [
+ '金融科技',
+ '电商零售',
+ '教育培训',
+ '医疗健康',
+ '硬件电路',
+ '能源环保',
+ '房地产',
+] as const
+
+export const CASE_FILTER_SCALES = [
+ '全部',
+ '50万以下',
+ '50-100万',
+ '100-300万',
+ '300-500万',
+ '500万以上',
+] as const
+
+export const CASE_FILTER_TIME_RANGES = [
+ '全部',
+ '近3个月',
+ '近半年',
+ '近一年',
+] as const
+
+export const DEFAULT_CASE_FILTER: CaseFilterValues = {
+ industries: [],
+ scales: [],
+ timeRanges: [],
+ dateRange: {
+ start: '',
+ end: '',
+ },
+}
+
+export const CASE_LIBRARY_LIST: CaseItem[] = [
+ {
+ id: '1',
+ title: '智能园区综合管理平台开发',
+ category: '互联网软件',
+ cover: '/static/icons/background.png',
+ clientType: '企业',
+ industry: '房地产',
+ scale: '200万',
+ cycle: '200个工作日',
+ teamSize: '20人',
+ completedAt: '2026/8/10',
+ favorite: true,
+ },
+ {
+ id: '2',
+ title: '工业设备远程监控系统',
+ category: '物联网全案',
+ cover: '/static/icons/1.png',
+ clientType: '企业',
+ industry: '金融科技',
+ scale: '150万',
+ cycle: '180个工作日',
+ teamSize: '16人',
+ completedAt: '2026/7/22',
+ },
+ {
+ id: '3',
+ title: '社区康养智能服务系统',
+ category: '互联网软件',
+ cover: '/static/icons/software.png',
+ clientType: '政府',
+ industry: '医疗健康',
+ scale: '320万',
+ cycle: '240个工作日',
+ teamSize: '24人',
+ completedAt: '2026/6/15',
+ favorite: true,
+ },
+ {
+ id: '4',
+ title: '新能源充电桩控制主板设计',
+ category: '硬件电路',
+ cover: '/static/icons/hardware.png',
+ clientType: '企业',
+ industry: '能源环保',
+ scale: '80万',
+ cycle: '90个工作日',
+ teamSize: '8人',
+ completedAt: '2026/5/28',
+ },
+ {
+ id: '5',
+ title: '智慧农业环境监测平台',
+ category: '物联网全案',
+ cover: '/static/icons/iot.png',
+ clientType: '企业',
+ industry: '教育培训',
+ scale: '260万',
+ cycle: '210个工作日',
+ teamSize: '18人',
+ completedAt: '2026/4/12',
+ },
+ {
+ id: '6',
+ title: '智能穿戴设备批量生产项目',
+ category: '生产制造',
+ cover: '/static/icons/production.png',
+ clientType: '企业',
+ industry: '电商零售',
+ scale: '500万',
+ cycle: '300个工作日',
+ teamSize: '30人',
+ completedAt: '2026/3/8',
+ },
+]
diff --git a/src/constants/quick-entries.ts b/src/constants/quick-entries.ts
new file mode 100644
index 0000000..4fdb6a3
--- /dev/null
+++ b/src/constants/quick-entries.ts
@@ -0,0 +1,41 @@
+import type { QuickEntryItem } from '@/types/home'
+
+export const QUICK_ENTRY_MAX = 5
+
+export const QUICK_ENTRY_STORAGE_KEY = 'home-quick-entry-ids'
+
+export const DEFAULT_QUICK_ENTRY_IDS = [
+ 'project',
+ 'report',
+ 'service',
+ 'contract',
+ 'finance',
+]
+
+export const QUICK_ENTRY_CATALOG: QuickEntryItem[] = [
+ { id: 'project', label: '项目中心', icon: '/static/icons/quick-project.png', bgColor: '#E8F0FF' },
+ { id: 'report', label: '快捷提报', icon: '/static/icons/quick-report.png', bgColor: '#E8FAF4' },
+ { id: 'service', label: '在线客服', icon: '/static/icons/quick-service.png', bgColor: '#F3E8FF' },
+ { id: 'contract', label: '合同管理', icon: '/static/icons/quick-contract.png', bgColor: '#FEE2E2' },
+ { id: 'finance', label: '财务管理', icon: '/static/icons/quick-finance.png', bgColor: '#E0F2FE' },
+ { id: 'personal', label: '个人中心', icon: '/static/icons/tab-personals.png', bgColor: '#E8F0FF' },
+ { id: 'message', label: '消息中心', icon: '/static/icons/tab-messages.png', bgColor: '#F3E8FF' },
+ { id: 'security', label: '账号安全', icon: '/static/icons/security.png', bgColor: '#E8FAF4' },
+ { id: 'feedback', label: '意见反馈', icon: '/static/icons/feedback.png', bgColor: '#FFECE1' },
+ { id: 'contract-list', label: '合同列表', icon: '/static/icons/contract-list.png', bgColor: '#FEE2E2' },
+ { id: 'invoice', label: '发票列表', icon: '/static/icons/invoice.png', bgColor: '#E0F2FE' },
+ { id: 'address', label: '地址管理', icon: '/static/icons/address.png', bgColor: '#E8F0FF' },
+ { id: 'qualification', label: '资质列表', icon: '/static/icons/qualification.png', bgColor: '#FFF3EB' },
+ { id: 'help', label: '帮助中心', icon: '/static/icons/help.png', bgColor: '#F3E8FF' },
+ { id: 'about', label: '关于我们', icon: '/static/icons/about.png', bgColor: '#E8F0FF' },
+]
+
+export function getQuickEntryById(id: string) {
+ return QUICK_ENTRY_CATALOG.find(item => item.id === id)
+}
+
+export function mapQuickEntryIds(ids: string[]) {
+ return ids
+ .map(id => getQuickEntryById(id))
+ .filter((item): item is QuickEntryItem => Boolean(item))
+}
diff --git a/src/hooks/use-quick-entries.ts b/src/hooks/use-quick-entries.ts
new file mode 100644
index 0000000..2e5343b
--- /dev/null
+++ b/src/hooks/use-quick-entries.ts
@@ -0,0 +1,71 @@
+import { computed, ref } from 'vue'
+import {
+ DEFAULT_QUICK_ENTRY_IDS,
+ mapQuickEntryIds,
+ QUICK_ENTRY_CATALOG,
+ QUICK_ENTRY_MAX,
+ QUICK_ENTRY_STORAGE_KEY,
+} from '@/constants/quick-entries'
+
+function loadPinnedIds(): string[] {
+ try {
+ const stored = uni.getStorageSync(QUICK_ENTRY_STORAGE_KEY)
+ if (Array.isArray(stored) && stored.length > 0)
+ return stored.slice(0, QUICK_ENTRY_MAX)
+ }
+ catch {
+ // ignore storage read errors
+ }
+ return [...DEFAULT_QUICK_ENTRY_IDS]
+}
+
+function savePinnedIds(ids: string[]) {
+ uni.setStorageSync(QUICK_ENTRY_STORAGE_KEY, ids.slice(0, QUICK_ENTRY_MAX))
+}
+
+export function useQuickEntries() {
+ const pinnedIds = ref(loadPinnedIds())
+ const editorVisible = ref(false)
+
+ const pinnedEntries = computed(() => mapQuickEntryIds(pinnedIds.value))
+
+ const otherEntries = computed(() =>
+ QUICK_ENTRY_CATALOG.filter(item => !pinnedIds.value.includes(item.id)),
+ )
+
+ function openEditor() {
+ editorVisible.value = true
+ }
+
+ function closeEditor() {
+ editorVisible.value = false
+ }
+
+ function removeFromPinned(id: string) {
+ pinnedIds.value = pinnedIds.value.filter(itemId => itemId !== id)
+ savePinnedIds(pinnedIds.value)
+ }
+
+ function addToPinned(id: string) {
+ if (pinnedIds.value.includes(id))
+ return
+
+ if (pinnedIds.value.length >= QUICK_ENTRY_MAX) {
+ uni.showToast({ title: `最多添加${QUICK_ENTRY_MAX}个快捷入口`, icon: 'none' })
+ return
+ }
+
+ pinnedIds.value = [...pinnedIds.value, id]
+ savePinnedIds(pinnedIds.value)
+ }
+
+ return {
+ pinnedEntries,
+ otherEntries,
+ editorVisible,
+ openEditor,
+ closeEditor,
+ removeFromPinned,
+ addToPinned,
+ }
+}
diff --git a/src/pages.json b/src/pages.json
index 83c9f70..771d364 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -49,6 +49,18 @@
"navigationStyle": "custom"
}
},
+ {
+ "path": "pages/home-index/business-detail/index",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "pages/home-index/requirement-submit/index",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
{
"path": "pages/case-library/index",
"style": {
diff --git a/src/pages/Login/user-register-success/index.vue b/src/pages/Login/user-register-success/index.vue
index e98aa37..dd8c19f 100644
--- a/src/pages/Login/user-register-success/index.vue
+++ b/src/pages/Login/user-register-success/index.vue
@@ -25,6 +25,10 @@ onLoad((options) => {
}
if (type === 'loginFailed') {
pageType.value = 'loginFailed'
+ return
+ }
+ if (type === 'submitSuccess') {
+ pageType.value = 'submitSuccess'
}
})
diff --git a/src/pages/case-library/components/CaseCard.vue b/src/pages/case-library/components/CaseCard.vue
new file mode 100644
index 0000000..9e7747e
--- /dev/null
+++ b/src/pages/case-library/components/CaseCard.vue
@@ -0,0 +1,185 @@
+
+
+
+
+
+
+
+ {{ item.category }}
+
+
+
+
+
+
+
+ {{ item.title }}
+
+
+
+
+
+
+ 客户类型
+
+
+ {{ item.clientType }}
+
+
+
+
+ 所属行业
+
+
+ {{ item.industry }}
+
+
+
+
+ 规模
+
+
+ {{ item.scale }}
+
+
+
+
+
+
+ 项目周期
+
+
+ {{ item.cycle }}
+
+
+
+
+ 服务团队
+
+
+ {{ item.teamSize }}
+
+
+
+
+ 完成时间
+
+
+ {{ item.completedAt }}
+
+
+
+
+
+
+
+
diff --git a/src/pages/case-library/components/CaseFilterPanel.vue b/src/pages/case-library/components/CaseFilterPanel.vue
new file mode 100644
index 0000000..8f1cb6a
--- /dev/null
+++ b/src/pages/case-library/components/CaseFilterPanel.vue
@@ -0,0 +1,526 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ 行业
+
+
+
+ {{ item }}
+
+
+
+
+
+
+ 项目规模
+
+
+
+ {{ item }}
+
+
+
+
+
+
+ 完成时间
+
+
+
+ {{ item }}
+
+
+
+
+
+
+
+ {{ draft.dateRange.start || '开始时间' }}
+
+
+
+
+ —
+
+
+
+
+ {{ draft.dateRange.end || '结束时间' }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ tag.label }}
+
+
+ ×
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pages/case-library/components/LoadMoreFooter.vue b/src/pages/case-library/components/LoadMoreFooter.vue
new file mode 100644
index 0000000..b6784ba
--- /dev/null
+++ b/src/pages/case-library/components/LoadMoreFooter.vue
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
diff --git a/src/pages/case-library/index.vue b/src/pages/case-library/index.vue
index 707c630..350fcf9 100644
--- a/src/pages/case-library/index.vue
+++ b/src/pages/case-library/index.vue
@@ -1,41 +1,319 @@
-
-
- 案例库
-
-
- 功能开发中
-
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pages/home-index/business-detail/index.vue b/src/pages/home-index/business-detail/index.vue
new file mode 100644
index 0000000..6ef4aeb
--- /dev/null
+++ b/src/pages/home-index/business-detail/index.vue
@@ -0,0 +1,335 @@
+
+
+
+
+
+
+
+
+
+ 业务详情
+
+
+
+
+
+
+
+
+
+
+ {{ detail.title }}
+
+
+ {{ detail.subtitle }}
+
+
+
+
+
+
+ 服务类型
+
+
+
+
+
+ {{ type.label }}
+
+
+
+
+
+
+
+ {{ detail.contentTitle }}
+
+
+
+
+
+ ▶
+
+
+
+
+
+
+ {{ paragraph }}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pages/home-index/components/HomeFloatingActions.vue b/src/pages/home-index/components/HomeFloatingActions.vue
new file mode 100644
index 0000000..aecf5e3
--- /dev/null
+++ b/src/pages/home-index/components/HomeFloatingActions.vue
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+ +
+
+
+
+ 快捷提报
+
+
+
+
+
+
+
+
+ 客服中心
+
+
+
+
+
+
diff --git a/src/pages/home-index/components/ProjectCard.vue b/src/pages/home-index/components/ProjectCard.vue
index faa8545..9f4126d 100644
--- a/src/pages/home-index/components/ProjectCard.vue
+++ b/src/pages/home-index/components/ProjectCard.vue
@@ -1,5 +1,6 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+ 其他入口
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+
+
+
diff --git a/src/pages/home-index/components/ServiceCard.vue b/src/pages/home-index/components/ServiceCard.vue
index 61ddfc5..0e3d0b3 100644
--- a/src/pages/home-index/components/ServiceCard.vue
+++ b/src/pages/home-index/components/ServiceCard.vue
@@ -1,9 +1,18 @@
@@ -12,7 +21,9 @@ defineProps<{
:class="[
`service-card--${item.theme}`,
{ 'service-card--with-illus': item.illus },
+ { 'service-card--clickable': item.detailId },
]"
+ @tap="handleTap"
>
import AppTabBar from '@/components/AppTabBar.vue'
import { useGreeting } from '@/hooks/use-greeting'
-import type { ProjectItem, QuickEntryItem, ServiceItem } from '@/types/home'
+import { useQuickEntries } from '@/hooks/use-quick-entries'
+import type { ProjectItem, ServiceItem } from '@/types/home'
import headerBg from '@/static/icons/1.png'
import softwareIllus from '@/static/icons/software.png'
import hardwareIllus from '@/static/icons/hardware.png'
import iotIllus from '@/static/icons/iot.png'
import productionIllus from '@/static/icons/production.png'
+import HomeFloatingActions from './components/HomeFloatingActions.vue'
import ProjectCard from './components/ProjectCard.vue'
+import QuickEntryEditor from './components/QuickEntryEditor.vue'
import ServiceCard from './components/ServiceCard.vue'
const greeting = useGreeting()
+const {
+ pinnedEntries,
+ otherEntries,
+ editorVisible,
+ openEditor,
+ closeEditor,
+ removeFromPinned,
+ addToPinned,
+} = useQuickEntries()
const services: ServiceItem[] = [
{
@@ -19,6 +31,7 @@ const services: ServiceItem[] = [
desc: 'Web/小程序/APP/二次开发/桌面工具等',
theme: 'blue',
illus: softwareIllus,
+ detailId: 'software',
},
{
id: '2',
@@ -43,14 +56,6 @@ const services: ServiceItem[] = [
},
]
-const quickEntries: QuickEntryItem[] = [
- { id: '1', label: '项目中心', icon: '/static/icons/quick-project.png', bgColor: '#E8F0FF' },
- { id: '2', label: '快捷提报', icon: '/static/icons/quick-report.png', bgColor: '#E8FAF4' },
- { id: '3', label: '在线客服', icon: '/static/icons/quick-service.png', bgColor: '#F3E8FF' },
- { id: '4', label: '合同管理', icon: '/static/icons/quick-contract.png', bgColor: '#FEE2E2' },
- { id: '5', label: '财务管理', icon: '/static/icons/quick-finance.png', bgColor: '#E0F2FE' },
-]
-
const projects: ProjectItem[] = [
{
id: '1',
@@ -70,7 +75,7 @@ const projects: ProjectItem[] = [
progress: 65,
status: '进行中',
updateTime: '2026-8-13 11:04:12',
- tagTheme: 'peach',
+ tagTheme: 'orange',
},
]
@@ -146,13 +151,16 @@ const projects: ProjectItem[] = [
快捷入口
-
+
编辑
@@ -168,7 +176,7 @@ const projects: ProjectItem[] = [
-
+
@@ -361,6 +390,14 @@ const projects: ProjectItem[] = [
padding-top: 20rpx
}
+.home__sectionss {
+ margin-bottom: 20rpx;
+ width: 711.83rpx;
+ background: $color-bg-page;
+ border-radius: 20rpx;
+ padding-top: 20rpx
+}
+
.home__section--last {
margin-bottom: 0;
}
@@ -422,34 +459,52 @@ const projects: ProjectItem[] = [
.home__stats-row {
display: flex;
gap: 20rpx;
+ padding: 0 20rpx;
}
.home__stat-card {
display: flex;
flex: 1;
flex-direction: column;
- padding: 28rpx 24rpx;
+ align-items: center;
+ justify-content: center;
+ padding: 32rpx 24rpx;
border-radius: 16rpx;
+ text-align: center;
&--blue {
- background: $color-primary-light;
+ background: linear-gradient(180deg, #D3E1FC 0%, #FFFFFF 100%);
}
&--orange {
- background: $color-stat-orange-bg;
+ background: linear-gradient(180deg, #FFECE1 0%, #FFFFFF 100%);
}
}
.home__stat-value {
- font-size: 32rpx;
+ display: flex;
+ align-items: baseline;
+ justify-content: center;
+}
+
+.home__stat-num {
+ font-size: 56rpx;
font-weight: 700;
+ line-height: 1;
+ color: $color-text-primary;
+}
+
+.home__stat-unit {
+ margin-left: 4rpx;
+ font-size: 28rpx;
+ font-weight: 500;
color: $color-text-primary;
}
.home__stat-label {
- margin-top: 8rpx;
+ margin-top: 12rpx;
font-size: 24rpx;
- color: $color-text-secondary;
+ color: #333333;
}
.home__recent-title {
diff --git a/src/pages/home-index/requirement-submit/index.vue b/src/pages/home-index/requirement-submit/index.vue
new file mode 100644
index 0000000..4b836f8
--- /dev/null
+++ b/src/pages/home-index/requirement-submit/index.vue
@@ -0,0 +1,706 @@
+
+
+
+
+
+
+
+
+
+ 需求提报
+
+
+
+
+
+
+
+
+ 业务类型
+ *
+
+
+
+
+
+ {{ businessType || '选择下方推荐的服务或手动输入服务名称' }}
+
+
+ ▾
+
+
+
+
+ {{ option }}
+
+
+
+
+
+
+
+
+
+ 项目名称
+ *
+
+
+
+
+
+
+
+ 核心需求描述
+ *
+
+
+
+
+
+ {{ descLength }}/500字
+
+
+
+
+
+
+ 预算范围
+
+
+
+ {{ option }}
+
+
+
+
+
+
+ 预计开发周期
+
+
+
+
+
+
+
+
+ 用户名称
+
+
+
+
+
+
+ 用户手机号
+
+
+
+
+
+
+ 附件上传
+
+
+ 支持图片/文档/压缩包
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+ 添加附件
+
+
+
+
+
+
+
+
+
+ 补充备注
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/static/icons/PDF.png b/src/static/icons/PDF.png
new file mode 100644
index 0000000..59e6ccc
Binary files /dev/null and b/src/static/icons/PDF.png differ
diff --git a/src/static/icons/PNG.png b/src/static/icons/PNG.png
new file mode 100644
index 0000000..db045b2
Binary files /dev/null and b/src/static/icons/PNG.png differ
diff --git a/src/static/icons/X.png b/src/static/icons/X.png
new file mode 100644
index 0000000..cb66fdf
Binary files /dev/null and b/src/static/icons/X.png differ
diff --git a/src/static/icons/about.png b/src/static/icons/about.png
new file mode 100644
index 0000000..d69559b
Binary files /dev/null and b/src/static/icons/about.png differ
diff --git a/src/static/icons/add.png b/src/static/icons/add.png
new file mode 100644
index 0000000..8cdb3fa
Binary files /dev/null and b/src/static/icons/add.png differ
diff --git a/src/static/icons/address.png b/src/static/icons/address.png
new file mode 100644
index 0000000..a5ee37e
Binary files /dev/null and b/src/static/icons/address.png differ
diff --git a/src/static/icons/background.png b/src/static/icons/background.png
new file mode 100644
index 0000000..fd76f92
Binary files /dev/null and b/src/static/icons/background.png differ
diff --git a/src/static/icons/contract-list.png b/src/static/icons/contract-list.png
new file mode 100644
index 0000000..5e133de
Binary files /dev/null and b/src/static/icons/contract-list.png differ
diff --git a/src/static/icons/delete.png b/src/static/icons/delete.png
new file mode 100644
index 0000000..4eaba96
Binary files /dev/null and b/src/static/icons/delete.png differ
diff --git a/src/static/icons/feedback.png b/src/static/icons/feedback.png
new file mode 100644
index 0000000..cb03289
Binary files /dev/null and b/src/static/icons/feedback.png differ
diff --git a/src/static/icons/help.png b/src/static/icons/help.png
new file mode 100644
index 0000000..1fc1e12
Binary files /dev/null and b/src/static/icons/help.png differ
diff --git a/src/static/icons/icon-filter.svg b/src/static/icons/icon-filter.svg
new file mode 100644
index 0000000..88e95c9
--- /dev/null
+++ b/src/static/icons/icon-filter.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/static/icons/icon-float-service.png b/src/static/icons/icon-float-service.png
new file mode 100644
index 0000000..bc1dcd4
Binary files /dev/null and b/src/static/icons/icon-float-service.png differ
diff --git a/src/static/icons/icon-heart-filled.svg b/src/static/icons/icon-heart-filled.svg
new file mode 100644
index 0000000..767cbe6
--- /dev/null
+++ b/src/static/icons/icon-heart-filled.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/static/icons/icon-heart.svg b/src/static/icons/icon-heart.svg
new file mode 100644
index 0000000..fb99452
--- /dev/null
+++ b/src/static/icons/icon-heart.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/static/icons/icon-search.svg b/src/static/icons/icon-search.svg
new file mode 100644
index 0000000..48f333a
--- /dev/null
+++ b/src/static/icons/icon-search.svg
@@ -0,0 +1,4 @@
+
diff --git a/src/static/icons/invoice.png b/src/static/icons/invoice.png
new file mode 100644
index 0000000..4b1c158
Binary files /dev/null and b/src/static/icons/invoice.png differ
diff --git a/src/static/icons/new-card.png b/src/static/icons/new-card.png
new file mode 100644
index 0000000..239d179
Binary files /dev/null and b/src/static/icons/new-card.png differ
diff --git a/src/static/icons/qualification.png b/src/static/icons/qualification.png
new file mode 100644
index 0000000..aff141f
Binary files /dev/null and b/src/static/icons/qualification.png differ
diff --git a/src/static/icons/security.png b/src/static/icons/security.png
new file mode 100644
index 0000000..d647e4c
Binary files /dev/null and b/src/static/icons/security.png differ
diff --git a/src/static/icons/service-app.png b/src/static/icons/service-app.png
new file mode 100644
index 0000000..0a1d504
Binary files /dev/null and b/src/static/icons/service-app.png differ
diff --git a/src/static/icons/service-desktop.png b/src/static/icons/service-desktop.png
new file mode 100644
index 0000000..767df79
Binary files /dev/null and b/src/static/icons/service-desktop.png differ
diff --git a/src/static/icons/service-mini.png b/src/static/icons/service-mini.png
new file mode 100644
index 0000000..8599f7c
Binary files /dev/null and b/src/static/icons/service-mini.png differ
diff --git a/src/static/icons/service-secondary.png b/src/static/icons/service-secondary.png
new file mode 100644
index 0000000..f25025a
Binary files /dev/null and b/src/static/icons/service-secondary.png differ
diff --git a/src/static/icons/service-secondary.svg b/src/static/icons/service-secondary.svg
new file mode 100644
index 0000000..523e574
--- /dev/null
+++ b/src/static/icons/service-secondary.svg
@@ -0,0 +1,4 @@
+
diff --git a/src/static/icons/service-web.png b/src/static/icons/service-web.png
new file mode 100644
index 0000000..3e26042
Binary files /dev/null and b/src/static/icons/service-web.png differ
diff --git a/src/static/icons/tab-case-active.png b/src/static/icons/tab-case-active.png
new file mode 100644
index 0000000..df12d7f
Binary files /dev/null and b/src/static/icons/tab-case-active.png differ
diff --git a/src/static/icons/tab-case.png b/src/static/icons/tab-case.png
new file mode 100644
index 0000000..97108cb
Binary files /dev/null and b/src/static/icons/tab-case.png differ
diff --git a/src/static/icons/tab-case.svg b/src/static/icons/tab-case.svg
deleted file mode 100644
index 4117081..0000000
--- a/src/static/icons/tab-case.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-
diff --git a/src/static/icons/tab-home-active.png b/src/static/icons/tab-home-active.png
new file mode 100644
index 0000000..742ea26
Binary files /dev/null and b/src/static/icons/tab-home-active.png differ
diff --git a/src/static/icons/tab-home.png b/src/static/icons/tab-home.png
new file mode 100644
index 0000000..d579b7c
Binary files /dev/null and b/src/static/icons/tab-home.png differ
diff --git a/src/static/icons/tab-home.svg b/src/static/icons/tab-home.svg
deleted file mode 100644
index 81a2e0a..0000000
--- a/src/static/icons/tab-home.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
diff --git a/src/static/icons/tab-message-active.png b/src/static/icons/tab-message-active.png
new file mode 100644
index 0000000..4ff349a
Binary files /dev/null and b/src/static/icons/tab-message-active.png differ
diff --git a/src/static/icons/tab-message.png b/src/static/icons/tab-message.png
new file mode 100644
index 0000000..22230b0
Binary files /dev/null and b/src/static/icons/tab-message.png differ
diff --git a/src/static/icons/tab-message.svg b/src/static/icons/tab-message.svg
deleted file mode 100644
index c3b179c..0000000
--- a/src/static/icons/tab-message.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-
diff --git a/src/static/icons/tab-messages.png b/src/static/icons/tab-messages.png
new file mode 100644
index 0000000..e5b05c4
Binary files /dev/null and b/src/static/icons/tab-messages.png differ
diff --git a/src/static/icons/tab-personal-active.png b/src/static/icons/tab-personal-active.png
new file mode 100644
index 0000000..28f289a
Binary files /dev/null and b/src/static/icons/tab-personal-active.png differ
diff --git a/src/static/icons/tab-personal.png b/src/static/icons/tab-personal.png
new file mode 100644
index 0000000..85d6eea
Binary files /dev/null and b/src/static/icons/tab-personal.png differ
diff --git a/src/static/icons/tab-personal.svg b/src/static/icons/tab-personal.svg
deleted file mode 100644
index cd0d641..0000000
--- a/src/static/icons/tab-personal.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
diff --git a/src/static/icons/tab-personals.png b/src/static/icons/tab-personals.png
new file mode 100644
index 0000000..7fad6cd
Binary files /dev/null and b/src/static/icons/tab-personals.png differ
diff --git a/src/static/icons/tab-project-active.png b/src/static/icons/tab-project-active.png
new file mode 100644
index 0000000..7d22a7f
Binary files /dev/null and b/src/static/icons/tab-project-active.png differ
diff --git a/src/static/icons/tab-project.png b/src/static/icons/tab-project.png
new file mode 100644
index 0000000..c218626
Binary files /dev/null and b/src/static/icons/tab-project.png differ
diff --git a/src/static/icons/tab-project.svg b/src/static/icons/tab-project.svg
deleted file mode 100644
index 3600b24..0000000
--- a/src/static/icons/tab-project.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-
diff --git a/src/types/business-detail.ts b/src/types/business-detail.ts
new file mode 100644
index 0000000..9212ea1
--- /dev/null
+++ b/src/types/business-detail.ts
@@ -0,0 +1,15 @@
+export interface ServiceTypeItem {
+ id: string
+ label: string
+ icon: string
+}
+
+export interface BusinessDetailContent {
+ id: string
+ title: string
+ subtitle: string
+ icon: string
+ serviceTypes: ServiceTypeItem[]
+ contentTitle: string
+ contentSections: string[]
+}
diff --git a/src/types/case-library.ts b/src/types/case-library.ts
new file mode 100644
index 0000000..12da75f
--- /dev/null
+++ b/src/types/case-library.ts
@@ -0,0 +1,25 @@
+export type CaseCategory = '全部' | '互联网软件' | '硬件电路' | '物联网全案' | '生产制造'
+
+export interface CaseItem {
+ id: string
+ title: string
+ category: Exclude
+ cover: string
+ clientType: string
+ industry: string
+ scale: string
+ cycle: string
+ teamSize: string
+ completedAt: string
+ favorite?: boolean
+}
+
+export interface CaseFilterValues {
+ industries: string[]
+ scales: string[]
+ timeRanges: string[]
+ dateRange: {
+ start: string
+ end: string
+ }
+}
diff --git a/src/types/home.ts b/src/types/home.ts
index 073a6a8..baade56 100644
--- a/src/types/home.ts
+++ b/src/types/home.ts
@@ -4,6 +4,7 @@ export interface ServiceItem {
desc: string
theme: 'blue' | 'green' | 'pink' | 'orange'
illus?: string
+ detailId?: string
}
export interface QuickEntryItem {
@@ -21,5 +22,5 @@ export interface ProjectItem {
progress: number
status: string
updateTime: string
- tagTheme?: 'orange' | 'peach'
+ tagTheme?: 'orange'
}
diff --git a/src/types/result-page.ts b/src/types/result-page.ts
index ecbd74f..347f7a2 100644
--- a/src/types/result-page.ts
+++ b/src/types/result-page.ts
@@ -1,4 +1,4 @@
-export type ResultPageType = 'register' | 'resetPassword' | 'loginFailed'
+export type ResultPageType = 'register' | 'resetPassword' | 'loginFailed' | 'submitSuccess'
export interface ResultPageConfig {
title: string
@@ -26,6 +26,12 @@ export const RESULT_PAGE_CONFIG: Record = {
icon: '/static/icons/icon-login-failed.svg',
redirectUrl: '/pages/Login/user-register/index',
},
+ submitSuccess: {
+ title: '提报成功',
+ subtitleTarget: '首页',
+ icon: '/static/icons/icon-register-success.png',
+ redirectUrl: '/pages/home-index/index',
+ },
}
export const RESULT_PAGE_ROUTE = '/pages/Login/user-register-success/index'
diff --git a/src/utils/case-filter.ts b/src/utils/case-filter.ts
new file mode 100644
index 0000000..c7ded32
--- /dev/null
+++ b/src/utils/case-filter.ts
@@ -0,0 +1,147 @@
+import type { CaseFilterValues, CaseItem } from '@/types/case-library'
+
+function parseScaleValue(scale: string): number {
+ const match = scale.match(/(\d+)/)
+ return match ? Number(match[1]) : 0
+}
+
+function matchScaleRange(scale: string, range: string): boolean {
+ const value = parseScaleValue(scale)
+
+ switch (range) {
+ case '50万以下':
+ return value < 50
+ case '50-100万':
+ return value >= 50 && value <= 100
+ case '100-300万':
+ return value > 100 && value <= 300
+ case '300-500万':
+ return value > 300 && value <= 500
+ case '500万以上':
+ return value > 500
+ default:
+ return true
+ }
+}
+
+function parseDate(dateStr: string): Date | null {
+ if (!dateStr)
+ return null
+
+ const [year, month, day] = dateStr.split('/').map(Number)
+ if (!year || !month || !day)
+ return null
+
+ return new Date(year, month - 1, day)
+}
+
+function matchTimeRange(completedAt: string, range: string, now = new Date()): boolean {
+ const date = parseDate(completedAt)
+ if (!date)
+ return false
+
+ const monthsMap: Record = {
+ 近3个月: 3,
+ 近半年: 6,
+ 近一年: 12,
+ }
+ const months = monthsMap[range]
+ if (!months)
+ return true
+
+ const start = new Date(now)
+ start.setMonth(start.getMonth() - months)
+
+ return date >= start && date <= now
+}
+
+function matchDateRange(completedAt: string, start: string, end: string): boolean {
+ const date = parseDate(completedAt)
+ const startDate = parseDate(start)
+ const endDate = parseDate(end)
+
+ if (!date || !startDate || !endDate)
+ return true
+
+ return date >= startDate && date <= endDate
+}
+
+export function cloneCaseFilter(filter: CaseFilterValues): CaseFilterValues {
+ return {
+ industries: [...filter.industries],
+ scales: [...filter.scales],
+ timeRanges: [...filter.timeRanges],
+ dateRange: {
+ start: filter.dateRange.start,
+ end: filter.dateRange.end,
+ },
+ }
+}
+
+export function getSelectedFilterTags(filter: CaseFilterValues): Array<{ key: string, label: string }> {
+ const tags: Array<{ key: string, label: string }> = []
+
+ filter.industries.forEach((item) => {
+ tags.push({ key: `industry:${item}`, label: item })
+ })
+
+ filter.scales.forEach((item) => {
+ tags.push({ key: `scale:${item}`, label: item })
+ })
+
+ filter.timeRanges.forEach((item) => {
+ tags.push({ key: `time:${item}`, label: item })
+ })
+
+ if (filter.dateRange.start && filter.dateRange.end) {
+ tags.push({
+ key: 'date-range',
+ label: `${filter.dateRange.start}-${filter.dateRange.end}`,
+ })
+ }
+
+ return tags
+}
+
+export function removeFilterTag(filter: CaseFilterValues, key: string): CaseFilterValues {
+ const next = cloneCaseFilter(filter)
+
+ if (key.startsWith('industry:')) {
+ const value = key.replace('industry:', '')
+ next.industries = next.industries.filter(item => item !== value)
+ }
+
+ if (key.startsWith('scale:')) {
+ const value = key.replace('scale:', '')
+ next.scales = next.scales.filter(item => item !== value)
+ }
+
+ if (key.startsWith('time:')) {
+ const value = key.replace('time:', '')
+ next.timeRanges = next.timeRanges.filter(item => item !== value)
+ }
+
+ if (key === 'date-range') {
+ next.dateRange = { start: '', end: '' }
+ }
+
+ return next
+}
+
+export function matchCaseFilter(item: CaseItem, filter: CaseFilterValues): boolean {
+ if (filter.industries.length > 0 && !filter.industries.includes(item.industry))
+ return false
+
+ if (filter.scales.length > 0 && !filter.scales.some(range => matchScaleRange(item.scale, range)))
+ return false
+
+ if (filter.timeRanges.length > 0 && !filter.timeRanges.some(range => matchTimeRange(item.completedAt, range)))
+ return false
+
+ if (filter.dateRange.start && filter.dateRange.end) {
+ if (!matchDateRange(item.completedAt, filter.dateRange.start, filter.dateRange.end))
+ return false
+ }
+
+ return true
+}
diff --git a/src/utils/navigate-back.ts b/src/utils/navigate-back.ts
new file mode 100644
index 0000000..c680126
--- /dev/null
+++ b/src/utils/navigate-back.ts
@@ -0,0 +1,15 @@
+export function navigateBackWithFallback(fallbackUrl: string) {
+ const pages = getCurrentPages()
+
+ if (pages.length > 1) {
+ uni.navigateBack()
+ return
+ }
+
+ uni.redirectTo({
+ url: fallbackUrl,
+ fail: () => {
+ uni.reLaunch({ url: fallbackUrl })
+ },
+ })
+}