Files
cz-web/src/api/profile.ts
2026-10-13 15:56:12 +08:00

407 lines
14 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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()
}
/** TODO(api): 后端帮助中心接口就绪后改为 request 调用;暂用设计稿假数据 */
export function getHelpFaqs(): Promise<HelpFaqGroup[]> {
return Promise.resolve([
{
title: '账户与登录',
items: [
{
q: '如何注册账号?',
a: '打开APP后点击“注册”,输入手机号获取验证码,设置登录密码即可完成注册。',
},
{
q: '忘记密码怎么办?',
a: '在登录页面点击“忘记密码”,输入注册手机号获取验证码,验证通过后即可重置新密码。',
},
{
q: '一个账号可以多端登录吗?',
a: '同一账号仅允许在 1 台设备上保持在线,超出将自动踢出最早登录的设备。',
},
{
q: '如何修改绑定手机号?',
a: '进入「我的 -> 设置 -> 账户安全 -> 更换手机号」,验证原手机号后即可绑定新号码。',
},
],
},
{
title: '功能使用指南',
items: [
{
q: '如何提交报修/工单?',
a: '首页点击「报修」 -> 选择报修类型 -> 填写问题描述并上传图片 -> 提交。提交后可在「我的 -> 我的工单」中查看处理进度。',
},
{
q: '如何预约会议室?',
a: '进入「服务 -> 会议室预订」,选择日期、时间段及会议室,确认后提交预约,预约成功将收到消息通知。',
},
{
q: '如何查看我的消息通知?',
a: '首页右上角铃铛图标进入消息中心,支持按“全部 / 未读 / 系统通知 / 业务提醒”分类查看。',
},
],
},
{
title: '系统与权限',
items: [
{
q: 'APP提示“无权限”怎么办?',
a: '部分功能需要管理员授权后方可使用,请联系贵司系统管理员为您分配对应角色权限。',
},
{
q: '为什么收不到推送通知?',
a: '请检查:①手机系统设置中是否允许本APP发送通知;②APP内「我的 -> 设置 -> 消息推送」是否已开启。',
},
{
q: 'APP支持哪些系统版本?',
a: 'iOS 13.0 及以上版本,Android 8.0 及以上版本。建议使用最新系统版本以获得最佳体验。',
},
],
},
])
}