项目中心
This commit is contained in:
@@ -1,16 +1,15 @@
|
||||
import type { FileInfo } from '@/types/api'
|
||||
import type {
|
||||
AfterSales,
|
||||
AfterSalesAttachment,
|
||||
AfterSalesPayload,
|
||||
Project,
|
||||
AfterSalesUploadVo,
|
||||
ProjectListResult,
|
||||
ProjectQuery,
|
||||
ProjectStatistics,
|
||||
RequirementDetailVo,
|
||||
RdProjectVo,
|
||||
RequirementDetailBundle,
|
||||
} from '@/types/business/project'
|
||||
import { request } from '@/utils/request'
|
||||
import { request, serializeQuery } from '@/utils/request'
|
||||
import { formatDate } from '@/utils/format'
|
||||
import { toProjectDetail } from '@/utils/projectVo'
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// 列表:真实接口
|
||||
@@ -21,7 +20,7 @@ import { toProjectDetail } from '@/utils/projectVo'
|
||||
// 鉴权:需登录态(匿名 401);每请求带 clientid 头(见 utils/request.ts 拦截器)。
|
||||
// 筛选参数实测(tools/probe_project_api.py):
|
||||
// key → like projectName OR projectNo OR requirementDesc
|
||||
// businessType → eq business_type(值是提报表主键 id,不是类型名)
|
||||
// businessTypes → IN business_type(**多选**;值是提报表主键 id,不是类型名)
|
||||
// status → eq status(码值,见 RdProjectStatus)
|
||||
// beginTime/endTime → between create_time(不是 submit_time!)
|
||||
// pageNum/pageSize → PageQuery
|
||||
@@ -83,12 +82,17 @@ export function getProjectList(query: ProjectQuery): Promise<ProjectListResult>
|
||||
return request<ProjectListResult>({
|
||||
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,
|
||||
businessType: query.businessType || undefined,
|
||||
// 多选:空数组不发;非空由 serializeQuery 展开成 businessTypes[0]=…&businessTypes[1]=…
|
||||
businessTypes: query.businessTypes.length > 0 ? [...query.businessTypes] : undefined,
|
||||
status: query.status || undefined,
|
||||
...toTimeRange(query),
|
||||
},
|
||||
@@ -108,240 +112,177 @@ export function getProjectFilterConditions(): Promise<ProjectStatistics> {
|
||||
})
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// 详情:真实接口
|
||||
// GET /web/requirementPool/get/{id} → ProjectRequirementUserController#get
|
||||
// → ProjectRequirementServiceImpl#queryRequirementByUserId
|
||||
// 出参 ProjectRequirementUserVo,经 utils/projectVo.ts 映射成详情页沿用的 Project 形态。
|
||||
// ⚠️ id 传的是**需求 id**(vm_project_requirement.id)= 列表行 RdProjectVo.id。
|
||||
// 未立项的需求也能查到(项目侧字段为空);不存在 / 非本人 → 后端 data 为 null。
|
||||
//
|
||||
// 文件 / 售后:**仍是前端 mock** —— 该 Controller 只有 create / list / get /
|
||||
// serviceTypeList 四个接口,没有附件上传、售后提交/取消的后端实现。
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/** 构造 mock 文件信息 */
|
||||
function mockFile(name: string, size: number, uploadTime: string): FileInfo {
|
||||
return { name, size, uploadTime, url: '' }
|
||||
}
|
||||
|
||||
/** 详情 mock 所属项目 id */
|
||||
const DETAIL_ID = 'project-004'
|
||||
|
||||
/** 项目列表 mock(6 条,覆盖全部状态,internet/iot 混合)——仅详情页链路在用 */
|
||||
const MOCK_PROJECTS: Project[] = [
|
||||
{
|
||||
id: 'project-001',
|
||||
projectNo: 'P8K2M202408001',
|
||||
projectName: '某大型银行数字化转型方案',
|
||||
businessType: 'internet',
|
||||
progress: 64,
|
||||
status: '待立项',
|
||||
submitTime: '2026-8-17 14:00',
|
||||
milestones: [],
|
||||
team: [],
|
||||
files: [],
|
||||
paymentPlans: [],
|
||||
invoiceRecords: [],
|
||||
},
|
||||
{
|
||||
id: 'project-002',
|
||||
projectNo: 'P8K2M202408002',
|
||||
projectName: '智慧城市大数据平台建设项目',
|
||||
businessType: 'iot',
|
||||
progress: 64,
|
||||
status: '待验收',
|
||||
submitTime: '2026-8-17 14:00',
|
||||
milestones: [],
|
||||
team: [],
|
||||
files: [],
|
||||
paymentPlans: [],
|
||||
invoiceRecords: [],
|
||||
},
|
||||
{
|
||||
id: 'project-003',
|
||||
projectNo: 'P8K2M202408003',
|
||||
projectName: '三甲医院指挥医疗信息化系统',
|
||||
businessType: 'internet',
|
||||
progress: 64,
|
||||
status: '已完成',
|
||||
submitTime: '2026-8-17 14:00',
|
||||
milestones: [],
|
||||
team: [],
|
||||
files: [],
|
||||
paymentPlans: [],
|
||||
invoiceRecords: [],
|
||||
},
|
||||
{
|
||||
id: DETAIL_ID,
|
||||
projectNo: '20260813RJ251545',
|
||||
projectName: '社区康养智能服务系统',
|
||||
businessType: 'internet',
|
||||
progress: 64,
|
||||
status: '进行中',
|
||||
submitTime: '2026-8-17 14:00',
|
||||
milestones: [],
|
||||
team: [],
|
||||
files: [],
|
||||
paymentPlans: [],
|
||||
invoiceRecords: [],
|
||||
},
|
||||
{
|
||||
id: 'project-005',
|
||||
projectNo: 'P8K2M202408005',
|
||||
projectName: '智能仓储物流分拣系统',
|
||||
businessType: 'iot',
|
||||
progress: 64,
|
||||
status: '售后中',
|
||||
submitTime: '2026-8-17 14:00',
|
||||
milestones: [],
|
||||
team: [],
|
||||
files: [],
|
||||
paymentPlans: [],
|
||||
invoiceRecords: [],
|
||||
afterSales: {
|
||||
status: '处理中',
|
||||
type: 'BUG问题',
|
||||
description: '分拣识别偶发误判,需要排查',
|
||||
remark: '',
|
||||
attachments: [],
|
||||
createTime: '2026-8-19 17:00',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'project-006',
|
||||
projectNo: 'P8K2M202408006',
|
||||
projectName: '新能源电站运维监控平台',
|
||||
businessType: 'internet',
|
||||
progress: 64,
|
||||
status: '已取消',
|
||||
submitTime: '2026-8-17 14:00',
|
||||
milestones: [],
|
||||
team: [],
|
||||
files: [],
|
||||
paymentPlans: [],
|
||||
invoiceRecords: [],
|
||||
},
|
||||
]
|
||||
|
||||
/** 项目详情 mock(社区康养智能服务系统) */
|
||||
const PROJECT_DETAIL: Project = {
|
||||
...MOCK_PROJECTS[3],
|
||||
progress: 65,
|
||||
startTime: '2026-8-13 11:04:12',
|
||||
endTime: '2026-10-30 18:00:00',
|
||||
milestones: [
|
||||
{ name: '需求确认', status: '已完成', time: '2026-8-13 11:04:12' },
|
||||
{ name: '原型设计', status: '已完成', time: '2026-8-13 11:04:12' },
|
||||
{ name: '开发实现', status: '进行中' },
|
||||
{ name: '测试验收', status: '待开始' },
|
||||
{ name: '项目交付', status: '待开始' },
|
||||
],
|
||||
team: [
|
||||
{ role: '项目经理', name: '张三', avatarChar: '张' },
|
||||
{ role: '项目经理', name: '张三', avatarChar: '张' },
|
||||
],
|
||||
files: [
|
||||
mockFile('项目需求规格说明书.pdf', 2516582, '2026-08-19 17:00'),
|
||||
mockFile('项目需求说明书.word', 1887437, '2026-08-19 17:00'),
|
||||
],
|
||||
paymentPlans: [
|
||||
{
|
||||
id: 'bill-001',
|
||||
planName: '第一期·预付款(比例33%)',
|
||||
billNo: '20260813ZZ251245',
|
||||
amount: 20100,
|
||||
status: '已支付',
|
||||
tradeNo: 'T20260819153035678K2M001',
|
||||
projectName: '社区康养智能服务系统',
|
||||
},
|
||||
{
|
||||
id: 'bill-002',
|
||||
planName: '第二期·付款(比例33%)',
|
||||
billNo: '20260813ZZ251245',
|
||||
amount: 20100,
|
||||
status: '待支付',
|
||||
projectName: '社区康养智能服务系统',
|
||||
},
|
||||
{
|
||||
id: 'bill-003',
|
||||
planName: '第三期·尾款(比例33%)',
|
||||
billNo: '20260813ZZ251245',
|
||||
amount: 20100,
|
||||
status: '未到期',
|
||||
projectName: '社区康养智能服务系统',
|
||||
},
|
||||
],
|
||||
invoiceRecords: [
|
||||
mockFile('增值税专用发票.pdf', 325120, '2026-08-19 17:00'),
|
||||
mockFile('电子回单.jpg', 186368, '2026-08-19 17:00'),
|
||||
],
|
||||
contractFile: mockFile('社区康养智能服务系统开发合同.pdf', 1039360, '2026-08-19 17:00'),
|
||||
afterSales: {
|
||||
status: '处理中',
|
||||
type: 'BUG问题',
|
||||
description: '具体请看清单',
|
||||
remark: '',
|
||||
attachments: [],
|
||||
createTime: '2026-8-19 17:00',
|
||||
},
|
||||
}
|
||||
|
||||
/** 项目详情(真实接口;不存在 / 非本人需求返回 null) */
|
||||
export function getProjectDetail(id: string): Promise<Project | null> {
|
||||
return request<RequirementDetailVo | null>({
|
||||
url: `/web/requirementPool/get/${id}`,
|
||||
/**
|
||||
* 已完成项目(申请售后页「项目名称」下拉的候选)。
|
||||
*
|
||||
* <p>直接复用列表接口做状态过滤:`status=COMPLETED` 在后端比的是
|
||||
* `COALESCE(vm_rd_project.status, vm_project_requirement.status)`,而 `COMPLETED` 只会
|
||||
* 出现在**项目表**(未立项的需求是 `INITIATING`)⇒ 结果天然就是「自己名下已立项且已完成的项目」,
|
||||
* 与后端申请售后的准入校验(只有 COMPLETED 可申请)口径一致。</p>
|
||||
*
|
||||
* <p>售后申请场景下候选量级不大,一次取回较大分页(后端无专用端点);后端默认排序
|
||||
* `update_time DESC`。返回行的 `id` = **需求 id**,正是申请接口要传的那个 id。</p>
|
||||
*/
|
||||
export function getCompletedProjects(): Promise<RdProjectVo[]> {
|
||||
return request<ProjectListResult>({
|
||||
url: '/web/requirementPool/list',
|
||||
method: 'get',
|
||||
}).then((vo) => (vo ? toProjectDetail(vo) : null))
|
||||
params: {
|
||||
pageNum: 1,
|
||||
pageSize: 200,
|
||||
status: 'COMPLETED',
|
||||
},
|
||||
}).then((result) => result?.requirementPage?.rows ?? [])
|
||||
}
|
||||
|
||||
/** 上传项目文件(mock:追加进详情文件列表) */
|
||||
export function uploadProjectFile(file: File): Promise<FileInfo> {
|
||||
const info: FileInfo = {
|
||||
name: file.name,
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// 详情:真实接口(**4 个页签各一个端点**,同帧并行取回后合并)
|
||||
// GET /web/requirementPool/get/progress/{id} → ProjectRequirementProgressVo
|
||||
// GET /web/requirementPool/get/files/{id} → ProjectRequirementFilesVo
|
||||
// GET /web/requirementPool/get/finance/{id} → ProjectRequirementFinanceVo
|
||||
// GET /web/requirementPool/get/afterSales/{id} → ProjectRequirementAfterSalesVo
|
||||
// → 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 个端点的后缀)。
|
||||
*
|
||||
* <p>`views/project/detail.vue` 里的 `DetailTab` 是同一组值;那边不 import 本模块
|
||||
* (页面层不直接依赖 api),靠字面量对齐。</p>
|
||||
*/
|
||||
export type ProjectDetailTab = 'progress' | 'files' | 'finance' | 'afterSales'
|
||||
|
||||
/** 页签 → 端点(4 支都继承 ProjectRequirementBaseVo,基础信息任一支都有) */
|
||||
const DETAIL_TAB_URL: Record<ProjectDetailTab, string> = {
|
||||
progress: '/web/requirementPool/get/progress',
|
||||
files: '/web/requirementPool/get/files',
|
||||
finance: '/web/requirementPool/get/finance',
|
||||
afterSales: '/web/requirementPool/get/afterSales',
|
||||
}
|
||||
|
||||
/**
|
||||
* 单个页签取数(**点一次页签 = 一次请求**,拿该页签的最新数据)。
|
||||
*
|
||||
* <p>返回类型按页签收窄:`getProjectDetailTab(id, 'finance')` → `RequirementFinanceVo | null`,
|
||||
* 所以调用方可以直接把结果写回 bundle 的对应键。</p>
|
||||
*
|
||||
* <p>`null` = 需求不存在 / 不属于当前用户(后端 `data: null`),调用方应保留现有数据并提示。</p>
|
||||
*/
|
||||
export function getProjectDetailTab<T extends ProjectDetailTab>(
|
||||
id: string,
|
||||
tab: T,
|
||||
): Promise<RequirementDetailBundle[T] | null> {
|
||||
return request<RequirementDetailBundle[T] | null>({
|
||||
url: `${DETAIL_TAB_URL[tab]}/${id}`,
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 详情四支并行取回(**首屏用**);任一为 null ⇒ 整个 bundle 为 null。
|
||||
*
|
||||
* <p>4 支同源(都查同一行需求),正常不会只缺一支;缺一支即视为「需求不存在 / 非本人」,
|
||||
* 详情页走整页空态。</p>
|
||||
*/
|
||||
export function getProjectDetailBundle(id: string): Promise<RequirementDetailBundle | null> {
|
||||
return Promise.all([
|
||||
getProjectDetailTab(id, 'progress'),
|
||||
getProjectDetailTab(id, 'files'),
|
||||
getProjectDetailTab(id, 'finance'),
|
||||
getProjectDetailTab(id, 'afterSales'),
|
||||
]).then(([progress, files, finance, afterSales]) => {
|
||||
if (!progress || !files || !finance || !afterSales) return null
|
||||
return { progress, files, finance, afterSales }
|
||||
})
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// 售后(**真实接口**)
|
||||
// 申请 POST /web/requirementPool/afterSales/request body ProjectRequirementActionBo
|
||||
// 撤回 POST /web/requirementPool/afterSales/withdraw body ProjectRequirementActionBo
|
||||
// → ProjectRequirementUserController#requestAfterSale / #withdrawAfterSale
|
||||
// → ProjectRequirementServiceImpl#requestAfterSale / #withdrawAfterSale
|
||||
// 附件上传 POST /web/workOrderDraft/upload(multipart,字段名 `file`)—— 只传 OSS 不落业务表;
|
||||
// 提交时下发 `attachmentOssIds`,后端转存进 `vm_project_requirement_attachment`
|
||||
// (phase = AFTER_SALE、target_id = 售后工单 id),OSS 文件不重复上传。
|
||||
//
|
||||
// ⚠️ 后端业务校验(失败抛 ServiceException,由统一 request 层弹提示):
|
||||
// · 只有「已完成(COMPLETED)」的项目能申请售后;
|
||||
// · 已有 REQUESTED / IN_PROGRESS 的售后时拒绝重复申请;
|
||||
// · 撤回只允许 REQUESTED 状态,撤回后售后置 WITHDRAWN、项目回到已完成。
|
||||
// ⚠️ 撤回接口收的是**需求 id**(不是售后工单 id),与后端 `checkOwner` 的校验口径一致。
|
||||
//
|
||||
// ⚠️ 详情页「项目文件」页签的上传 / 删除**仍无用户端接口**(上传入口在需求提报页),
|
||||
// 所以这里不再保留 mock —— 详情数据来自真实接口,塞本地假数据会让刷新前后不一致。
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* 上传售后附件(复用需求提报的 OSS 上传口)。
|
||||
*
|
||||
* <p>只传 OSS、不落业务表;返回项带 `ossId`,提交时由后端转存成售后附件。
|
||||
* 后端响应没有文件大小,大小取本地 `File.size`。</p>
|
||||
*/
|
||||
export function uploadAfterSalesFile(file: File): Promise<AfterSalesAttachment> {
|
||||
const data = new FormData()
|
||||
data.append('file', file)
|
||||
return request<AfterSalesUploadVo>({
|
||||
url: '/web/workOrderDraft/upload',
|
||||
method: 'post',
|
||||
data,
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
}).then((vo) => ({
|
||||
ossId: vo.ossId,
|
||||
name: vo.originalName || file.name,
|
||||
size: file.size,
|
||||
url: vo.url,
|
||||
uploadTime: formatDate(new Date()),
|
||||
url: '',
|
||||
}
|
||||
PROJECT_DETAIL.files.push(info)
|
||||
return Promise.resolve({ ...info })
|
||||
}))
|
||||
}
|
||||
|
||||
/** 删除项目文件(mock:按索引从详情文件列表移除) */
|
||||
export function deleteProjectFile(index: number): Promise<void> {
|
||||
if (index >= 0 && index < PROJECT_DETAIL.files.length) {
|
||||
PROJECT_DETAIL.files.splice(index, 1)
|
||||
}
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
/** 提交售后工单(mock) */
|
||||
/**
|
||||
* 申请售后(用户端)。
|
||||
*
|
||||
* <p>`id` 是**需求 id**(= 详情页路由参数);`payload` 的 `reason` / `note` 分别对应
|
||||
* 页面的「问题描述」与「补充备注」。</p>
|
||||
*/
|
||||
export function submitAfterSales(
|
||||
projectId: string,
|
||||
id: string,
|
||||
payload: AfterSalesPayload,
|
||||
): Promise<AfterSales> {
|
||||
const result: AfterSales = {
|
||||
status: '处理中',
|
||||
type: payload.type,
|
||||
description: payload.description,
|
||||
remark: payload.remark,
|
||||
attachments: [...payload.attachments],
|
||||
createTime: formatDate(new Date()),
|
||||
}
|
||||
if (projectId === DETAIL_ID) PROJECT_DETAIL.afterSales = result
|
||||
return Promise.resolve({ ...result, attachments: [...result.attachments] })
|
||||
): Promise<void> {
|
||||
return request<void>({
|
||||
url: '/web/requirementPool/afterSales/request',
|
||||
method: 'post',
|
||||
data: {
|
||||
id,
|
||||
type: payload.type,
|
||||
reason: payload.reason,
|
||||
note: payload.note,
|
||||
// 空数组是安全的(后端 `appendAttachments` 对空集合直接 return,不 NPE)
|
||||
attachmentOssIds: payload.attachmentOssIds,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/** 取消售后工单(mock) */
|
||||
export function cancelAfterSales(projectId: string): Promise<AfterSales> {
|
||||
const result: AfterSales = {
|
||||
status: '无',
|
||||
type: '',
|
||||
description: '',
|
||||
remark: '',
|
||||
attachments: [],
|
||||
createTime: '',
|
||||
}
|
||||
if (projectId === DETAIL_ID) PROJECT_DETAIL.afterSales = result
|
||||
return Promise.resolve({ ...result })
|
||||
/**
|
||||
* 撤回售后申请(用户端)。
|
||||
*
|
||||
* <p>`id` 传**需求 id**;`reason` 是撤回原因(选填,后端会存进 `withdraw_reason`)。</p>
|
||||
*/
|
||||
export function cancelAfterSales(id: string, reason = ''): Promise<void> {
|
||||
return request<void>({
|
||||
url: '/web/requirementPool/afterSales/withdraw',
|
||||
method: 'post',
|
||||
data: { id, reason },
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
// 用户web端首页接口(真实后端绑定)
|
||||
// 后端: vermis-maker com.ruoyi.vermins.controller.pc.web.UserSideWebHomePageController
|
||||
// 前缀: /web/home-page 鉴权: 公开接口,无需 token
|
||||
//
|
||||
// 使用约定(与项目 SKILL.md 一致):
|
||||
// 页面/组件禁止直接 import axios,一律经 store 调用本模块的 request<T>。
|
||||
// 本文件只放「函数签名 + 请求路径」,不写业务逻辑。
|
||||
import { request } from '@/utils/request'
|
||||
import type {
|
||||
ProjectStatusCount,
|
||||
ProjectSubmissionVo,
|
||||
BannerVo,
|
||||
AgreementFormVo,
|
||||
} from '@/types/web/home'
|
||||
|
||||
/** 项目状态统计 */
|
||||
export function getProjectStatusCount(): Promise<ProjectStatusCount> {
|
||||
return request<ProjectStatusCount>({
|
||||
url: '/web/home-page/project-status-count',
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
/** 业务服务类型列表 */
|
||||
export function getServiceTypeList(): Promise<ProjectSubmissionVo[]> {
|
||||
return request<ProjectSubmissionVo[]>({
|
||||
url: '/web/home-page/service-type-list',
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
/** 业务类型详情 */
|
||||
export function getServiceTypeDetail(id: number | string): Promise<ProjectSubmissionVo> {
|
||||
return request<ProjectSubmissionVo>({
|
||||
url: `/web/home-page/service-type-detail/${id}`,
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
/** 轮播图列表 */
|
||||
export function getCarouselList(): Promise<BannerVo[]> {
|
||||
return request<BannerVo[]>({
|
||||
url: '/web/home-page/carousel-list',
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
/** 平台介绍(富文本 HTML) */
|
||||
export function getPlatformIntro(): Promise<AgreementFormVo> {
|
||||
return request<AgreementFormVo>({
|
||||
url: '/web/home-page/platform-intro',
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
/** 联系信息(富文本 HTML) */
|
||||
export function getContactInfo(): Promise<AgreementFormVo> {
|
||||
return request<AgreementFormVo>({
|
||||
url: '/web/home-page/contact-info',
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user