diff --git a/src/api/auth.ts b/src/api/auth.ts
index cbbae6f..8b380b8 100644
--- a/src/api/auth.ts
+++ b/src/api/auth.ts
@@ -8,16 +8,8 @@ import type {
} from '@/types/business/user'
import { isPhone, isValidPassword } from '@/utils/validate'
-/**
- * PC 端 clientId(sys_client 种子数据,grantType 含 password)。
- * 与请求头 clientid 同源(见 @/utils/request),改一处即可整体生效。
- */
export const PC_CLIENT_ID = CLIENT_ID
-/**
- * 账号密码登录:POST /auth/login
- * 后端要求请求体含 clientId + grantType + username + password(api-decrypt 未开启,明文即可)
- */
export function loginByAccountApi(data: { username: string; password: string }): Promise {
return request({
url: '/auth/login',
@@ -31,10 +23,6 @@ export function loginByAccountApi(data: { username: string; password: string }):
})
}
-/**
- * 账号密码注册:POST /auth/register
- * userType=sys_user;需后端开启注册开关(sys.account.registerUser=true),否则返回「当前系统没有开启注册功能!」
- */
export function registerByAccountApi(data: { username: string; password: string }): Promise {
return request({
url: '/auth/register',
@@ -53,13 +41,11 @@ export function registerByAccountApi(data: { username: string; password: string
const SIX_DIGIT_CODE = /^\d{6}$/
-/** 发送短信验证码 */
export function sendSmsCode(phone: string): Promise {
if (!isPhone(phone)) return Promise.reject(new Error('手机号格式不正确'))
return Promise.resolve()
}
-/** 手机验证码登录(mock:验证码须为 6 位数字) */
export function loginBySms(params: LoginBySmsParams): Promise {
const { phone, code } = params
if (!isPhone(phone)) return Promise.reject(new Error('手机号格式不正确'))
@@ -90,7 +76,6 @@ function validateAuthForm(
return null
}
-/** 重置密码 */
export function resetPassword(params: ResetPasswordParams): Promise {
const message = validateAuthForm(
params.phone,
diff --git a/src/api/cases.ts b/src/api/cases.ts
index ba9bde9..e47bfe0 100644
--- a/src/api/cases.ts
+++ b/src/api/cases.ts
@@ -1,10 +1,4 @@
-// 案例库接口(真实后端绑定)
-// 后端: vermis-maker com.ruoyi.vermins.controller.pc.web.ProjectCaseUserController
-// 前缀: /web/projectCase
//
-// 使用约定(与项目 SKILL.md 一致):
-// 页面/组件禁止直接 import axios,一律经 store 调用本模块的 request。
-// 本文件只放「函数签名 + 请求路径」,不做数据加工、不维护状态。
import { request, serializeQuery } from '@/utils/request'
import type {
CaseSelectionModel,
@@ -13,16 +7,6 @@ import type {
ProjectCaseVo,
} from '@/types/business/cases'
-/**
- * 案例库分页列表(返回列表 + 业务数据统计)。
- *
- * 规模区间是嵌套对象(`scales[0].lowerLimit`),必须用 serializeQuery 序列化——
- * axios 默认的 `scales[0][lowerLimit]` 后端绑不上,实测 HTTP 500。
- *
- * @param bo 筛选条件(businessTypes 按案例表 business_type 原值匹配)
- * @param pageNum 页码,从 1 开始(后端 PageQuery)
- * @param pageSize 每页条数
- */
export function getCaseList(
bo: ProjectCaseUserBo,
pageNum: number,
@@ -36,11 +20,6 @@ export function getCaseList(
})
}
-/**
- * 案例详情(含项目背景富文本与附件,并回填当前用户是否已收藏)。
- *
- * 注意:该接口每次调用都会把案例预览量 +1,勿在轮询 / 重试场景滥用。
- */
export function getCaseDetail(id: string): Promise {
return request({
url: `/web/projectCase/${id}`,
@@ -48,11 +27,6 @@ export function getCaseDetail(id: string): Promise {
})
}
-/**
- * 案例收藏 / 取消收藏。
- *
- * 后端为 toggle 语义:已收藏则取消收藏。需登录态,匿名调用会被后端拦截。
- */
export function collectCase(id: string): Promise {
return request({
url: '/web/projectCase/collect',
@@ -61,13 +35,6 @@ export function collectCase(id: string): Promise {
})
}
-/**
- * 筛选面板选项(业务类型统计 + 行业 + 规模档位)。
- *
- * 左侧筛选除完成时间外的选项都由本接口一次下发:业务类型与案例总数在
- * {@code projectCaseStatisticsVo},行业在 {@code businessIndustry},规模在
- * {@code upperAndLowerLimits}(label 已由后端拼好)。
- */
export function getCaseCategories(): Promise {
return request({
url: '/web/projectCase/categories',
@@ -75,12 +42,6 @@ export function getCaseCategories(): Promise {
})
}
-/**
- * 案例浏览王(首页「案例库精选」)。
- *
- * 不传 type 时返回「各业务类型的浏览王」各一条;传 type 时按案例表
- * business_type 的原值精确匹配,返回该类型全部案例。
- */
export function getFeaturedCases(type?: string): Promise {
return request({
url: '/web/projectCase/mostViewed',
diff --git a/src/api/contract.ts b/src/api/contract.ts
index 8ba4472..ac25892 100644
--- a/src/api/contract.ts
+++ b/src/api/contract.ts
@@ -3,15 +3,12 @@ import type { Contract, ContractQuery } from '@/types/business/contract'
// TODO(api): 待接口文档到位后,将以下 mock 替换为 request 调用
-/** 构造 mock 文件信息 */
function mockFile(name: string, size: number, uploadTime: string): FileInfo {
return { name, size, uploadTime, url: '' }
}
-/** 详情 mock 所属合同 id */
const DETAIL_ID = 'contract-001'
-/** 合同列表 mock(3 条,覆盖全部签署状态) */
const MOCK_CONTRACTS: Contract[] = [
{
id: 'contract-001',
@@ -56,7 +53,6 @@ const MOCK_CONTRACTS: Contract[] = [
},
]
-/** 合同详情 mock */
const CONTRACT_DETAIL: Contract = {
id: DETAIL_ID,
contractNo: 'C8K2M202408001',
@@ -72,7 +68,6 @@ const CONTRACT_DETAIL: Contract = {
files: [mockFile('项目需求规格说明书.pdf', 2516582, '2024-10-15')],
}
-/** 合同列表(keyword 筛选 + 分页) */
export function getContractList(query: ContractQuery): Promise> {
const filtered = MOCK_CONTRACTS.filter((item) => {
if (
@@ -92,19 +87,16 @@ export function getContractList(query: ContractQuery): Promise {
if (id === DETAIL_ID) return Promise.resolve({ ...CONTRACT_DETAIL, files: [...CONTRACT_DETAIL.files] })
const found = MOCK_CONTRACTS.find((item) => item.id === id) ?? null
return Promise.resolve(found ? { ...found, files: [...found.files] } : null)
}
-/** 获取签署二维码(返回有效期) */
export function getSignQr(_id: string): Promise<{ expiresInSeconds: number }> {
return Promise.resolve({ expiresInSeconds: 272 })
}
-/** 刷新签署二维码(返回有效期) */
export function refreshSignQr(_id: string): Promise<{ expiresInSeconds: number }> {
return Promise.resolve({ expiresInSeconds: 272 })
}
diff --git a/src/api/demand.ts b/src/api/demand.ts
index bb40589..4561635 100644
--- a/src/api/demand.ts
+++ b/src/api/demand.ts
@@ -1,14 +1,4 @@
-// 需求提报接口(真实后端绑定)
-// 草稿 com.ruoyi.vermins.controller.pc.web.WorkUserOrderDraftController → /web/workOrderDraft
-// 提交 com.ruoyi.vermins.controller.pc.web.ProjectRequirementUserController → /web/requirementPool/create(WorkOrderDraftBo)
-// 同控制器的 /submit(RdProjectBo)是直接提报入口(额外落 vm_rd_project),前端当前未使用
-// 业务类型 com.ruoyi.vermins.controller.pc.ProjectSubmissionWebController → /web/projectSubmission(@SaIgnore 免登录)
-// 预算范围 org.dromara.system.controller.system.SysDictDataController → /system/dict/data/type/{dictType}
-// 图片换链 org.dromara.resource.controller.SysOssController → /resource/oss/listByIds/{ids}
-// 鉴权:业务类型列表免登录;草稿 / 提交 / 字典 / OSS 需登录态(匿名实测 401,故 /demand 路由带 requiresAuth)
//
-// 使用约定(与项目 SKILL.md 一致):
-// 页面/组件禁止直接 import axios,一律经 store 调用本模块;本文件只放「函数签名 + 请求路径」。
import service, { request } from '@/utils/request'
import type { ApiResponse } from '@/types/api'
import type {
@@ -20,21 +10,9 @@ import type {
SubmissionBizTypeVo,
} from '@/types/business/demand'
-/** 业务类型字典类型(sys_dict_type.dict_type)——仅作提报列表为空时的兜底值域 */
export const BIZ_TYPE_DICT = 'vm_biz_type'
-/** 预算范围字典类型 */
export const BUDGET_RANGE_DICT = 'vm_budget_range'
-/**
- * 业务类型列表(项目提报表,**免登录**)。
- *
- * 后端 `ProjectSubmissionWebController` 带 `@SaIgnore`,是需求页唯一匿名可用的接口;
- * 它与首页 `/web/home-page/service-type-list` 共用同一个 `queryEnabledList()`,只返回
- * `enabled = 1` 且未被逻辑删除的记录。
- *
- * 返回项里 `subtitle` 是卡片描述来源、`logoUrl` 是卡片图标来源(实测是 OSS 文件标识,
- * 需经 {@link getOssUrls} 换链)。
- */
export function getSubmissionBizTypes(): Promise {
return request({
url: '/web/projectSubmission/list',
@@ -42,14 +20,6 @@ export function getSubmissionBizTypes(): Promise {
})
}
-/**
- * OSS 文件标识 → 可直接访问的地址。
- *
- * 提报列表的 `coverUrl` / `logoUrl` 下发的是 OSS 主键(如 2099753406859292674)而非地址,
- * 直接当 `
` 用会请求到本站的错误路径上,必须换链。
- *
- * ⚠️ 本接口需要登录态;失败时调用方回退前端内置图标,且不阻塞页面。
- */
export function getOssUrls(ids: (string | number)[]): Promise {
return request({
url: `/resource/oss/listByIds/${ids.join(',')}`,
@@ -57,12 +27,6 @@ export function getOssUrls(ids: (string | number)[]): Promise {
})
}
-/**
- * 业务类型字典(`vm_biz_type`)。
- *
- * ⚠️ 仅作**兜底**用:业务类型值域已改为提报列表 {@link getSubmissionBizTypes};
- * 只有当提报表一条可用记录都没有时,store 才回退到本字典,避免页面无可选项。
- */
export function getBizTypeDict(): Promise {
return request({
url: `/system/dict/data/type/${BIZ_TYPE_DICT}`,
@@ -70,7 +34,6 @@ export function getBizTypeDict(): Promise {
})
}
-/** 预算范围选项(字典 vm_budget_range) */
export function getBudgetRangeDict(): Promise {
return request({
url: `/system/dict/data/type/${BUDGET_RANGE_DICT}`,
@@ -78,14 +41,6 @@ export function getBudgetRangeDict(): Promise {
})
}
-/**
- * 读取当前登录用户的需求提报草稿(无草稿返回 null)。
- *
- * ⚠️ 后端 `WorkUserOrderDraftController#getDraft` 在"该用户还没有草稿"时会 NPE:
- * `VmWorkOrderDraftServiceImpl#queryById` 里 `draft` 为 null 仍继续执行 `draft.getId()`,
- * 实测返回 code=500「发生未知异常」。这里刻意绕过统一 `request`(它会对非 200 弹错误提示),
- * 直接用原始实例静默兜底:非 200 一律视作"无草稿"。后端补上判空后本段可简化。
- */
export async function getDraftDemand(): Promise {
const resp = await service.request>({
url: '/web/workOrderDraft/getDraft',
@@ -95,18 +50,6 @@ export async function getDraftDemand(): Promise {
return resp.data.data ?? null
}
-/**
- * Demand → 后端 `WorkOrderDraftBo` 请求体。
- *
- * 显式列出 BO 的字段,**剔掉纯前端字段 `budgetManual`**(后端 BO/VO 与两张表都没有
- * 「是否手写」的概念,留着虽然会被 Jackson 忽略,但容易被误读成后端支持该标记)。
- *
- * 预算范围只有一个字段可下发:预设档位是字典 dictValue,手写时是用户填的金额文本
- * ——后端没有可用的 `budgetCustom`(`WorkOrderDraftBo` 里被注释掉、表也无该列)。
- *
- * `developmentCycle` 是 Integer,表单未填时是空串,必须归一成 null:空串虽然能靠
- * Jackson 的宽松转换塞进去,但依赖默认行为、且语义上是"没填"。
- */
function toBoPayload(demand: Demand): Record {
return {
id: demand.id,
@@ -122,7 +65,6 @@ function toBoPayload(demand: Demand): Record {
}
}
-/** 新增/覆盖草稿(后端 insertByBo 按登录用户 upsert) */
export function saveDraft(demand: Demand): Promise {
return request({
url: '/web/workOrderDraft/add',
@@ -131,7 +73,6 @@ export function saveDraft(demand: Demand): Promise {
})
}
-/** 清空当前用户的草稿(后端 cleanHistoryDrafts) */
export function resetDraft(): Promise {
return request({
url: '/web/workOrderDraft/reset',
@@ -139,7 +80,6 @@ export function resetDraft(): Promise {
})
}
-/** 上传附件(multipart,后端字段名 file,返回 SysOssVo) */
export function uploadDemandFile(file: File): Promise {
const data = new FormData()
data.append('file', file)
@@ -151,29 +91,6 @@ export function uploadDemandFile(file: File): Promise {
})
}
-/**
- * 提交需求(`POST /web/requirementPool/create`)。
- *
- * 入参与草稿共用同一个 BO(`WorkOrderDraftBo`),故请求体直接复用 {@link toBoPayload},
- * 不需要字段名转换。
- *
- * 后端 `createRequirement` 一个事务里做三件事:
- *
- * - 落 `vm_project_requirement`(需求主记录,生成项目编号、优先级=未评估、状态=待接洽);
- * - 把**请求体里的 `attachmentInfo`** 逐条复制成需求附件(只复制 `ossId` 引用到
- * `vm_project_requirement_attachment`,OSS 文件不重复上传)——注意这里是直接吃请求体,
- * 不像 `/submit` 那样还得先落一次草稿,所以附件随本次请求一起走;
- * - 清掉该用户的草稿(`cleanHistoryDrafts`)。
- *
- *
- * 后端必填校验:`bizType` / `projectName` / `requirementDesc` 任一为空返回
- * 「请完整填写业务类型、项目名称和需求描述」;联系人姓名与电话缺失时先回退登录用户资料,
- * 仍为空则报「请完善联系人姓名和联系电话」。
- *
- * ⚠️ 本条链路**只落 `vm_project_requirement` 单表**。而「我的项目/需求」列表
- * (`/web/requirementPool/list`)查的是 `vm_rd_project`,因此 create 提交的记录不会出现在
- * 该列表里——要同时落两张表得走后端 `/web/requirementPool/submit`(`RdProjectBo`)。
- */
export function submitDemand(demand: Demand): Promise {
return request({
url: '/web/requirementPool/create',
diff --git a/src/api/finance.ts b/src/api/finance.ts
index 29b1570..dbd15bf 100644
--- a/src/api/finance.ts
+++ b/src/api/finance.ts
@@ -17,10 +17,6 @@ import { toBills, toPlanBills, type PlanLike } from '@/utils/billVo'
import { toPayMethod } from '@/utils/payMeta'
import { request } from '@/utils/request'
-// 说明:账单 / 支付相关接口已接后端真数据;仅「发票」与「统计」仍是 mock。
-// 另有已下线的遗留演示扫码页(pay.vue)用的一组 mock,见文件中部注释。
-
-/** 遗留演示页用的假账单(真账单走 `GET /web/bill/list`,不读这里) */
const MOCK_BILLS: Bill[] = [
{
id: 'bill-001',
@@ -80,7 +76,6 @@ const MOCK_BILLS: Bill[] = [
},
]
-/** 发票 mock(可变:申请开票后状态在前端内存中翻转演示) */
const MOCK_INVOICES: Invoice[] = [
{
id: 'invoice-001',
@@ -113,7 +108,6 @@ const MOCK_INVOICES: Invoice[] = [
},
]
-/** 发票抬头 mock(可变,CRUD 在前端内存中演示) */
const MOCK_TITLES: InvoiceTitle[] = [
{
id: 'title-001',
@@ -131,10 +125,8 @@ const MOCK_TITLES: InvoiceTitle[] = [
},
]
-/** 支付进行单(billId → 当前二维码) */
const MOCK_PAYMENTS = new Map()
-/** 已产生支付结果的账单(billId → 结果),预置已支付账单 */
const MOCK_RESULTS = new Map()
MOCK_RESULTS.set('bill-001', {
method: 'wechat',
@@ -163,18 +155,15 @@ const DEFAULT_STATS: FinanceStats = {
],
}
-/** 财务统计(period 为展示周期参数,mock 恒返回原型数据) */
export function getFinanceStats(period?: string): Promise {
void period
return Promise.resolve(structuredClone(DEFAULT_STATS))
}
-/** 真账单 id 一定是纯数字(`vm_bill.id` 是 bigint);非数字只可能来自已下线的演示mock */
function isRealBillId(id: string): boolean {
return /^\d+$/.test(id)
}
-/** 拉取「当前登录用户」的全部账单(`GET /web/bill/list`,不带 ids) */
async function fetchOwnBills(): Promise {
const rows = await request({ url: '/web/bill/list', method: 'get' })
return toBills(rows)
@@ -190,13 +179,6 @@ function matchBillKeyword(item: Bill, keyword: string): boolean {
)
}
-/**
- * 账单列表(筛选 + 分页)。
- *
- * ⚠️ `GET /web/bill/list` 只按登录用户返回**全量**账单,后端没有 pageNum / keyword /
- * status 查询参数;单个客户的账单量级是「几条 ~ 几十条」,故筛选与分页放在前端做。
- * 若日后账单量变大,应给该端点补后端分页参数,这里再切成一次请求。
- */
export async function getBillList(query: BillQuery): Promise> {
const all = await fetchOwnBills()
const filtered = all.filter((item) => {
@@ -207,22 +189,15 @@ export async function getBillList(query: BillQuery): Promise> {
return { list: filtered.slice(start, start + query.pageSize), total: filtered.length }
}
-/** 账单详情(不存在返回 null) */
export async function getBillDetail(id: string): Promise {
const rows = await request({ url: '/web/bill/list', method: 'get', params: { ids: id } })
return toBills(rows)[0] ?? null
}
// ═══════════════════════════════════════════════════════════════════════
-// 遗留演示扫码页(`/finance/bills/:id/pay`,页面 pay.vue)
// ---------------------------------------------------------------------
-// 该页已无任何入口(收银台 checkout.vue 取代了它),但按既定决定保留。
-// 它用的是下面这几个 mock 函数,与真账单互不干扰:真账单 id 一定是数字,
-// 假账单 id 形如 `bill-001`,两条路径靠 `isRealBillId` 分流。
-// 若要下线该页,这一整段(含 MOCK_PAYMENTS / MOCK_RESULTS)可一并删除。
// ═══════════════════════════════════════════════════════════════════════
-/** 创建支付单(遗留页演示用:生成二维码支付信息) */
export function createPayment(billId: string, method: PayMethod): Promise {
const bill = MOCK_BILLS.find((item) => item.id === billId)
if (!bill) return Promise.reject(new Error('账单不存在'))
@@ -236,21 +211,10 @@ export function createPayment(billId: string, method: PayMethod): Promise {
return createPayment(billId, method)
}
-/**
- * 查询支付结果。
- *
- * 真账单:直接读 `vm_bill` —— 账单被回调置为 PAID 时,`pay_time` /
- * `transaction_no` / `pay_channel` 已由后端一并回写,这里拼出结果页所需结构;
- * 未支付则返回 null。
- *
- * 假账单(id 形如 `bill-001`):走下面的遗留演示逻辑。真账单 id 一定是数字,
- * 故只有已下线的 pay.vue 会命中这条分支。
- */
export async function getPayResult(billId: string): Promise {
if (isRealBillId(billId)) {
const bill = await getBillDetail(billId)
@@ -266,7 +230,6 @@ export async function getPayResult(billId: string): Promise {
const existing = MOCK_RESULTS.get(billId)
if (existing) return Promise.resolve(structuredClone(existing))
@@ -275,7 +238,6 @@ function getLegacyPayResult(billId: string): Promise {
const bill = MOCK_BILLS.find((item) => item.id === billId)
if (!payment || !bill) return Promise.resolve(null)
- // 演示:存在支付单即视为完成支付(createPayment 由「完成支付」触发)
const tradeNo = bill.tradeNo ?? 'T20260819153035678K2M001'
if (bill.status !== '已支付') {
bill.status = '已支付'
@@ -302,7 +264,6 @@ function matchInvoiceKeyword(item: Invoice, keyword: string): boolean {
)
}
-/** 发票列表(筛选 + 分页) */
export function getInvoiceList(query: InvoiceQuery): Promise> {
const filtered = MOCK_INVOICES.filter((item) => {
if (query.status !== 'all' && item.status !== query.status) return false
@@ -315,7 +276,6 @@ export function getInvoiceList(query: InvoiceQuery): Promise
})
}
-/** 申请开票(演示:状态置为开票中),返回最新发票 */
export function applyInvoice(id: string): Promise {
const found = MOCK_INVOICES.find((item) => item.id === id)
if (!found) return Promise.reject(new Error('发票记录不存在'))
@@ -323,12 +283,10 @@ export function applyInvoice(id: string): Promise {
return Promise.resolve({ ...found })
}
-/** 发票抬头列表 */
export function getInvoiceTitles(): Promise {
return Promise.resolve(MOCK_TITLES.map((item) => ({ ...item })))
}
-/** 新增发票抬头 */
export function createInvoiceTitle(payload: InvoiceTitlePayload): Promise {
const created: InvoiceTitle = {
id: `title-${Date.now()}`,
@@ -339,7 +297,6 @@ export function createInvoiceTitle(payload: InvoiceTitlePayload): Promise {
const found = MOCK_TITLES.find((item) => item.id === id)
if (!found) return Promise.reject(new Error('抬头不存在'))
@@ -349,7 +306,6 @@ export function updateInvoiceTitle(id: string, payload: InvoiceTitlePayload): Pr
return Promise.resolve({ ...found })
}
-/** 删除发票抬头 */
export function deleteInvoiceTitle(id: string): Promise {
const index = MOCK_TITLES.findIndex((item) => item.id === id)
if (index < 0) return Promise.reject(new Error('抬头不存在'))
@@ -357,7 +313,6 @@ export function deleteInvoiceTitle(id: string): Promise {
return Promise.resolve()
}
-/** 设为默认抬头(唯一默认) */
export function setDefaultTitle(id: string): Promise {
for (const item of MOCK_TITLES) {
item.isDefault = item.id === id
@@ -365,30 +320,13 @@ export function setDefaultTitle(id: string): Promise {
return Promise.resolve(MOCK_TITLES.map((item) => ({ ...item })))
}
-/** 导出报表(演示:稍后由页面提示成功) */
export function exportReport(): Promise {
return Promise.resolve()
}
// ═══════════════════════════════════════════════════════════════════════
-// 收银台(确认支付)——以下为**真实后端接口**,不是 mock
-// 后端类:vermis-modules/…/controller/pc/pay/WebScanPayController,类级 @SaIgnore(匿名可调)
// ═══════════════════════════════════════════════════════════════════════
-/**
- * 取收银台「订单明细」——**复用项目详情「合同财务」那个现成接口**,不另开端点。
- *
- * `GET /web/requirementPool/get/finance/{requirementId}`(`ProjectRequirementUserController`)
- * 的 `{id}` 是**需求 id**;后端把「需求 + 项目」拼成一条联合结构(`loadProject` 用
- * `vm_rd_project.requirement_id` 反查项目),再把该项目的付款计划随 `billPlans` 一并下发。
- *
- * 本栈支付口径是 `vm_bill_plan.id`(`vm_finance_payment.bill_id` 实测存的就是计划 id),
- * 故订单明细直接取这份 `billPlans`,只保留**本次要付的期**:
- * URL 带 `ids`(期次 id)时按期次过滤,不带则取状态为「待支付」的期。
- *
- * @param requirementId 需求 id(项目详情路由 `:id`)
- * @param ids 期次 id(`vm_bill_plan.id`)列表,可选,用于精确指定付哪一期
- */
export async function getCheckoutBills(requirementId: string, ids: string[] = []): Promise {
if (!/^\d+$/.test(requirementId)) return []
const vo = await request<{ billPlans?: PlanLike[] }>({
@@ -401,12 +339,6 @@ export async function getCheckoutBills(requirementId: string, ids: string[] = []
: all.filter((bill) => bill.status === '待支付')
}
-/**
- * 支付结果(收银台「我已完成支付」→ 结果页)。
- *
- * 口径同 {@link getCheckoutBills}:按**需求 id + 期次 id** 从 `billPlans` 里取出该期,
- * 支付单状态为 `SUCCESS` 才算已支付——计划本身的 status 可能还没被回调推到 DONE。
- */
export async function getPlanPayResult(requirementId: string, planId: string): Promise {
const bills = await getCheckoutBills(requirementId, [planId])
const bill = bills[0]
@@ -420,17 +352,6 @@ export async function getPlanPayResult(requirementId: string, planId: string): P
}
}
-/**
- * 微信 Native 下单(PC 网站扫码):`POST /pay/web/wechat/native`,`@SaIgnore`。
- *
- * @param orderNo 商户订单号(前端生成,见 `utils/payMeta.ts#createMerchantOrderNo`)
- * @param amount 支付金额,单位 **元**(后端内部 `×100` 转「分」提交微信)
- * @param billIds 本笔支付覆盖的账单 id(合并支付传多张)。
- * 后端落 `vm_finance_payment`(status=CREATED)时把它序列化进
- * `request_payload`,支付成功回调据此为**每张账单**落一行
- * `vm_finance_payment_bill`,缺了它回调分摊落库会跳过。
- * @returns `codeUrl`(形如 `weixin://wxpay/bizpayurl?pr=xxx`),前端渲染成二维码供扫
- */
export function createWechatNativeOrder(
orderNo: string,
amount: number,
@@ -443,16 +364,6 @@ export function createWechatNativeOrder(
})
}
-/**
- * 支付宝电脑网站支付下单:`POST /pay/web/alipay/page`,`@SaIgnore`。
- *
- * 入参对应后端 `IFinancePaymentBo`。其 `outTradeNo` / `status` 上的 `@NotBlank`
- * 只声明在 AddGroup / EditGroup 分组上,而控制器用的是默认分组 ⇒ 只传
- * `outTradeNo` + `amount` 即可(`payChannel` / `status` 由后端自己补),不会校验失败。
- *
- * @returns `formBody` —— 后端走 `pageExecute(request, "GET")`,实测内容是
- * **支付宝收银台跳转地址**(`https://…/gateway.do?…`)而不是 HTML 表单;前端两种形态都兜住。
- */
export function createAlipayPageOrder(
outTradeNo: string,
amount: number,
diff --git a/src/api/home.ts b/src/api/home.ts
index 5bd904e..236c091 100644
--- a/src/api/home.ts
+++ b/src/api/home.ts
@@ -1,11 +1,4 @@
-// 首页接口(真实后端绑定)
-// 后端: vermis-maker com.ruoyi.vermins.controller.pc.web.UserSideWebHomePageController
-// 前缀: /web/home-page 鉴权: 公开接口,无需 token
-// 门户入口: com.ruoyi.vermins.controller.pc.web.IPortalEntryUserController(首页快捷入口功能,并入本文件)
//
-// 使用约定(与项目 SKILL.md 一致):
-// 页面/组件禁止直接 import axios,一律经 store 调用本模块的 request。
-// 本文件只放「函数签名 + 请求路径」,不写业务逻辑。
import { request } from '@/utils/request'
import type {
AgreementFormVo,
@@ -17,7 +10,6 @@ import type {
ProjectSubmissionVo,
} from '@/types/business/home'
-/** 项目状态统计 */
export function getProjectStatusCount(): Promise {
return request({
url: '/web/home-page/project-status-count',
@@ -25,7 +17,6 @@ export function getProjectStatusCount(): Promise {
})
}
-/** 业务服务类型列表 */
export function getServiceTypeList(): Promise {
return request({
url: '/web/home-page/service-type-list',
@@ -33,7 +24,6 @@ export function getServiceTypeList(): Promise {
})
}
-/** 业务类型详情(聚合 VO:projectSubmission / projectServiceType / projectSubmissionAttachment / projectSubmissionCatalog) */
export function getServiceTypeDetail(id: number | string): Promise {
return request({
url: `/web/home-page/service-type-detail/${id}`,
@@ -41,7 +31,6 @@ export function getServiceTypeDetail(id: number | string): Promise {
return request({
url: '/web/home-page/carousel-list',
@@ -49,7 +38,6 @@ export function getCarouselList(): Promise {
})
}
-/** 平台介绍(富文本 HTML) */
export function getPlatformIntro(): Promise {
return request({
url: '/web/home-page/platform-intro',
@@ -57,7 +45,6 @@ export function getPlatformIntro(): Promise {
})
}
-/** 联系信息(富文本 HTML) */
export function getContactInfo(): Promise {
return request({
url: '/web/home-page/contact-info',
@@ -65,14 +52,6 @@ export function getContactInfo(): Promise {
})
}
-// 首页「案例库精选」接口(/web/projectCase/mostViewed)按资源归位到 `@/api/cases` 的 getFeaturedCases。
-
-/**
- * 查询用户门户入口列表
- *
- * 登录态返回该用户个性化后的分组结果;匿名返回固定目录。
- * 两组数据由 groupType 区分(1 = 快捷、0 = 其他)。
- */
export function getPortalEntryList(): Promise {
return request({
url: '/vermins/portalEntryUser/list',
@@ -80,14 +59,6 @@ export function getPortalEntryList(): Promise {
})
}
-/**
- * 快捷 / 其他入口互转
- *
- * 后端 add 的入参是 @RequestParam,必须走 query 而非 body。
- *
- * @param id 入口 id
- * @param type 目标分组:1 = 快捷、0 = 其他
- */
export function switchPortalEntryGroup(id: number, type: PortalEntryGroup): Promise {
return request({
url: '/vermins/portalEntryUser/add',
diff --git a/src/api/message.ts b/src/api/message.ts
index 29ef993..324a809 100644
--- a/src/api/message.ts
+++ b/src/api/message.ts
@@ -3,7 +3,6 @@ import type { Message, MessageQuery } from '@/types/business/message'
// TODO(api): 待接口文档到位后,将以下 mock 替换为 request 调用
-/** 消息 mock(可变,已读状态在前端内存中翻转演示) */
const MOCK_MESSAGES: Message[] = [
{
id: 'msg-001',
@@ -107,7 +106,6 @@ function applyFilters(query: MessageQuery): Message[] {
})
}
-/** 消息列表(筛选 + 分页) */
export function getMessageList(query: MessageQuery): Promise> {
const filtered = applyFilters(query)
const start = (query.page - 1) * query.pageSize
@@ -117,13 +115,11 @@ export function getMessageList(query: MessageQuery): Promise
})
}
-/** 消息详情(不存在返回 null) */
export function getMessageDetail(id: string): Promise {
const found = MOCK_MESSAGES.find((item) => item.id === id) ?? null
return Promise.resolve(found ? { ...found } : null)
}
-/** 全部标记已读 */
export function markAllRead(): Promise {
for (const item of MOCK_MESSAGES) {
item.isRead = true
@@ -131,14 +127,12 @@ export function markAllRead(): Promise {
return Promise.resolve()
}
-/** 单条标记已读 */
export function markRead(id: string): Promise {
const found = MOCK_MESSAGES.find((item) => item.id === id)
if (found) found.isRead = true
return Promise.resolve()
}
-/** 各分类消息总数(tab 角标) */
export function getTabCounts(): Promise<{ all: number; 在线客服: number; 状态通知: number; 系统通知: number }> {
const counts = { all: MOCK_MESSAGES.length, 在线客服: 0, 状态通知: 0, 系统通知: 0 }
for (const item of MOCK_MESSAGES) {
@@ -147,7 +141,6 @@ export function getTabCounts(): Promise<{ all: number; 在线客服: number; 状
return Promise.resolve(counts)
}
-/** 未读消息总数(头部角标) */
export function getUnreadCount(): Promise {
return Promise.resolve(MOCK_MESSAGES.filter((item) => !item.isRead).length)
}
diff --git a/src/api/oss.ts b/src/api/oss.ts
index 1d49d5f..7edcc63 100644
--- a/src/api/oss.ts
+++ b/src/api/oss.ts
@@ -1,15 +1,5 @@
import service from '@/utils/request'
-/**
- * 同源预览:后端从 OSS 读取字节后以 `inline` 方式返回,绕开阿里云 OSS 桶「强制下载」配置。
- *
- * ⚠️ 该端点返回的是裸字节(非 `R.ok()` 包装的 `ApiResponse`),故不走统一的
- * `request` 解包逻辑,直接用底层 axios 实例拿 `blob`:请求拦截器已自动带上
- * `Authorization` 与 `clientid` 头,后端据此放行(端点需登录)。
- *
- * 用 blob 而非 `window.open(url)` 的关键:blob URL 自身不带 `Content-Disposition`,
- * 天然绕开 OSS 的强制下载;且全程同源,不受 OSS 跨域 / 强制下载限制。
- */
export async function fetchOssPreviewBlob(ossId: string | number): Promise {
const resp = await service.get(`/web/workOrderDraft/preview/${ossId}`, {
responseType: 'blob',
diff --git a/src/api/profile.ts b/src/api/profile.ts
index 0b3e7b8..21e1446 100644
--- a/src/api/profile.ts
+++ b/src/api/profile.ts
@@ -14,7 +14,6 @@ import type {
// TODO(api): 待接口文档到位后,将以下 mock 替换为 request 调用(页面 → store → api 数据流不变)
-/** 账号资料 mock(可变,昵称/绑定等操作在前端内存中演示) */
const MOCK_PROFILE: Profile = {
nickname: '王永志',
phone: '186****618',
@@ -22,57 +21,48 @@ const MOCK_PROFILE: Profile = {
passwordModifiedAt: '15天前',
}
-/** 获取账号资料 */
export function getProfile(): Promise {
return Promise.resolve({ ...MOCK_PROFILE })
}
-/** 修改昵称 */
export function updateNickname(name: string): Promise {
MOCK_PROFILE.nickname = name
return Promise.resolve({ ...MOCK_PROFILE })
}
-/** 修改密码(验证码 + 新密码) */
export function changePassword(params: ChangePasswordParams): Promise {
MOCK_PROFILE.passwordModifiedAt = '刚刚'
void params
return Promise.resolve()
}
-/** 绑定/换绑手机号 */
export function bindPhone(phone: string, code: string): Promise {
void code
MOCK_PROFILE.phone = phone
return Promise.resolve({ ...MOCK_PROFILE })
}
-/** 绑定/换绑邮箱 */
export function bindEmail(email: string, code: string): Promise {
void code
MOCK_PROFILE.email = email
return Promise.resolve({ ...MOCK_PROFILE })
}
-/** 取消绑定邮箱 */
export function unbindEmail(): Promise {
MOCK_PROFILE.email = ''
return Promise.resolve({ ...MOCK_PROFILE })
}
-/** 注销前安全身份验证 */
export function verifyIdentity(phone: string, code: string): Promise {
void phone
void code
return Promise.resolve()
}
-/** 注销账号 */
export function deleteAccount(): Promise {
return Promise.resolve()
}
-/** 收货地址 mock(isDefault 混合) */
const MOCK_ADDRESSES: Address[] = [
{
id: 'addr-1',
@@ -116,12 +106,10 @@ function paginate(list: T[], query: ListQuery): PageResult {
}
}
-/** 收货地址列表(分页) */
export function getAddresses(query: ListQuery): Promise> {
return Promise.resolve(paginate(MOCK_ADDRESSES, query))
}
-/** 新增收货地址 */
export function createAddress(input: Omit): Promise {
const created: Address = {
...input,
@@ -132,7 +120,6 @@ export function createAddress(input: Omit): Promise
return Promise.resolve({ ...created })
}
-/** 编辑收货地址 */
export function updateAddress(id: string, input: Omit): Promise {
const found = MOCK_ADDRESSES.find((item) => item.id === id)
if (!found) return Promise.reject(new Error('地址不存在'))
@@ -140,14 +127,12 @@ export function updateAddress(id: string, input: Omit {
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 {
for (const item of MOCK_ADDRESSES) {
item.isDefault = item.id === id
@@ -155,7 +140,6 @@ export function setDefaultAddress(id: string): Promise {
return Promise.resolve(MOCK_ADDRESSES.map((item) => ({ ...item })))
}
-/** 我的收藏 mock(4 条已收藏案例,字段与案例库原型一致) */
const MOCK_FAVORITES: Case[] = [
{
id: 'fav-1',
@@ -243,7 +227,6 @@ const MOCK_FAVORITES: Case[] = [
},
]
-/** 我的收藏(关键字/分类筛选 + 分页) */
export function getFavorites(query: FavoritesQuery): Promise> {
const filtered = MOCK_FAVORITES.filter((item) => {
if (query.category !== 'all' && item.category !== query.category) return false
@@ -257,7 +240,6 @@ export function getFavorites(query: FavoritesQuery): Promise> {
})
}
-/** 收藏分类计数(分类快捷按钮角标) */
export function getCaseCounts(): Promise>> {
const counts: Partial> = {
internet: 1,
@@ -268,7 +250,6 @@ export function getCaseCounts(): Promise>>
return Promise.resolve(counts)
}
-/** 资质 mock(状态混合:已认证/审核中/未通过) */
const MOCK_QUALIFICATIONS: Qualification[] = [
{
id: 'qual-1',
@@ -324,12 +305,10 @@ const MOCK_QUALIFICATIONS: Qualification[] = [
},
]
-/** 资质列表(分页) */
export function getQualifications(query: ListQuery): Promise> {
return Promise.resolve(paginate(MOCK_QUALIFICATIONS, query))
}
-/** 新增资质(提交后进入审核中) */
export function createQualification(input: QualificationInput): Promise {
const created: Qualification = {
...input,
@@ -340,7 +319,6 @@ export function createQualification(input: QualificationInput): Promise {
const found = MOCK_QUALIFICATIONS.find((item) => item.id === id)
if (!found) return Promise.reject(new Error('资质不存在'))
@@ -355,20 +333,17 @@ export function updateQualification(id: string, input: QualificationInput): Prom
return Promise.resolve({ ...found })
}
-/** 删除资质 */
export function deleteQualification(id: string): Promise {
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 feedback
return Promise.resolve()
}
-/** 帮助中心 FAQ */
export function getHelpFaqs(): Promise {
return Promise.resolve([
{
diff --git a/src/api/project.ts b/src/api/project.ts
index 0fc7f2a..1f760fd 100644
--- a/src/api/project.ts
+++ b/src/api/project.ts
@@ -12,55 +12,29 @@ import { request, serializeQuery } from '@/utils/request'
import { formatDate } from '@/utils/format'
// ─────────────────────────────────────────────────────────────────────────────
-// 列表:真实接口
// GET /web/requirementPool/list → ProjectRequirementUserController#list
// → ProjectRequirementServiceImpl#queryUserPageList
-// 入参 RdProjectBo + PageQuery;出参 ProjectRequirementAndCountVo
// { requirementPage: { total, rows: RdProjectVo[] }, requirementStatistics: null }
-// 鉴权:需登录态(匿名 401);每请求带 clientid 头(见 utils/request.ts 拦截器)。
-// 筛选参数实测(tools/probe_project_api.py):
// key → like projectName OR projectNo OR requirementDesc
-// businessTypes → IN business_type(**多选**;值是提报表主键 id,不是类型名)
-// status → eq status(码值,见 RdProjectStatus)
-// beginTime/endTime → between create_time(不是 submit_time!)
// pageNum/pageSize → PageQuery
-// ⚠️ 主表已改为**需求表** vm_project_requirement(LEFT JOIN 项目表),未立项的需求也会出现;
-// 未立项行 progress 为 null(显示「—」)、status 回落需求表中的 INITIATING。
-// ⚠️ 列表行的 businessType 是 SQL 里 JOIN 提报表**翻译后的中文名称**(如「互联网软件」),
-// 与筛选参数 businessType(提报表 id)**不是同一口径**,渲染时不能用 typeCounts 反查。
// ─────────────────────────────────────────────────────────────────────────────
// ─────────────────────────────────────────────────────────────────────────────
-// 业务类型筛选条件:真实接口
// GET /web/requirementPool/getFilterConditions
// → ProjectRequirementUserController#getFilterConditions
// → ProjectRequirementServiceImpl#getFilterConditions
-// 出参 ProjectRequirementStatisticsVo:
-// { total: 该用户需求总数,
// businessTypeCounts: [{ businessTypeId, businessTypeLabel, count }] }
-// 口径:**全量、不分页**,所以件数不会随 pageNum/pageSize 变化,适合当筛选栏的固定值域;
-// businessTypeId = vm_project_submission 主键 id(直接回传当 businessType 筛选参数);
-// businessTypeLabel = 该表的 business_type 名称;提报表里没命中的脏数据不计入。
-// ⚠️ /list 响应里的 requirementStatistics 后端仍是注释状态(实测恒 null),统计一律走本端点。
// ─────────────────────────────────────────────────────────────────────────────
-/** 两位补零 */
function pad(value: number): string {
return String(value).padStart(2, '0')
}
-/** Date → 'yyyy-MM-dd HH:mm:ss'(后端 RdProjectBo.beginTime/endTime 是 Date,实测该格式可绑定) */
function toDateTime(date: Date, endOfDay: boolean): string {
const ymd = `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`
return `${ymd} ${endOfDay ? '23:59:59' : '00:00:00'}`
}
-/**
- * 提交时间条件 → 后端 `beginTime` / `endTime`(都落在 `create_time` 上)。
- *
- * 自选区间优先(UI 上两组互斥,这里再兜一层);结束日一律补到 23:59:59,
- * 否则 `endTime=2026-09-30` 会被绑成当天 00:00:00 而漏掉当天数据。
- */
function toTimeRange(query: ProjectQuery): { beginTime?: string; endTime?: string } {
if (query.startDate || query.endDate) {
return {
@@ -77,21 +51,15 @@ function toTimeRange(query: ProjectQuery): { beginTime?: string; endTime?: strin
return { beginTime: toDateTime(start, false), endTime: toDateTime(new Date(), true) }
}
-/** 项目列表(真实接口:服务端筛选 + 分页;业务类型统计走 getProjectFilterConditions) */
export function getProjectList(query: ProjectQuery): Promise {
return request({
url: '/web/requirementPool/list',
method: 'get',
- // 多选数组必须走 serializeQuery,展开成 businessTypes[0]=…&businessTypes[1]=…
- //(与 api/cases.ts 同一做法;不传则走 axios 默认的 businessTypes[]=,实测后端也能绑,
- // 但这里取与文档/案例库一致的索引形式,避免依赖框架默认行为)
paramsSerializer: { serialize: serializeQuery },
params: {
pageNum: query.pageNum,
pageSize: query.pageSize,
- // 空串不出现在 querystring 里,与后端 eqIfText 的「有值才等值匹配」语义一致
key: query.keyword || undefined,
- // 多选:空数组不发;非空由 serializeQuery 展开成 businessTypes[0]=…&businessTypes[1]=…
businessTypes: query.businessTypes.length > 0 ? [...query.businessTypes] : undefined,
status: query.status || undefined,
...toTimeRange(query),
@@ -99,12 +67,6 @@ export function getProjectList(query: ProjectQuery): Promise
})
}
-/**
- * 业务类型筛选条件(左侧筛选栏「业务类型」的值域 + 件数)。
- *
- * 与列表分开取:`/list` 的 `requirementStatistics` 后端恒为 null,统计由本端点单独下发,
- * 且是**全量口径**(不随筛选、分页变化),所以进页面拉一次即可。
- */
export function getProjectFilterConditions(): Promise {
return request({
url: '/web/requirementPool/getFilterConditions',
@@ -112,17 +74,6 @@ export function getProjectFilterConditions(): Promise {
})
}
-/**
- * 已完成项目(申请售后页「项目名称」下拉的候选)。
- *
- * 直接复用列表接口做状态过滤:`status=COMPLETED` 在后端比的是
- * `COALESCE(vm_rd_project.status, vm_project_requirement.status)`,而 `COMPLETED` 只会
- * 出现在**项目表**(未立项的需求是 `INITIATING`)⇒ 结果天然就是「自己名下已立项且已完成的项目」,
- * 与后端申请售后的准入校验(只有 COMPLETED 可申请)口径一致。
- *
- * 售后申请场景下候选量级不大,一次取回较大分页(后端无专用端点);后端默认排序
- * `update_time DESC`。返回行的 `id` = **需求 id**,正是申请接口要传的那个 id。
- */
export function getCompletedProjects(): Promise {
return request({
url: '/web/requirementPool/list',
@@ -136,7 +87,6 @@ export function getCompletedProjects(): Promise {
}
// ─────────────────────────────────────────────────────────────────────────────
-// 详情:真实接口(**4 个页签各一个端点**,同帧并行取回后合并)
// GET /web/requirementPool/get/progress/{id} → ProjectRequirementProgressVo
// GET /web/requirementPool/get/files/{id} → ProjectRequirementFilesVo
// GET /web/requirementPool/get/finance/{id} → ProjectRequirementFinanceVo
@@ -144,26 +94,10 @@ export function getCompletedProjects(): Promise {
// → ProjectRequirementUserController#getProgress / #getFiles / #getFinance / #getAfterSales
// → ProjectRequirementServiceImpl#queryProgress / queryFiles / queryFinance / queryAfterSales
//
-// 4 个 VO 都继承 ProjectRequirementBaseVo(基础信息始终带)⇒ 任一响应里都有项目名 /
-// 编号 / 业务类型 / 状态 / 提交时间,所以详情页顶部信息卡只依赖其中一支即可,切页签不缺数据。
-// 首屏用 getProjectDetailBundle **同帧并行**发 4 个请求(一次到位,避免首屏缺数据);
-// **之后每次点击页签**再用 getProjectDetailTab 只拉对应那一支(点一次 = 一次请求),
-// 响应回填到 store 里的 bundle 后重新映射 ⇒ 页面始终是**最新数据**,不重拉另外三支。
-// 出参由 stores/modules/project.ts 缓存成 bundle,经 utils/projectVo.ts#toProjectDetail
-// 映射成详情页沿用的 Project 形态。
-// ⚠️ id 传的是**需求 id**(vm_project_requirement.id)= 列表行 RdProjectVo.id;
-// 未立项的需求也能查到(项目侧字段为空);不存在 / 非本人 → 后端 4 支 data 均为 null。
// ─────────────────────────────────────────────────────────────────────────────
-/**
- * 详情页签(= `RequirementDetailBundle` 的键名,也就是 4 个端点的后缀)。
- *
- * `views/project/detail.vue` 里的 `DetailTab` 是同一组值;那边不 import 本模块
- * (页面层不直接依赖 api),靠字面量对齐。
- */
export type ProjectDetailTab = 'progress' | 'files' | 'finance' | 'afterSales'
-/** 页签 → 端点(4 支都继承 ProjectRequirementBaseVo,基础信息任一支都有) */
const DETAIL_TAB_URL: Record = {
progress: '/web/requirementPool/get/progress',
files: '/web/requirementPool/get/files',
@@ -171,14 +105,6 @@ const DETAIL_TAB_URL: Record = {
afterSales: '/web/requirementPool/get/afterSales',
}
-/**
- * 单个页签取数(**点一次页签 = 一次请求**,拿该页签的最新数据)。
- *
- * 返回类型按页签收窄:`getProjectDetailTab(id, 'finance')` → `RequirementFinanceVo | null`,
- * 所以调用方可以直接把结果写回 bundle 的对应键。
- *
- * `null` = 需求不存在 / 不属于当前用户(后端 `data: null`),调用方应保留现有数据并提示。
- */
export function getProjectDetailTab(
id: string,
tab: T,
@@ -189,12 +115,6 @@ export function getProjectDetailTab(
})
}
-/**
- * 详情四支并行取回(**首屏用**);任一为 null ⇒ 整个 bundle 为 null。
- *
- * 4 支同源(都查同一行需求),正常不会只缺一支;缺一支即视为「需求不存在 / 非本人」,
- * 详情页走整页空态。
- */
export function getProjectDetailBundle(id: string): Promise {
return Promise.all([
getProjectDetailTab(id, 'progress'),
@@ -208,31 +128,12 @@ export function getProjectDetailBundle(id: string): Promise只传 OSS、不落业务表;返回项带 `ossId`,提交时由后端转存成售后附件。
- * 后端响应没有文件大小,大小取本地 `File.size`。
- */
export function uploadAfterSalesFile(file: File): Promise {
const data = new FormData()
data.append('file', file)
@@ -250,12 +151,6 @@ export function uploadAfterSalesFile(file: File): Promise
}))
}
-/**
- * 申请售后(用户端)。
- *
- * `id` 是**需求 id**(= 详情页路由参数);`payload` 的 `reason` / `note` 分别对应
- * 页面的「问题描述」与「补充备注」。
- */
export function submitAfterSales(
id: string,
payload: AfterSalesPayload,
@@ -268,17 +163,11 @@ export function submitAfterSales(
type: payload.type,
reason: payload.reason,
note: payload.note,
- // 空数组是安全的(后端 `appendAttachments` 对空集合直接 return,不 NPE)
attachmentOssIds: payload.attachmentOssIds,
},
})
}
-/**
- * 撤回售后申请(用户端)。
- *
- * `id` 传**需求 id**;`reason` 是撤回原因(选填,后端会存进 `withdraw_reason`)。
- */
export function cancelAfterSales(id: string, reason = ''): Promise {
return request({
url: '/web/requirementPool/afterSales/withdraw',
diff --git a/src/api/service.ts b/src/api/service.ts
index 092286b..37a430e 100644
--- a/src/api/service.ts
+++ b/src/api/service.ts
@@ -15,7 +15,6 @@ function nowTime(): string {
return `今天 ${pad(date.getHours())}:${pad(date.getMinutes())}`
}
-/** 历史会话(欢迎语 + 用户提问 + 文件资料) */
export function getChatHistory(): Promise {
return Promise.resolve([
{
@@ -40,7 +39,6 @@ export function getChatHistory(): Promise {
])
}
-/** 发送文本消息(echo 用户消息,携带当前时间) */
export function sendChatMessage(content: string): Promise {
return Promise.resolve({
id: nextId('chat'),
@@ -50,7 +48,6 @@ export function sendChatMessage(content: string): Promise {
})
}
-/** 上传聊天文件(生成文件卡片消息) */
export function uploadChatFile(file: File): Promise {
return Promise.resolve({
id: nextId('chat'),
@@ -61,7 +58,6 @@ export function uploadChatFile(file: File): Promise {
})
}
-/** 客服自动回复 */
export function mockAutoReply(): Promise {
return Promise.resolve({
id: nextId('chat'),
diff --git a/src/api/user.ts b/src/api/user.ts
index 620c70c..1ca857e 100644
--- a/src/api/user.ts
+++ b/src/api/user.ts
@@ -1,15 +1,6 @@
-// 用户资料接口(真实后端绑定)
-// 后端:org.dromara.system.controller.system.SysUserController#profile → /system/user/profile
-// 鉴权:需登录态
import { request } from '@/utils/request'
import type { UserProfileVo } from '@/types/business/user'
-/**
- * 当前登录用户资料(需求提报页预填联系人姓名 / 电话)。
- *
- * ⚠️ 后端返回的是 `R
- */
export async function getUserProfile(): Promise {
const data = await request<{ user: UserProfileVo }>({
url: '/system/user/profile',
diff --git a/src/components/AppFooter.vue b/src/components/AppFooter.vue
index 5ba505a..296d47e 100644
--- a/src/components/AppFooter.vue
+++ b/src/components/AppFooter.vue
@@ -3,7 +3,6 @@ import { useSiteStore } from '@/stores/modules/site'
const siteStore = useSiteStore()
-// 设计稿快速导航列原文:首页 / 案例中心 / 需求提报 / 下载 APP / 帮助中心
const quickLinks = [
{ label: '首页', path: '/' },
{ label: '案例中心', path: '/cases' },
@@ -85,10 +84,6 @@ const coreBusiness = [
diff --git a/src/views/home/index.vue b/src/views/home/index.vue
index d675cc4..63d6e14 100644
--- a/src/views/home/index.vue
+++ b/src/views/home/index.vue
@@ -2,7 +2,6 @@
-