From f5d634bbaf80ae7998dc72707a5d11964c807289 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E4=BC=8A=E5=B8=86?= Date: Mon, 14 Sep 2026 10:32:21 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E6=B6=88=E6=81=AF=E4=B8=AD=E5=BF=83?= =?UTF-8?q?=E5=92=8C=E6=A1=88=E4=BE=8B=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/constants/case-detail.ts | 34 + src/constants/customer-service.ts | 18 + src/constants/message-center.ts | 29 + src/constants/project-center.ts | 44 ++ src/constants/project-detail.ts | 72 ++ src/constants/status-notification.ts | 25 + src/constants/system-notification.ts | 24 + src/hooks/use-case-favorites.ts | 73 ++ src/pages.json | 36 + .../components/CaseFilterPanel.vue | 8 +- src/pages/case-library/detail/index.vue | 345 +++++++++ src/pages/case-library/favorites/index.vue | 466 ++++++++++++ src/pages/case-library/index.vue | 39 +- .../components/HomeFloatingActions.vue | 5 +- .../message-center/components/MessageItem.vue | 106 +++ .../components/ChatMessage.vue | 112 +++ .../message-center/customer-service/index.vue | 299 ++++++++ src/pages/message-center/index.vue | 113 ++- .../components/StatusNotificationItem.vue | 96 +++ .../status-notification/index.vue | 182 +++++ .../system-notification/index.vue | 182 +++++ .../components/ProjectCenterCard.vue | 173 +++++ src/pages/project-center/detail/index.vue | 703 ++++++++++++++++++ src/pages/project-center/index.vue | 248 +++++- src/static/icons/icon-chat-add.png | Bin 0 -> 665 bytes src/static/icons/icon-chat-camera.png | Bin 0 -> 1737 bytes src/static/icons/icon-chat-file.png | Bin 0 -> 1458 bytes src/static/icons/icon-chat-photo.png | Bin 0 -> 1446 bytes src/static/icons/icon-chat-voice.png | Bin 0 -> 1204 bytes src/static/icons/icon-filter.svg | 4 +- src/static/icons/icon-message-service.png | Bin 0 -> 3423 bytes src/static/icons/icon-message-system.png | Bin 0 -> 3267 bytes src/static/icons/icon-message-workorder.png | Bin 0 -> 3398 bytes src/static/icons/添 加.png | Bin 0 -> 665 bytes src/types/case-library.ts | 14 + src/types/customer-service.ts | 9 + src/types/message-center.ts | 11 + src/types/project-center.ts | 16 + src/types/project-detail.ts | 35 + src/types/status-notification.ts | 7 + src/utils/case-filter.ts | 4 +- 41 files changed, 3484 insertions(+), 48 deletions(-) create mode 100644 src/constants/case-detail.ts create mode 100644 src/constants/customer-service.ts create mode 100644 src/constants/message-center.ts create mode 100644 src/constants/project-center.ts create mode 100644 src/constants/project-detail.ts create mode 100644 src/constants/status-notification.ts create mode 100644 src/constants/system-notification.ts create mode 100644 src/hooks/use-case-favorites.ts create mode 100644 src/pages/case-library/detail/index.vue create mode 100644 src/pages/case-library/favorites/index.vue create mode 100644 src/pages/message-center/components/MessageItem.vue create mode 100644 src/pages/message-center/customer-service/components/ChatMessage.vue create mode 100644 src/pages/message-center/customer-service/index.vue create mode 100644 src/pages/message-center/status-notification/components/StatusNotificationItem.vue create mode 100644 src/pages/message-center/status-notification/index.vue create mode 100644 src/pages/message-center/system-notification/index.vue create mode 100644 src/pages/project-center/components/ProjectCenterCard.vue create mode 100644 src/pages/project-center/detail/index.vue create mode 100644 src/static/icons/icon-chat-add.png create mode 100644 src/static/icons/icon-chat-camera.png create mode 100644 src/static/icons/icon-chat-file.png create mode 100644 src/static/icons/icon-chat-photo.png create mode 100644 src/static/icons/icon-chat-voice.png create mode 100644 src/static/icons/icon-message-service.png create mode 100644 src/static/icons/icon-message-system.png create mode 100644 src/static/icons/icon-message-workorder.png create mode 100644 src/static/icons/添 加.png create mode 100644 src/types/customer-service.ts create mode 100644 src/types/message-center.ts create mode 100644 src/types/project-center.ts create mode 100644 src/types/project-detail.ts create mode 100644 src/types/status-notification.ts diff --git a/src/constants/case-detail.ts b/src/constants/case-detail.ts new file mode 100644 index 0000000..33ef350 --- /dev/null +++ b/src/constants/case-detail.ts @@ -0,0 +1,34 @@ +import { CASE_LIBRARY_LIST } from '@/constants/case-library' +import type { CaseDetail } from '@/types/case-library' + +const SHARED_BACKGROUND = '随着我国城镇化进程不断加快,园区管理面临着从传统粗放式管理向精细化、智能化管理转型的迫切需求。在"数字中国"战略背景下,各地园区纷纷探索通过信息化手段提升运营效率、优化资源配置、改善企业服务体验。' + +const SHARED_PAIN_POINTS = '传统园区管理方式依赖人工巡检和纸质记录,信息孤岛严重,各部门数据无法互通,导致管理效率低下。企业服务响应慢,缺乏统一的服务入口,企业诉求难以快速传达和处理。能耗管理粗放,无法实时监控和分析,造成资源浪费。' + +const SHARED_REQUIREMENT = '建设一套集园区管理、企业服务、数据分析于一体的综合管理平台,实现园区运营的数字化、智能化。平台需支持多端访问,包括Web管理端、移动端APP,满足不同角色的使用需求。' + +const SHARED_DELIVERABLES = '交付园区综合管理平台一套,包含Web管理端、移动端APP、数据可视化大屏,并提供完整的源代码、技术文档、用户手册及一年免费运维服务。' + +const DEFAULT_ATTACHMENTS = [ + { id: '1', name: '需求文档.pdf', icon: '/static/icons/PDF.png' }, + { id: '2', name: '系统....pdf', icon: '/static/icons/PDF.png' }, + { id: '3', name: '参考图.png', icon: '/static/icons/PNG.png' }, +] + +const CASE_DETAIL_MAP: Record = Object.fromEntries( + CASE_LIBRARY_LIST.map(item => [ + item.id, + { + ...item, + background: SHARED_BACKGROUND, + painPoints: SHARED_PAIN_POINTS, + requirement: SHARED_REQUIREMENT, + deliverables: SHARED_DELIVERABLES, + attachments: DEFAULT_ATTACHMENTS, + }, + ]), +) + +export function getCaseDetail(id: string): CaseDetail | null { + return CASE_DETAIL_MAP[id] || null +} diff --git a/src/constants/customer-service.ts b/src/constants/customer-service.ts new file mode 100644 index 0000000..8cf8433 --- /dev/null +++ b/src/constants/customer-service.ts @@ -0,0 +1,18 @@ +import type { ChatMessage } from '@/types/customer-service' + +export const CUSTOMER_SERVICE_MESSAGES: ChatMessage[] = [ + { + id: '1', + role: 'user', + nickname: '昵称', + content: '怎么购买?怎么购买?', + avatar: '/static/icons/hi.png', + }, + { + id: '2', + role: 'service', + nickname: '昵称', + content: '怎么购买?怎么购买?', + avatar: '/static/icons/quick-service.png', + }, +] diff --git a/src/constants/message-center.ts b/src/constants/message-center.ts new file mode 100644 index 0000000..d6003b3 --- /dev/null +++ b/src/constants/message-center.ts @@ -0,0 +1,29 @@ +import type { MessageItem } from '@/types/message-center' + +export const MESSAGE_LIST: MessageItem[] = [ + { + id: '1', + type: 'service', + icon: '/static/icons/icon-message-service.png', + title: '在线客服', + preview: '您好,请问有什么可以帮您的?', + time: '刚刚', + unread: true, + }, + { + id: '2', + type: 'workorder', + icon: '/static/icons/icon-message-workorder.png', + title: '工单状态通知', + preview: '您的「社区康养服务系统」项目已进入开发阶段,请关注进度', + time: '10:23', + }, + { + id: '3', + type: 'system', + icon: '/static/icons/icon-message-system.png', + title: '系统通知', + preview: '平台将于2026年7月31日00:00:00进行系统维护', + time: '昨天', + }, +] diff --git a/src/constants/project-center.ts b/src/constants/project-center.ts new file mode 100644 index 0000000..c1191d7 --- /dev/null +++ b/src/constants/project-center.ts @@ -0,0 +1,44 @@ +import type { ProjectCategory, ProjectCenterItem } from '@/types/project-center' + +export const PROJECT_CATEGORIES: ProjectCategory[] = [ + '全部', + '互联网软件', + '硬件电路', + '物联网全案', + '生产制造', +] + +export const PROJECT_CENTER_LIST: ProjectCenterItem[] = [ + { + id: '1', + title: '社区康养智能服务系统', + category: '互联网软件', + projectNo: '20260813RJ251545', + status: '进行中', + industry: '医疗健康', + scale: '320万', + completedAt: '2026/8/10', + progress: 65, + updateTime: '2026-8-13 11:04:12', + }, + { + id: '2', + title: '社区康养智能服务系统', + category: '生产制造', + projectNo: '20260813RJ251545', + status: '待立项', + industry: '电商零售', + scale: '500万', + completedAt: '2026/3/8', + }, + { + id: '3', + title: '社区康养智能服务系统', + category: '互联网软件', + projectNo: '20260813RJ251545', + status: '售后中', + industry: '医疗健康', + scale: '320万', + completedAt: '2026/6/15', + }, +] diff --git a/src/constants/project-detail.ts b/src/constants/project-detail.ts new file mode 100644 index 0000000..6341e98 --- /dev/null +++ b/src/constants/project-detail.ts @@ -0,0 +1,72 @@ +import { PROJECT_CENTER_LIST } from '@/constants/project-center' +import type { ProjectDetail } from '@/types/project-detail' + +const DEFAULT_STEPS = [ + { + id: '1', + title: '需求确认', + status: 'done' as const, + time: '2026-8-13 11:04:12', + }, + { + id: '2', + title: '原型设计', + status: 'done' as const, + time: '2026-8-13 11:04:12', + }, + { + id: '3', + title: '开发实现', + status: 'active' as const, + statusText: '进行中', + }, + { + id: '4', + title: '测试验收', + status: 'pending' as const, + statusText: '待开始', + }, + { + id: '5', + title: '项目交付', + status: 'pending' as const, + statusText: '待开始', + }, +] + +const DEFAULT_TEAM = [ + { id: '1', name: '张三', role: '项目经理' }, + { id: '2', name: '张三', role: '项目经理' }, + { id: '3', name: '张三', role: '项目经理' }, + { id: '4', name: '张三', role: '项目经理' }, +] + +const DEFAULT_FILES = [ + { id: '1', name: '需求文档.pdf', icon: '/static/icons/PDF.png' }, + { id: '2', name: '系统....pdf', icon: '/static/icons/PDF.png' }, + { id: '3', name: '参考图.png', icon: '/static/icons/PNG.png' }, +] + +function buildDetail(item: typeof PROJECT_CENTER_LIST[number]): ProjectDetail { + const progress = item.progress ?? 0 + + return { + ...item, + progressStartTime: '2026-8-17', + progressEndTime: '2026-8-17', + steps: DEFAULT_STEPS.map(step => ({ ...step })), + team: DEFAULT_TEAM.map(member => ({ ...member })), + files: DEFAULT_FILES.map(file => ({ ...file })), + financeSummary: '合同金额已确认,当前处于开发阶段付款节点,发票与回款记录可在后台查看。', + afterSalesSummary: '项目交付后将提供一年免费运维服务,支持 7×24 小时远程技术支持与故障响应。', + progress, + } +} + +const PROJECT_DETAIL_MAP: Record = Object.fromEntries( + PROJECT_CENTER_LIST.map(item => [item.id, buildDetail(item)]), +) + +export function getProjectDetail(id: string): ProjectDetail | null { + return PROJECT_DETAIL_MAP[id] || null +} diff --git a/src/constants/status-notification.ts b/src/constants/status-notification.ts new file mode 100644 index 0000000..c80a51c --- /dev/null +++ b/src/constants/status-notification.ts @@ -0,0 +1,25 @@ +import type { StatusNotificationItem } from '@/types/status-notification' + +export const STATUS_NOTIFICATION_ICON = '/static/icons/icon-message-workorder.png' + +export const STATUS_NOTIFICATION_LIST: StatusNotificationItem[] = [ + { + id: '1', + title: '项目待立项确认', + preview: '您的需求已收到,等待确认立项,请留意后续进展', + time: '刚刚', + unread: true, + }, + { + id: '2', + title: '合同生效', + preview: '您的合同已正式生效 合同编号 xxxx 已开始生效,可随时查看详情及履约进度', + time: '10:23', + }, + { + id: '3', + title: '您有一笔新账单待支付', + preview: '账单金额 ¥xxx,请尽快完成付款,以免影响服务', + time: '昨天', + }, +] diff --git a/src/constants/system-notification.ts b/src/constants/system-notification.ts new file mode 100644 index 0000000..6315628 --- /dev/null +++ b/src/constants/system-notification.ts @@ -0,0 +1,24 @@ +import type { StatusNotificationItem } from '@/types/status-notification' + +export const SYSTEM_NOTIFICATION_ICON = '/static/icons/icon-message-system.png' + +export const SYSTEM_NOTIFICATION_LIST: StatusNotificationItem[] = [ + { + id: '1', + title: '系统通知', + preview: '平台将于2026年7月31日00:00:00进行系统维护', + time: '昨天', + }, + { + id: '2', + title: '系统通知', + preview: '平台将于2026年7月31日00:00:00进行系统维护', + time: '昨天', + }, + { + id: '3', + title: '系统通知', + preview: '平台将于2026年7月31日00:00:00进行系统维护', + time: '昨天', + }, +] diff --git a/src/hooks/use-case-favorites.ts b/src/hooks/use-case-favorites.ts new file mode 100644 index 0000000..338295e --- /dev/null +++ b/src/hooks/use-case-favorites.ts @@ -0,0 +1,73 @@ +import { computed, ref } from 'vue' +import { CASE_LIBRARY_LIST } from '@/constants/case-library' +import type { CaseItem } from '@/types/case-library' + +export const CASE_FAVORITES_STORAGE_KEY = 'case-favorites' + +function getDefaultFavoriteIds(): string[] { + return CASE_LIBRARY_LIST + .filter(item => item.favorite) + .map(item => item.id) +} + +function loadFavoriteIds(): string[] { + try { + const stored = uni.getStorageSync(CASE_FAVORITES_STORAGE_KEY) + if (Array.isArray(stored)) + return stored + } + catch { + // ignore storage read errors + } + + return getDefaultFavoriteIds() +} + +function saveFavoriteIds(ids: string[]) { + uni.setStorageSync(CASE_FAVORITES_STORAGE_KEY, ids) +} + +const favoriteIds = ref(loadFavoriteIds()) + +export function useCaseFavorites() { + const favoriteCases = computed(() => + CASE_LIBRARY_LIST + .filter(item => favoriteIds.value.includes(item.id)) + .map(item => ({ ...item, favorite: true })), + ) + + function syncFavoriteIds() { + favoriteIds.value = loadFavoriteIds() + } + + function isFavorite(id: string) { + return favoriteIds.value.includes(id) + } + + function toggleFavorite(id: string) { + if (favoriteIds.value.includes(id)) { + favoriteIds.value = favoriteIds.value.filter(itemId => itemId !== id) + } + else { + favoriteIds.value = [...favoriteIds.value, id] + } + + saveFavoriteIds(favoriteIds.value) + } + + function applyFavoritesToList(list: CaseItem[]): CaseItem[] { + return list.map(item => ({ + ...item, + favorite: favoriteIds.value.includes(item.id), + })) + } + + return { + favoriteIds, + favoriteCases, + syncFavoriteIds, + isFavorite, + toggleFavorite, + applyFavoritesToList, + } +} diff --git a/src/pages.json b/src/pages.json index 771d364..3772666 100644 --- a/src/pages.json +++ b/src/pages.json @@ -67,18 +67,54 @@ "navigationStyle": "custom" } }, + { + "path": "pages/case-library/detail/index", + "style": { + "navigationStyle": "custom" + } + }, + { + "path": "pages/case-library/favorites/index", + "style": { + "navigationStyle": "custom" + } + }, { "path": "pages/message-center/index", "style": { "navigationStyle": "custom" } }, + { + "path": "pages/message-center/customer-service/index", + "style": { + "navigationStyle": "custom" + } + }, + { + "path": "pages/message-center/status-notification/index", + "style": { + "navigationStyle": "custom" + } + }, + { + "path": "pages/message-center/system-notification/index", + "style": { + "navigationStyle": "custom" + } + }, { "path": "pages/project-center/index", "style": { "navigationStyle": "custom" } }, + { + "path": "pages/project-center/detail/index", + "style": { + "navigationStyle": "custom" + } + }, { "path": "pages/personal-center/index", "style": { diff --git a/src/pages/case-library/components/CaseFilterPanel.vue b/src/pages/case-library/components/CaseFilterPanel.vue index 8f1cb6a..8a95a7e 100644 --- a/src/pages/case-library/components/CaseFilterPanel.vue +++ b/src/pages/case-library/components/CaseFilterPanel.vue @@ -6,7 +6,9 @@ import { CASE_FILTER_TIME_RANGES, DEFAULT_CASE_FILTER, } from '@/constants/case-library' -import type { CaseFilterValues, CaseItem } from '@/types/case-library' +import type { CaseFilterValues } from '@/types/case-library' +import type { CaseFilterTarget } from '@/utils/case-filter' +import filterIcon from '@/static/icons/icon-filter.svg' import { cloneCaseFilter, getSelectedFilterTags, @@ -16,7 +18,7 @@ import { const props = defineProps<{ visible: boolean - cases: CaseItem[] + cases: CaseFilterTarget[] value: CaseFilterValues }>() @@ -152,7 +154,7 @@ function handleConfirm() { diff --git a/src/pages/case-library/detail/index.vue b/src/pages/case-library/detail/index.vue new file mode 100644 index 0000000..0b56a02 --- /dev/null +++ b/src/pages/case-library/detail/index.vue @@ -0,0 +1,345 @@ + + + + + diff --git a/src/pages/case-library/favorites/index.vue b/src/pages/case-library/favorites/index.vue new file mode 100644 index 0000000..6b39b6d --- /dev/null +++ b/src/pages/case-library/favorites/index.vue @@ -0,0 +1,466 @@ + + + + + diff --git a/src/pages/case-library/index.vue b/src/pages/case-library/index.vue index 350fcf9..07ba4c2 100644 --- a/src/pages/case-library/index.vue +++ b/src/pages/case-library/index.vue @@ -1,6 +1,8 @@