406 lines
14 KiB
TypeScript
406 lines
14 KiB
TypeScript
import type { BusinessType, PageResult } from '@/types/api'
|
||
import type { Case } from '@/types/business/cases'
|
||
import type {
|
||
Address,
|
||
ChangePasswordParams,
|
||
Feedback,
|
||
FavoritesQuery,
|
||
HelpFaqGroup,
|
||
ListQuery,
|
||
Profile,
|
||
Qualification,
|
||
QualificationInput,
|
||
} from '@/types/business/profile'
|
||
|
||
// TODO(api): 待接口文档到位后,将以下 mock 替换为 request<T> 调用(页面 → store → api 数据流不变)
|
||
|
||
const MOCK_PROFILE: Profile = {
|
||
nickname: '王永志',
|
||
phone: '186****618',
|
||
email: 'yongzh******4@163.com',
|
||
passwordModifiedAt: '15天前',
|
||
}
|
||
|
||
export function getProfile(): Promise<Profile> {
|
||
return Promise.resolve({ ...MOCK_PROFILE })
|
||
}
|
||
|
||
export function updateNickname(name: string): Promise<Profile> {
|
||
MOCK_PROFILE.nickname = name
|
||
return Promise.resolve({ ...MOCK_PROFILE })
|
||
}
|
||
|
||
export function changePassword(params: ChangePasswordParams): Promise<void> {
|
||
MOCK_PROFILE.passwordModifiedAt = '刚刚'
|
||
void params
|
||
return Promise.resolve()
|
||
}
|
||
|
||
export function bindPhone(phone: string, code: string): Promise<Profile> {
|
||
void code
|
||
MOCK_PROFILE.phone = phone
|
||
return Promise.resolve({ ...MOCK_PROFILE })
|
||
}
|
||
|
||
export function bindEmail(email: string, code: string): Promise<Profile> {
|
||
void code
|
||
MOCK_PROFILE.email = email
|
||
return Promise.resolve({ ...MOCK_PROFILE })
|
||
}
|
||
|
||
export function unbindEmail(): Promise<Profile> {
|
||
MOCK_PROFILE.email = ''
|
||
return Promise.resolve({ ...MOCK_PROFILE })
|
||
}
|
||
|
||
export function verifyIdentity(phone: string, code: string): Promise<void> {
|
||
void phone
|
||
void code
|
||
return Promise.resolve()
|
||
}
|
||
|
||
export function deleteAccount(): Promise<void> {
|
||
return Promise.resolve()
|
||
}
|
||
|
||
const MOCK_ADDRESSES: Address[] = [
|
||
{
|
||
id: 'addr-1',
|
||
receiverName: '王永志',
|
||
phone: '18556669516',
|
||
region: '山东省日照市东港区',
|
||
detailAddress: '凌云购物广场三楼',
|
||
isDefault: true,
|
||
},
|
||
{
|
||
id: 'addr-2',
|
||
receiverName: '王永志',
|
||
phone: '18556669516',
|
||
region: '山东省日照市东港区',
|
||
detailAddress: '海曲东路 12 号研发中心 A 座 8 层',
|
||
isDefault: false,
|
||
},
|
||
{
|
||
id: 'addr-3',
|
||
receiverName: '李晓婷',
|
||
phone: '13863331234',
|
||
region: '山东省青岛市市南区',
|
||
detailAddress: '香港中路 76 号 A 座 18 层',
|
||
isDefault: false,
|
||
},
|
||
{
|
||
id: 'addr-4',
|
||
receiverName: '王永志',
|
||
phone: '18556669516',
|
||
region: '山东省济南市历下区',
|
||
detailAddress: '经十路 9999 号舜耕大厦 12 层',
|
||
isDefault: false,
|
||
},
|
||
]
|
||
|
||
function paginate<T>(list: T[], query: ListQuery): PageResult<T> {
|
||
const start = (query.page - 1) * query.pageSize
|
||
return {
|
||
list: list.slice(start, start + query.pageSize),
|
||
total: list.length,
|
||
}
|
||
}
|
||
|
||
export function getAddresses(query: ListQuery): Promise<PageResult<Address>> {
|
||
return Promise.resolve(paginate(MOCK_ADDRESSES, query))
|
||
}
|
||
|
||
export function createAddress(input: Omit<Address, 'id' | 'isDefault'>): Promise<Address> {
|
||
const created: Address = {
|
||
...input,
|
||
id: `addr-${Date.now()}`,
|
||
isDefault: MOCK_ADDRESSES.length === 0,
|
||
}
|
||
MOCK_ADDRESSES.push(created)
|
||
return Promise.resolve({ ...created })
|
||
}
|
||
|
||
export function updateAddress(id: string, input: Omit<Address, 'id' | 'isDefault'>): Promise<Address> {
|
||
const found = MOCK_ADDRESSES.find((item) => item.id === id)
|
||
if (!found) return Promise.reject(new Error('地址不存在'))
|
||
Object.assign(found, input)
|
||
return Promise.resolve({ ...found })
|
||
}
|
||
|
||
export function deleteAddress(id: string): Promise<void> {
|
||
const index = MOCK_ADDRESSES.findIndex((item) => item.id === id)
|
||
if (index >= 0) MOCK_ADDRESSES.splice(index, 1)
|
||
return Promise.resolve()
|
||
}
|
||
|
||
export function setDefaultAddress(id: string): Promise<Address[]> {
|
||
for (const item of MOCK_ADDRESSES) {
|
||
item.isDefault = item.id === id
|
||
}
|
||
return Promise.resolve(MOCK_ADDRESSES.map((item) => ({ ...item })))
|
||
}
|
||
|
||
const MOCK_FAVORITES: Case[] = [
|
||
{
|
||
id: 'fav-1',
|
||
title: '自动化生产线升级改造项目',
|
||
category: 'manufacturing',
|
||
cover: '',
|
||
finishDate: '2026/8/10',
|
||
teamSize: 50,
|
||
scale: '300万',
|
||
industry: '自动化',
|
||
duration: '150个工作日',
|
||
clientType: '企业',
|
||
sections: [
|
||
{ title: '项目背景', content: '<p>传统产线效率低、人工依赖高,客户需要通过自动化升级提升产能与品控水平。</p>' },
|
||
{ title: '客户痛点', content: '<p>1、产线依赖人工巡检,异常响应慢;2、设备数据孤岛,缺乏统一监控;3、工艺参数无法追溯。</p>' },
|
||
{ title: '需求描述', content: '<p>建设产线数据采集与监控平台,完成关键工位自动化改造,打通 MES 系统接口。</p>' },
|
||
{ title: '交付物', content: '<p>1、产线自动化改造方案;2、PLC 控制程序与上位机软件;3、数据看板与运维手册;4、培训与质保服务。</p>' },
|
||
],
|
||
video: '',
|
||
isFavorite: true,
|
||
favoriteCount: 0,
|
||
},
|
||
{
|
||
id: 'fav-2',
|
||
title: '智能工厂物联网整体解决方案',
|
||
category: 'iot',
|
||
cover: '',
|
||
finishDate: '2026/8/10',
|
||
teamSize: 30,
|
||
scale: '500万',
|
||
industry: '工厂服务',
|
||
duration: '200个工作日',
|
||
clientType: '企业',
|
||
sections: [
|
||
{ title: '项目背景', content: '<p>园区工厂多系统独立运行,能耗与设备管理粗放,需要整体数字化升级。</p>' },
|
||
{ title: '客户痛点', content: '<p>1、门禁/监控/能耗子系统数据不互通;2、能源浪费缺乏精细监测;3、决策缺少实时数据支撑。</p>' },
|
||
{ title: '需求描述', content: '<p>构建 IoT 平台接入设备数据,建设综合驾驶舱,实现能耗监测与智能告警。</p>' },
|
||
{ title: '交付物', content: '<p>1、IoT 接入平台;2、综合驾驶舱大屏;3、能耗分析系统;4、集成联调与培训服务。</p>' },
|
||
],
|
||
video: '',
|
||
isFavorite: true,
|
||
favoriteCount: 0,
|
||
},
|
||
{
|
||
id: 'fav-3',
|
||
title: '智能穿戴设备PCB设计与量产',
|
||
category: 'hardware',
|
||
cover: '',
|
||
finishDate: '2026/8/10',
|
||
teamSize: 50,
|
||
scale: '10-50万',
|
||
industry: '智能设备',
|
||
duration: '30个工作日',
|
||
clientType: '企业',
|
||
sections: [
|
||
{ title: '项目背景', content: '<p>客户推出新一代智能穿戴产品,需要高集成度低功耗 PCB 设计并快速量产。</p>' },
|
||
{ title: '客户痛点', content: '<p>1、板载空间受限,器件布局密集;2、功耗要求严格;3、量产良率需爬坡。</p>' },
|
||
{ title: '需求描述', content: '<p>完成原理图与 PCB 设计、打样验证、SMT 贴片与整机装配量产。</p>' },
|
||
{ title: '交付物', content: '<p>1、原理图与 PCB 设计文件;2、样板与测试报告;3、量产良率报告;4、BOM 与工艺文件。</p>' },
|
||
],
|
||
video: '',
|
||
isFavorite: true,
|
||
favoriteCount: 0,
|
||
},
|
||
{
|
||
id: 'fav-4',
|
||
title: '智能园区综合管理平台开发',
|
||
category: 'internet',
|
||
cover: '',
|
||
finishDate: '2026/8/10',
|
||
teamSize: 20,
|
||
scale: '200万',
|
||
industry: '园区服务',
|
||
duration: '200个工作日',
|
||
clientType: '企业',
|
||
sections: [
|
||
{ title: '项目背景', content: '<p>传统园区管理普遍"数据孤岛",安防、能耗、物业、招商等系统独立运行,缺乏联动,管理手段依赖人工巡检和纸质流程。</p>' },
|
||
{ title: '客户痛点', content: '<p>1、运营效率低下:安保依赖人工巡逻;2、系统孤岛严重:门禁、监控、停车、能耗等子系统独立建设;3、能源浪费突出;4、服务体验欠佳;5、决策缺乏依据;6、安全隐患犹存。</p>' },
|
||
{ title: '需求描述', content: '<p>打造集"感知、预警、分析、决策、服务"于一体的智能园区综合管理平台,打通园区各子系统壁垒,实现全场景数字化覆盖。</p>' },
|
||
{ title: '交付物', content: '<p>1、Web 端管理平台(驾驶舱/安防/能源/物业);2、移动端服务门户;3、IoT 平台与数据大屏;4、全套技术文档;5、培训与不少于1年免费质保。</p>' },
|
||
],
|
||
video: '',
|
||
isFavorite: true,
|
||
favoriteCount: 0,
|
||
},
|
||
]
|
||
|
||
export function getFavorites(query: FavoritesQuery): Promise<PageResult<Case>> {
|
||
const filtered = MOCK_FAVORITES.filter((item) => {
|
||
if (query.category !== 'all' && item.category !== query.category) return false
|
||
if (query.keyword && !item.title.includes(query.keyword)) return false
|
||
return true
|
||
})
|
||
const start = (query.page - 1) * query.pageSize
|
||
return Promise.resolve({
|
||
list: filtered.slice(start, start + query.pageSize).map((item) => ({ ...item })),
|
||
total: filtered.length,
|
||
})
|
||
}
|
||
|
||
export function getCaseCounts(): Promise<Partial<Record<BusinessType, number>>> {
|
||
const counts: Partial<Record<BusinessType, number>> = {
|
||
internet: 1,
|
||
hardware: 1,
|
||
iot: 1,
|
||
manufacturing: 1,
|
||
}
|
||
return Promise.resolve(counts)
|
||
}
|
||
|
||
const MOCK_QUALIFICATIONS: Qualification[] = [
|
||
{
|
||
id: 'qual-1',
|
||
type: '体系认证',
|
||
certName: 'ISO9001 质量管理体系认证证书',
|
||
certNo: 'ISO202609080075',
|
||
issuer: '中国质量认证中心',
|
||
validFrom: '2026-9-10',
|
||
validTo: '2027-9-10',
|
||
status: '已认证',
|
||
attachments: [
|
||
{ name: '体系认证证书', size: 1_048_576, uploadTime: '2026-09-10', url: '' },
|
||
],
|
||
},
|
||
{
|
||
id: 'qual-2',
|
||
type: '营业执照',
|
||
certName: '营业执照',
|
||
certNo: '91371102MA3XX8876Q',
|
||
issuer: '日照市东港区市场监督管理局',
|
||
validFrom: '2020-3-15',
|
||
validTo: '2030-3-14',
|
||
status: '审核中',
|
||
attachments: [
|
||
{ name: '营业执照', size: 820_000, uploadTime: '2026-09-12', url: '' },
|
||
],
|
||
},
|
||
{
|
||
id: 'qual-3',
|
||
type: '检测报告',
|
||
certName: '智能终端产品第三方检测报告',
|
||
certNo: 'WT20260512001',
|
||
issuer: '山东省产品质量检验研究院',
|
||
validFrom: '2026-5-12',
|
||
validTo: '2027-5-12',
|
||
status: '未通过',
|
||
attachments: [
|
||
{ name: '检测报告', size: 2_097_152, uploadTime: '2026-05-15', url: '' },
|
||
],
|
||
},
|
||
{
|
||
id: 'qual-4',
|
||
type: '生产许可证',
|
||
certName: '全国工业产品生产许可证',
|
||
certNo: 'XK06-123-45678',
|
||
issuer: '山东省市场监督管理局',
|
||
validFrom: '2024-1-8',
|
||
validTo: '2029-1-7',
|
||
status: '已认证',
|
||
attachments: [
|
||
{ name: '生产许可证', size: 1_258_291, uploadTime: '2024-01-10', url: '' },
|
||
],
|
||
},
|
||
]
|
||
|
||
export function getQualifications(query: ListQuery): Promise<PageResult<Qualification>> {
|
||
return Promise.resolve(paginate(MOCK_QUALIFICATIONS, query))
|
||
}
|
||
|
||
export function createQualification(input: QualificationInput): Promise<Qualification> {
|
||
const created: Qualification = {
|
||
...input,
|
||
id: `qual-${Date.now()}`,
|
||
status: '审核中',
|
||
}
|
||
MOCK_QUALIFICATIONS.unshift(created)
|
||
return Promise.resolve({ ...created })
|
||
}
|
||
|
||
export function updateQualification(id: string, input: QualificationInput): Promise<Qualification> {
|
||
const found = MOCK_QUALIFICATIONS.find((item) => item.id === id)
|
||
if (!found) return Promise.reject(new Error('资质不存在'))
|
||
found.type = input.type
|
||
found.certName = input.certName
|
||
found.certNo = input.certNo
|
||
found.issuer = input.issuer
|
||
found.validFrom = input.validFrom
|
||
found.validTo = input.validTo
|
||
found.attachments = input.attachments
|
||
if (found.status === '未通过') found.status = '审核中'
|
||
return Promise.resolve({ ...found })
|
||
}
|
||
|
||
export function deleteQualification(id: string): Promise<void> {
|
||
const index = MOCK_QUALIFICATIONS.findIndex((item) => item.id === id)
|
||
if (index >= 0) MOCK_QUALIFICATIONS.splice(index, 1)
|
||
return Promise.resolve()
|
||
}
|
||
|
||
export function submitFeedback(feedback: Feedback): Promise<void> {
|
||
void feedback
|
||
return Promise.resolve()
|
||
}
|
||
|
||
export function getHelpFaqs(): Promise<HelpFaqGroup[]> {
|
||
return Promise.resolve([
|
||
{
|
||
title: '1. 账户与登录',
|
||
items: [
|
||
{
|
||
q: '如何注册账号?',
|
||
a: '点击页面右上角"注册",输入手机号并获取验证码,设置 6-20 位登录密码即可完成注册。',
|
||
},
|
||
{
|
||
q: '忘记密码怎么办?',
|
||
a: '在登录页点击"忘记密码",通过绑定手机号验证码验证身份后即可重新设置密码。',
|
||
},
|
||
{
|
||
q: '一个账号可以多地登录吗?',
|
||
a: '同一账号同时仅允许在 1 台设备上保持在线,超出将自动踢出最早登录的设备。',
|
||
},
|
||
{
|
||
q: '如何修改绑定手机号?',
|
||
a: '进入 个人中心 → 账号安全 → 绑定手机,验证原手机号后即可绑定新号码。',
|
||
},
|
||
],
|
||
},
|
||
{
|
||
title: '2. 功能使用指南',
|
||
items: [
|
||
{
|
||
q: '如何提交需求?',
|
||
a: '进入"发布需求"页面,填写需求描述、预算、周期等信息并提交,专业顾问将在一个工作日内与您联系。',
|
||
},
|
||
{
|
||
q: '如何查看我的消息?',
|
||
a: '登录后点击右上角消息图标,或进入 个人中心 → 消息通知,即可查看系统通知与顾问消息。',
|
||
},
|
||
{
|
||
q: '如何申请售后?',
|
||
a: '在"我的订单"中找到对应项目,点击"申请售后"填写问题描述并上传附件,平台将尽快为您处理。',
|
||
},
|
||
],
|
||
},
|
||
{
|
||
title: '3. 系统与权限',
|
||
items: [
|
||
{
|
||
q: '无权限怎么办?',
|
||
a: '请确认当前账号角色是否具备该模块权限;如仍无法访问,请联系专属客服或平台管理员为您开通。',
|
||
},
|
||
{
|
||
q: '收不到通知怎么办?',
|
||
a: '请检查浏览器通知权限与消息设置是否开启;若仍未收到,请联系客服核实账号通知配置。',
|
||
},
|
||
{
|
||
q: '支持哪些浏览器?',
|
||
a: '推荐使用 Chrome、Edge、Firefox、Safari 等主流浏览器的最新版本访问本平台。',
|
||
},
|
||
],
|
||
},
|
||
])
|
||
}
|