Files
cz-web/src/api/profile.ts
wangzzpeng 7bc84bbe5e first
2026-09-24 10:10:43 +08:00

419 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 数据流不变)
/** 账号资料 mock(可变,昵称/绑定等操作在前端内存中演示) */
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()
}
/** 收货地址 mock(isDefault 混合) */
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 })))
}
/** 我的收藏 mock(4 条已收藏案例,字段与案例库原型一致) */
const MOCK_FAVORITES: Case[] = [
{
id: 'fav-1',
title: '自动化生产线升级改造项目',
category: 'manufacturing',
cover: '',
finishDate: '2026/8/10',
teamSize: 50,
scale: '300万',
industry: '自动化',
duration: '150个工作日',
clientType: '企业',
background: '传统产线效率低、人工依赖高,客户需要通过自动化升级提升产能与品控水平。',
painPoints: '1、产线依赖人工巡检,异常响应慢;2、设备数据孤岛,缺乏统一监控;3、工艺参数无法追溯。',
requirements: '建设产线数据采集与监控平台,完成关键工位自动化改造,打通 MES 系统接口。',
deliverables: '1、产线自动化改造方案;2、PLC 控制程序与上位机软件;3、数据看板与运维手册;4、培训与质保服务。',
video: '',
isFavorite: true,
},
{
id: 'fav-2',
title: '智能工厂物联网整体解决方案',
category: 'iot',
cover: '',
finishDate: '2026/8/10',
teamSize: 30,
scale: '500万',
industry: '工厂服务',
duration: '200个工作日',
clientType: '企业',
background: '园区工厂多系统独立运行,能耗与设备管理粗放,需要整体数字化升级。',
painPoints: '1、门禁/监控/能耗子系统数据不互通;2、能源浪费缺乏精细监测;3、决策缺少实时数据支撑。',
requirements: '构建 IoT 平台接入设备数据,建设综合驾驶舱,实现能耗监测与智能告警。',
deliverables: '1、IoT 接入平台;2、综合驾驶舱大屏;3、能耗分析系统;4、集成联调与培训服务。',
video: '',
isFavorite: true,
},
{
id: 'fav-3',
title: '智能穿戴设备PCB设计与量产',
category: 'hardware',
cover: '',
finishDate: '2026/8/10',
teamSize: 50,
scale: '10-50万',
industry: '智能设备',
duration: '30个工作日',
clientType: '企业',
background: '客户推出新一代智能穿戴产品,需要高集成度低功耗 PCB 设计并快速量产。',
painPoints: '1、板载空间受限,器件布局密集;2、功耗要求严格;3、量产良率需爬坡。',
requirements: '完成原理图与 PCB 设计、打样验证、SMT 贴片与整机装配量产。',
deliverables: '1、原理图与 PCB 设计文件;2、样板与测试报告;3、量产良率报告;4、BOM 与工艺文件。',
video: '',
isFavorite: true,
},
{
id: 'fav-4',
title: '智能园区综合管理平台开发',
category: 'internet',
cover: '',
finishDate: '2026/8/10',
teamSize: 20,
scale: '200万',
industry: '园区服务',
duration: '200个工作日',
clientType: '企业',
background: '传统园区管理普遍"数据孤岛",安防、能耗、物业、招商等系统独立运行,缺乏联动,管理手段依赖人工巡检和纸质流程。',
painPoints: '1、运营效率低下:安保依赖人工巡逻;2、系统孤岛严重:门禁、监控、停车、能耗等子系统独立建设;3、能源浪费突出;4、服务体验欠佳;5、决策缺乏依据;6、安全隐患犹存。',
requirements: '打造集"感知、预警、分析、决策、服务"于一体的智能园区综合管理平台,打通园区各子系统壁垒,实现全场景数字化覆盖。',
deliverables: '1、Web 端管理平台(驾驶舱/安防/能源/物业);2、移动端服务门户;3、IoT 平台与数据大屏;4、全套技术文档;5、培训与不少于1年免费质保。',
video: '',
isFavorite: true,
},
]
/** 我的收藏(关键字/分类筛选 + 分页) */
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)
}
/** 资质 mock(状态混合:已认证/审核中/未通过) */
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()
}
/** 帮助中心 FAQ */
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 等主流浏览器的最新版本访问本平台。',
},
],
},
])
}