init: 橘视厅酒店版会员系统前端

This commit is contained in:
zhaogd
2026-07-26 12:54:46 +08:00
commit 690568861b
243 changed files with 42311 additions and 0 deletions

109
src/api/card.ts Executable file
View File

@@ -0,0 +1,109 @@
import http from '@/utils/httpRequest'
import type { ApiResponse, PageParams, PageResult } from '@/types/api'
/**
* 卡信息
*/
export interface CardInfo {
id: number
cardNo: string
cardType: string
status: string
activeAt?: string
expireAt?: string
[key: string]: any
}
/**
* 卡列表参数
*/
export interface CardListParams extends PageParams {
cardNo?: string
cardCode?: string
status?: string
cardType?: string
inventoryStatus?: string
usageStatus?: string
beginActiveAt?: string
endActiveAt?: string
}
/**
* 卡导入数据
*/
export interface CardImportData {
cardType: string
items: Array<{
cardNo: string
expireAt?: string
}>
}
/**
* 卡导入预览结果
*/
export interface CardImportPreview {
total: number
valid: number
invalid: number
items: Array<{
cardNo: string
valid: boolean
reason?: string
}>
}
/** 卡详情 */
export function getCardInfo(cardId: number | string): Promise<ApiResponse<CardInfo>> {
return http.get(http.adornUrl(`/sys/card/info/${cardId}`), { params: http.adornParams() })
}
/** 卡列表(分页) */
export function getCardList(params?: CardListParams): Promise<ApiResponse<PageResult<CardInfo>>> {
return http
.get(http.adornUrl('/sys/card/list'), { params: http.adornParams(params || {}) })
.then((res) => res.data)
}
/** 卡批量导入 */
export function importCard(data: CardImportData): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/card/import'), http.adornData(data, false))
}
/** 卡预导入 */
export function importCardPreview(data: CardImportData): Promise<ApiResponse<CardImportPreview>> {
return http.post(http.adornUrl('/sys/card/import/preview'), http.adornData(data, false))
}
/** 卡导入批次(分页) */
export function getImportBatchList(params?: PageParams): Promise<ApiResponse<PageResult<any>>> {
return http.get(http.adornUrl('/sys/card/import-batches'), { params: http.adornParams(params || {}) })
}
/** 某导入批次下的卡(分页) */
export function getImportBatchCards(
importBatchId: number | string,
params?: PageParams
): Promise<ApiResponse<PageResult<CardInfo>>> {
return http.get(
http.adornUrl(`/sys/card/import-batches/${importBatchId}/cards`),
{ params: http.adornParams(params || {}) }
)
}
/** 临期未使用卡(剩余激活时间 ≤ 31 天) */
export interface NearExpiryUnusedCard {
id: number
cardNo: string
cardType: string
orgId: number
orgName: string
activationExpireAt: string
remainingActivationDays: number
}
export function getNearExpiryUnusedCards(): Promise<ApiResponse<{ list: NearExpiryUnusedCard[] }>> {
return http
.get(http.adornUrl('/sys/card/near-expiry-unused'), { params: http.adornParams() })
.then((res) => res.data)
}

60
src/api/cardAllocation.ts Executable file
View File

@@ -0,0 +1,60 @@
import type { AxiosResponse } from 'axios'
import http from '@/utils/httpRequest'
import type { ApiResponse } from '@/types/api'
/**
* 卡分配明细参数
*/
export interface CardAllocationDetailParams {
startDate: string
endDate: string
orgId?: string | number
}
/**
* 卡分配明细项
*/
export interface CardAllocationDetailItem {
bizDate: string
counterpartyOrgId: number
counterpartyOrgName: string
inCount: number
outCount: number
[key: string]: any
}
/** 详情接口 data 中可选字段(蛇形 / 驼峰会一并兼容解析) */
export interface CardAllocationDetailPayload {
cardFlowBreakdown?: CardAllocationDetailItem[]
card_flow_breakdown?: CardAllocationDetailItem[]
byType?: Array<{
cardType: string
cardTypeName?: string
allocatableCount?: number
}>
}
/**
* 卡分配详情:data.cardFlowBreakdown(bizDate、counterpartyOrg*、inCount、outCount);可选 byType 等。
* @param params yyyy-MM-dd;可选 orgId
*/
export function getCardAllocationDetail(
params: CardAllocationDetailParams
): Promise<AxiosResponse<ApiResponse<CardAllocationDetailPayload>>> {
return http.get(http.adornUrl('/sys/card-allocation/detail'), {
params: http.adornParams(params || {})
})
}
/**
* 卡分配详情导出(Excel);查询参数与 getCardAllocationDetail 一致。
* @param params yyyy-MM-dd;可选 orgId
*/
export function exportCardAllocationDetail(
params: CardAllocationDetailParams
): Promise<AxiosResponse<Blob>> {
return http.get(http.adornUrl('/sys/card-allocation/detail/export'), {
params: http.adornParams(params || {}),
responseType: 'blob'
})
}

145
src/api/cardFlow.ts Executable file
View File

@@ -0,0 +1,145 @@
import type { AxiosResponse } from 'axios'
import http from '@/utils/httpRequest'
import type { ApiResponse } from '@/types/api'
/**
* POST /sys/card-flow/allocate — 与后端 CardFlowAllocateRequest 对齐
*/
export interface CardFlowAllocateRequest {
/** 分配数量(≥1) */
count: number
/** YEAR / QUARTER / MONTH / WEEK / OTHER */
cardType: string
/** 目标渠道/代理商/门店组织 ID */
toChannelOrgId: number
/** 分配到门店时的权益激活码(可选,不传则服务端生成) */
activationCode?: string
}
/**
* 卡转移 / 回退等通用请求体(allocate 请用 CardFlowAllocateRequest)
*/
export interface CardFlowData {
cardNos?: string[]
count?: number
fromOrgId?: number
toOrgId?: number
cardType?: string
importBatchId?: number
[key: string]: any
}
/** 卡分配/销售 */
export function allocateCard(data: CardFlowAllocateRequest): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/card-flow/allocate'), http.adornData(data))
}
/** 卡转移 */
export function transferCard(data: CardFlowData): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/card-flow/transfer'), http.adornData(data))
}
/** 卡回退(渠道/代理商按数量回退到上级,请求体:{ count, fromOrgId, cardType }) */
export function rollbackCard(data: CardFlowData): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/card-flow/rollback-to-parent-by-count'), http.adornData(data))
}
/** 无效卡按导入批次回退至渠道,请求体:{ importBatchId } */
export function rollbackInvalidImportBatchToChannel(
data: Pick<CardFlowData, 'importBatchId'>
): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/card-flow/rollback-invalid-import-batch-to-channel'), http.adornData(data))
}
/** GET /sys/card-flow/allocation-orders/search 查询参数(fromOrgId / toOrgId 至少填一个) */
export interface AllocationOrderSearchParams {
fromOrgId?: number
toOrgId?: number
page?: number
limit?: number
}
/** 分配单搜索列表项 */
export interface AllocationOrderSearchItem {
id: number
orderNo: string
fromOrgId: number
fromOrgName: string
fromOrgType: string
toOrgId: number
toOrgName: string
toOrgType: string
totalCount: number
status: string
createdAt: string
}
/** 分配单搜索响应(字段可能在 data 内或响应根级) */
export interface AllocationOrderSearchPayload {
fromOrgId?: number
toOrgId?: number
items?: AllocationOrderSearchItem[]
totalCount?: number
page?: {
list?: AllocationOrderSearchItem[]
totalCount?: number
}
}
/** GET /sys/card-flow/allocation-order-final-destination-stat 查询参数 */
export interface AllocationOrderFinalDestinationStatsParams {
/** 分配单 ID */
allocationOrderId: number
page?: number
limit?: number
}
/** 各组织最终去向统计行 */
export interface AllocationOrderFinalDestinationStatItem {
orgId: number
orgName: string
orgType: string
count: number
}
/** 分配单卡最终去向统计响应(字段可能在 data 内或响应根级) */
export interface AllocationOrderFinalDestinationStatsPayload {
allocationOrderId: number
orderNo: string
fromOrgId: number
toOrgId: number
/** 卡总数(与 cardTotalCount 同义) */
totalCount?: number
cardTotalCount?: number
totalCountOnOrder?: number
items?: AllocationOrderFinalDestinationStatItem[]
page?: {
list?: AllocationOrderFinalDestinationStatItem[]
totalCount?: number
pageSize?: number
totalPage?: number
currPage?: number
}
}
/**
* 按流出/流入组织搜索分配单
*/
export function searchAllocationOrders(
params: AllocationOrderSearchParams
): Promise<AxiosResponse<ApiResponse<AllocationOrderSearchPayload>>> {
return http.get(http.adornUrl('/sys/card-flow/allocation-orders/search'), {
params: http.adornParams(params)
})
}
/**
* 按分配单 ID 统计卡最终流向(card_allocation_log → card.org_id 分组)
*/
export function getAllocationOrderFinalDestinationStats(
params: AllocationOrderFinalDestinationStatsParams
): Promise<AxiosResponse<ApiResponse<AllocationOrderFinalDestinationStatsPayload>>> {
return http.get(http.adornUrl('/sys/card-flow/allocation-order-final-destination-stats'), {
params: http.adornParams(params)
})
}

75
src/api/contract.ts Executable file
View File

@@ -0,0 +1,75 @@
import http from '@/utils/httpRequest'
import type { ApiResponse, PageParams, PageResult } from '@/types/api'
/**
* 激活码信息
*/
export interface ActivationCode {
id: number
code: string
status: string
maxDeviceCount?: number
[key: string]: any
}
/**
* 合同查询参数
*/
export interface ContractQueryParams extends PageParams {
storeOrgId?: number
[key: string]: any
}
/**
* 保存激活码数据(常与合同页对齐:code、cardType、maxDeviceCount)
*/
export interface SaveActivationCodeData {
code?: string
maxDeviceCount?: number
[key: string]: any
}
/** 按门店查询合同/激活码列表 */
export function getContractByStore(data: ContractQueryParams): Promise<ApiResponse<PageResult<any>>> {
return http.post(http.adornUrl('/manage/contract/by-store'), http.adornData(data))
}
/** 获取合同下激活码 */
export function getContractActivationCode(
storeOrgId: number
): Promise<ApiResponse<ActivationCode[]>> {
return http.get(http.adornUrl(`/manage/contract/${storeOrgId}/activation-code`), { params: http.adornParams() })
}
/** 获取合同下激活码(传 contractId) */
export function getActivationCodeByContractId(
contractId: number
): Promise<ApiResponse<ActivationCode[]>> {
return http.get(http.adornUrl(`/manage/contract/${contractId}/activation-code`), { params: http.adornParams() })
}
/** 重新生成激活码 */
export function regenerateActivationCode(cacId: number): Promise<ApiResponse<any>> {
return http.post(http.adornUrl(`/manage/contract/activation-code/${cacId}/regenerate-code`), http.adornData({}))
}
/** 获取激活码最大设备数 */
export function getActivationCodeMaxDeviceCount(storeOrgId: number): Promise<ApiResponse<number>> {
return http.get(http.adornUrl(`/manage/contract/activation-code/${storeOrgId}/max-device-count`), { params: http.adornParams() })
}
/** 更新激活码最大设备数(PUT);路径参数为门店组织 ID,非 CAC 主键 */
export function updateActivationCodeMaxDeviceCount(
storeOrgId: number,
data: { maxDeviceCount: number } & Record<string, any>
): Promise<ApiResponse<any>> {
return http.put(http.adornUrl(`/manage/contract/activation-code/${storeOrgId}/max-device-count`), http.adornData(data))
}
/** 创建/保存门店下权益激活码(POST) */
export function saveStoreActivationCode(
storeOrgId: number,
data: SaveActivationCodeData
): Promise<ApiResponse<any>> {
return http.post(http.adornUrl(`/manage/contract/${storeOrgId}/activation-code`), http.adornData(data))
}

231
src/api/device.ts Executable file
View File

@@ -0,0 +1,231 @@
import http from '@/utils/httpRequest'
import type { ApiResponse, PageParams, PageResult } from '@/types/api'
/**
* 设备信息
*/
export interface DeviceInfo {
id: number
deviceSn?: string
sn?: string
deviceUid?: string
uid?: string
mac?: string
status?: string
bindCardNo?: string | null
bindCardActiveAt?: string | null
bindCardPresetAt?: string | null
bindCardExpireAt?: string | null
bindCardStatus?: string | null
[key: string]: any
}
/**
* 设备列表查询参数
*/
export interface DeviceListParams extends PageParams {
storeOrgId?: number
mac?: string
cardStatus?: 'UNBOUND' | 'PRESET' | 'ACTIVATING' | 'ACTIVATION_FAILED' | 'ACTIVE' | 'EXPIRED'
[key: string]: any
}
/**
* 设备导入数据
*/
export interface DeviceImportData {
storeOrgId: number
cardType: string
items: Array<{
mac?: string
deviceSn?: string
deviceUid?: string
roomNo?: string
}>
}
/**
* 设备批量预置数据
*/
export interface DeviceBatchPresetData {
storeOrgId: number
cardType: string
items: Array<{
deviceId?: number
mac?: string
deviceSn?: string
deviceUid?: string
}>
}
/** 设备列表:page、limit、storeOrgId(可选)、mac(模糊)、cardStatus */
export function getDeviceList(params?: DeviceListParams): Promise<ApiResponse<PageResult<DeviceInfo>>> {
return http.get(http.adornUrl('/sys/device/list'), { params: http.adornParams(params || {}) })
}
/** 导出设备列表 Excel */
export function exportDeviceListExcel(params?: DeviceListParams): Promise<Blob> {
return http.get(http.adornUrl('/sys/device/export-excel'), {
params: http.adornParams(params || {}),
responseType: 'blob'
})
}
/** 重复 MAC/设备 SN 列表 */
export function getDuplicateMacDeviceSnList(
params?: DeviceListParams
): Promise<ApiResponse<PageResult<DeviceInfo>>> {
return http.get(http.adornUrl('/sys/device/duplicate-mac'), { params: http.adornParams(params || {}) })
}
/** 临期设备(年卡等即将到期)列表 */
export function getExpiringYearDeviceList(
params?: DeviceListParams
): Promise<ApiResponse<PageResult<DeviceInfo>>> {
return http.get(http.adornUrl('/sys/device/expiring-year'), { params: http.adornParams(params || {}) })
}
/** 设备列表(不按组织过滤) */
export function getDeviceListWithoutOrg(
params?: DeviceListParams
): Promise<ApiResponse<PageResult<DeviceInfo>>> {
return http.get(http.adornUrl('/sys/device/list-without-org'), { params: http.adornParams(params || {}) })
}
/** 按组织 ID 获取该组织下设备列表 */
export function getDeviceListByOrg(orgId: number): Promise<ApiResponse<DeviceInfo[]>> {
return http.get(http.adornUrl(`/sys/device/list-by-org/${orgId}`), { params: http.adornParams() })
}
/** 设备批量导入 */
export function importDevice(data: DeviceImportData): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/device/import'), http.adornData(data))
}
/** 设备单条导入(手动添加) */
export function importDeviceOne(data: Partial<DeviceInfo>): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/device/import-one'), http.adornData(data))
}
/** 设备批量预置(设备授权/预置) */
export function batchPresetDevice(data: DeviceBatchPresetData): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/device/batch-preset'), http.adornData(data))
}
/** 批量预置/导入前服务端校验 */
export function validateDeviceImport(data: DeviceImportData): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/device/import-validate'), http.adornData(data))
}
/** 设备预激活 */
export function bindDevicePreImport(data: { deviceId: number }): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/device/preImport'), http.adornData(data))
}
/** 设备解绑 */
export function unbindDevice(data: { deviceId: number }): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/device/unbind'), http.adornData(data))
}
/** 预置设备删除预置 */
export function cancelPresetDevice(data: { deviceId: number }): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/device/cancel-preset'), http.adornData(data))
}
/** 设备间权益卡转移 */
export function transferDeviceCard(data: {
fromDeviceId: number
toDeviceId: number
}): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/device/transfer-card'), http.adornData(data))
}
/** 可换绑的卡信息 */
export interface ReplaceableCard {
id: number
cardNo: string
thirdCardNo?: string
cardType: string
thirdStartAt?: string
thirdExpireAt?: string
}
/** 查询设备可换绑的卡列表 */
export function getReplaceableCards(deviceId: number | string): Promise<ApiResponse<ReplaceableCard[]>> {
return http.get(http.adornUrl(`/sys/device/${deviceId}/replaceable-cards`), { params: http.adornParams() })
}
/** 设备换卡 */
export function replaceCard(data: { deviceId: number; cardId: number }): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/device/replace-card'), http.adornData(data))
}
/** 修改设备房间号 */
export function updateDeviceRoomNo(data: { deviceId: number; roomNo: string }): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/device/update-room-no'), http.adornData(data))
}
/** 修改设备 MAC */
export function updateDeviceMac(data: { deviceId: number; mac: string }): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/device/update-mac'), http.adornData(data))
}
/** 设备续费 */
export function renewDevice(data: { deviceId: number; cardType: string }): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/device/renew'), http.adornData(data))
}
/** 根据设备ID查询设备详细信息 */
export function getDeviceDetail(deviceId: number): Promise<ApiResponse<DeviceInfo>> {
return http.get(http.adornUrl(`/sys/device/detail/${deviceId}`), { params: http.adornParams() })
}
/** 开发人员设备迁移 */
export function developerManualImportDevice(data: {
storeId: number
mac: string
expireAt: string
}): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/device/developer-manual-import'), http.adornData(data))
}
/** 设备转移门店 */
export function assignDeviceStore(data: {
deviceId: number
toStoreOrgId?: number
storeOrgId?: number
}): Promise<ApiResponse<any>> {
const payload = {
deviceId: data?.deviceId,
toStoreOrgId: data?.toStoreOrgId ?? data?.storeOrgId
}
return http.post(http.adornUrl('/sys/device/transform'), http.adornData(payload))
}
/** 清空设备 SN/UID */
export function clearDeviceSnUid(data: { deviceId: number }): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/device/clear-sn-uid'), http.adornData(data))
}
/** 软删除设备 */
export function softDeleteDevice(data: { deviceId: number }): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/device/soft-delete'), http.adornData(data))
}
/** 禁用设备(status → DISABLED) */
export function disableDevice(data: { deviceId: number }): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/device/disable'), http.adornData(data))
}
/** 同 MAC 已绑卡设备列表(不含自身,字段与 duplicate-mac 列表一致) */
export function getSameMacBoundDeviceList(deviceId: number): Promise<ApiResponse<DeviceInfo[]>> {
return http.get(http.adornUrl(`/sys/device/same-mac-bound-list/${deviceId}`), { params: http.adornParams() })
}
/** 替换重复设备:保留 device1 绑卡,交换 SN/UID,软删除 device2 */
export function replaceDuplicateDevice(data: {
device1: number
device2: number
}): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/device/replace-duplicate'), http.adornData(data))
}

22
src/api/index.ts Executable file
View File

@@ -0,0 +1,22 @@
/**
* 统一导出 http 实例及所有 API 模块
* 业务请从各模块按需引入,例如:import { getOrgTree } from '@/api/org'
*
* 新 manage 后端接口(/manage/ 前缀)请从独立入口引入:
* import { getChannelList, getOverviewStats } from '@/api/manage'
* 或按模块引入:
* import { getChannelList } from '@/api/manage/channel'
*/
import http from '@/utils/httpRequest'
export { http }
export * from './org'
export * from './card'
export * from './cardFlow'
export * from './cardAllocation'
export * from './contract'
export * from './store'
export * from './device'
export * from './mediaAsset'
export * from './mediaAssetRank'
export * from './sys'

83
src/api/jetsenMedia.ts Normal file
View File

@@ -0,0 +1,83 @@
import http from '@/utils/httpRequest'
/**
* 橘视厅媒资内容项(对应后端透传的橘视厅 result 字段)
*/
export interface JetsenContentItem {
contentcode: string
name: string
categoryname?: string
score?: string
actordisplay?: string
description?: string
releaseyear?: string
originalcountry?: string
isFree?: number
episodecount?: number
duration?: string
posterimg?: string
midimg?: string
image?: string
[key: string]: any
}
/** 栏目标签 */
export interface JetsenTag {
id: number
name: string
code: string
type?: number
parent_id?: number
big_project?: string
[key: string]: any
}
/** 栏目树节点(一级含 children 二级子栏目) */
export interface JetsenCatalogNode {
id: number
name: string
code?: string
children?: JetsenCatalogNode[]
}
/** 分页数据(后端 R.dataSuccess 统一格式) */
export interface JetsenPageData<T> {
list: T[]
totalCount: number
currPage: number
pageSize: number
totalPage: number
}
/** 首页导航(一级栏目入口) */
export function getJetsenMediaNav() {
return http.get(http.adornUrl('/manage/jetsen-media/nav'), { params: http.adornParams() })
}
/** 栏目标签(一级栏目传 parentid=0) */
export function getJetsenMediaTags(parentid: string | number = 0) {
return http.get(http.adornUrl('/manage/jetsen-media/tags'), { params: http.adornParams({ parentid }) })
}
/** 栏目树(一级栏目 + 其下二级子栏目,查内容列表用二级 id) */
export function getJetsenMediaCatalogTree() {
return http.get(http.adornUrl('/manage/jetsen-media/catalog-tree'), { params: http.adornParams() })
}
/** 内容列表(按栏目 catalogid 分页) */
export function getJetsenMediaList(params: { catalogid: string | number; pageindex: number; pagesize: number }) {
return http.get(http.adornUrl('/manage/jetsen-media/list'), { params: http.adornParams(params) })
}
/** 搜索 */
export function searchJetsenMedia(params: { keyword: string; pageindex: number; pagesize: number }) {
return http.get(http.adornUrl('/manage/jetsen-media/search'), { params: http.adornParams(params) })
}
/** 导出 Excel(返回 blob) */
export function exportJetsenMedia(params: { catalogid?: string | number; keyword?: string; catalogName?: string }) {
return http.get(http.adornUrl('/manage/jetsen-media/export'), {
params: http.adornParams(params),
responseType: 'blob'
})
}

View File

@@ -0,0 +1,55 @@
import http from '@/utils/httpRequest'
import type { ManageResponse } from './types'
// ===================== 天卡设备激活码 =====================
/** 激活码实体 */
export interface ActivationCodeItem {
id: number
/** 激活码(5位字符,如 7A3FK) */
code: string
/** 渠道组织ID */
channelOrgId: number
/** 门店组织ID */
storeOrgId: number
/** 状态:ACTIVE-启用 / DISABLED-禁用 */
status: 'ACTIVE' | 'DISABLED'
/** 最大可激活设备数(0=不限) */
maxDeviceCount: number
/** 已激活设备数 */
activatedCount: number
/** 备注 */
remark: string | null
createdAt: string
}
/** 生成激活码请求体 */
export interface ActivationCodeGenerateBody {
storeOrgId: number
remark?: string
}
/** 按门店查询激活码列表(GET /manage/daycard/activation-code/list/{storeOrgId}) */
export function getActivationCodeList (storeOrgId: number): Promise<ManageResponse<{ list: ActivationCodeItem[] }>> {
return http.get(http.adornUrl(`/manage/daycard/activation-code/list/${storeOrgId}`), { params: http.adornParams() }).then(res => res.data)
}
/** 为门店生成激活码(每门店一个,已存在则返回已有的) */
export function generateActivationCode (data: ActivationCodeGenerateBody): Promise<ManageResponse<ActivationCodeItem>> {
return http.post(http.adornUrl('/manage/daycard/activation-code/generate'), http.adornData(data)).then(res => res.data)
}
/** 重新生成激活码(旧码失效) */
export function regenerateActivationCode (id: number): Promise<ManageResponse<{ code: string }>> {
return http.post(http.adornUrl(`/manage/daycard/activation-code/${id}/regenerate`), http.adornData({})).then(res => res.data)
}
/** 启用/禁用激活码(PUT /manage/daycard/activation-code/{id}/status) */
export function updateActivationCodeStatus (id: number, status: 'ACTIVE' | 'DISABLED'): Promise<ManageResponse> {
return http.put(http.adornUrl(`/manage/daycard/activation-code/${id}/status`), http.adornData({ status })).then(res => res.data)
}
/** 删除激活码(软删除) */
export function deleteActivationCode (id: number): Promise<ManageResponse> {
return http.delete(http.adornUrl(`/manage/daycard/activation-code/${id}`)).then(res => res.data)
}

75
src/api/manage/channel.ts Normal file
View File

@@ -0,0 +1,75 @@
import http from '@/utils/httpRequest'
import type { ManageListResponse, ManageResponse, ManagePageParams } from './types'
/**
* 渠道信息
*/
export interface ChannelInfo {
id: number
parentId: number
mpath: string
name: string
orderNo?: number
type: string
/** 后端 @JsonProperty("orgCode") 重命名,JSON 中为 orgCode */
orgCode?: string
canHoldInventory: boolean
activationPrefix: string
brandLogoUrl: string | null
developmentStaff?: string
contactPhone?: string
servicePartner?: string
wechatQrImageUrl?: string | null
status: string
createdAt: string
updatedAt: string
/** 非表字段,后端 join 返回 */
parentOrgName?: string
channelName?: string
children?: ChannelInfo[]
}
/**
* 渠道列表查询参数
*/
export interface ChannelListParams extends ManagePageParams {
name?: string
status?: string
}
/**
* 渠道保存/更新数据
*/
export interface ChannelSaveData {
id?: number
parentId: number
name: string
orgCode?: string
canHoldInventory?: boolean
activationPrefix?: string
brandLogoUrl?: string
developmentStaff?: string
contactPhone?: string
servicePartner?: string
}
/** 渠道分页列表 */
export function getChannelList(params?: ChannelListParams): Promise<ManageListResponse<ChannelInfo>> {
return http.get(http.adornUrl('/manage/org/channel/list'), { params: http.adornParams(params || {}) }).then(res => res.data)
}
/** 渠道详情 */
export function getChannelInfo(id: number): Promise<ManageResponse<{ channel?: ChannelInfo }>> {
return http.get(http.adornUrl(`/manage/org/channel/info/${id}`), { params: http.adornParams() }).then(res => res.data)
}
/** 新增/修改渠道 */
export function saveOrUpdateChannel(data: ChannelSaveData): Promise<ManageResponse> {
const url = data.id ? '/manage/org/channel/update' : '/manage/org/channel/save'
return http.post(http.adornUrl(url), http.adornData(data)).then(res => res.data)
}
/** 删除渠道(批量软删除) */
export function deleteChannel(ids: number[]): Promise<ManageResponse> {
return http.post(http.adornUrl('/manage/org/channel/delete'), http.adornData(ids, false)).then(res => res.data)
}

View File

@@ -0,0 +1,112 @@
import http from '@/utils/httpRequest'
import type { ManageListResponse, ManageResponse, ManagePageParams } from './types'
/**
* 内容包信息(绑定 partnerId)
*/
export interface ContentPackage {
id: number
/** 合作伙伴UUID(字符串) */
partnerId: string
name: string
description?: string
/** 状态:ACTIVE-启用 / DISABLED-禁用 */
status: 'ACTIVE' | 'DISABLED'
createdAt: string
updatedAt: string
/** 非表字段,后端 join 返回 */
partnerName?: string
}
/**
* 内容包保存/更新数据
*/
export interface ContentPackageSaveData {
id?: number
/** 合作伙伴UUID(字符串) */
partnerId: string
name: string
description?: string
status?: 'ACTIVE' | 'DISABLED'
}
/**
* 内容包列表查询参数
*/
export interface ContentPackageListParams extends ManagePageParams {
/** 合作伙伴UUID(字符串) */
partnerId?: string
name?: string
status?: string
}
/** 内容包分页列表 */
export function getContentPackageList(params?: ContentPackageListParams): Promise<ManageListResponse<ContentPackage>> {
return http.get(http.adornUrl('/manage/content-package/list'), { params: http.adornParams(params || {}) }).then(res => res.data)
}
// ===================== 栏目内容选择辅助接口 =====================
/** 栏目内容预览项(精简字段,供管理员勾选) */
export interface CatalogContentItem {
contentcode: string
name: string
posterimg?: string
categoryname?: string
score?: string
isFree?: number | string
episodecount?: number
duration?: number
releaseyear?: string
originalcountry?: string
}
/** 内容包详情(含解析后的内容列表,前端直接展示,无需 JSON.parse) */
export interface ContentPackageDetail {
/** 原始实体(contentCodes 是 JSON 字符串) */
contentPackage: ContentPackage
/** 解析后的内容数组 */
contentList: CatalogContentItem[]
}
/** 内容包详情(按 id,含 contentList) */
export function getContentPackageInfo(id: number): Promise<ManageResponse<ContentPackageDetail>> {
return http.get(http.adornUrl(`/manage/content-package/info/${id}`), { params: http.adornParams() }).then(res => res.data)
}
/** 内容包详情(按 partnerId,含 contentList) */
export function getContentPackageInfoByPartner(partnerId: string): Promise<ManageResponse<ContentPackageDetail>> {
return http.get(http.adornUrl(`/manage/content-package/info-by-partner/${partnerId}`), { params: http.adornParams() }).then(res => res.data)
}
/** 新增/修改内容包元信息(绑定 partnerId) */
export function saveOrUpdateContentPackage(data: ContentPackageSaveData): Promise<ManageResponse> {
const url = data.id ? '/manage/content-package/update' : '/manage/content-package/save'
return http.post(http.adornUrl(url), http.adornData(data)).then(res => res.data)
}
/** 删除内容包(软删除,批量) */
export function deleteContentPackage(ids: number[]): Promise<ManageResponse> {
return http.post(http.adornUrl('/manage/content-package/delete'), http.adornData(ids, false)).then(res => res.data)
}
/** 拉取栏目内容预览(GET /manage/content-package/fetch-contents?catalogid=&pagesize=) */
export function fetchPackageContents(params: { catalogid: string | number; pagesize?: number; pageindex?: number }): Promise<ManageResponse<{ list: CatalogContentItem[]; totalCount: number; totalPage: number }>> {
return http.get(http.adornUrl('/manage/content-package/fetch-contents'), { params: http.adornParams(params) }).then(res => res.data)
}
/** 一键保存勾选内容请求体(POST /manage/content-package/save-from-selection;传 id 覆盖,不传新建) */
export interface SaveFromSelectionBody {
/** 传 id 按 id 更新覆盖;不传按 partnerId 查找 */
id?: number
/** 合作伙伴UUID(字符串) */
partnerId: string
name: string
catalogIds: string
selectedContents: CatalogContentItem[]
}
/** 一键保存勾选内容(管理员勾选的内容对象数组直接传后端,序列化存入 content_codes;不带 t 时间戳) */
export function saveContentPackageFromSelection(data: SaveFromSelectionBody): Promise<ManageResponse> {
return http.post(http.adornUrl('/manage/content-package/save-from-selection'), http.adornData(data, false)).then(res => res.data)
}

151
src/api/manage/daycard.ts Normal file
View File

@@ -0,0 +1,151 @@
import http from '@/utils/httpRequest'
import type { ManageListResponse, ManageResponse, ManagePageParams } from './types'
// ===================== 天卡池 =====================
/** 天卡池实体 */
export interface DayCardPoolItem {
id: number
/** 卡密(橘视厅激活码) */
cardCode: string
/** 第三方引用标识(橘视厅免密登录 uid) */
thirdPartyRef: string
/** 第三方卡号(D + 24位随机,App 用于访问内容) */
thirdCardNo: string
cardType: string
partnerId: number
/** 状态: UNUSED / RESERVED / USED */
status: string
/** 激活状态: PENDING / SUCCESS / FAILED */
activateStatus: string
activateError: string | null
activatedAt: string | null
orderNo: string | null
deviceId: number | null
importBatchId: number | null
expireAt: string | null
usedAt: string | null
createdAt: string
updatedAt: string
}
/** 卡池列表参数 */
export interface DayCardPoolListParams extends ManagePageParams {
partnerId?: number
status?: string
cardCode?: string
orderNo?: string
}
/** 卡池统计 */
export interface DayCardPoolStats {
total: number
available: number
reserved: number
used: number
}
/** 导入卡密请求 */
export interface DayCardPoolImportData {
partnerId: number
cardCodes: string[]
}
/** 导入卡密响应 */
export interface DayCardPoolImportResult {
successCount: number
totalCount: number
}
/** 导入批次 */
export interface DayCardImportBatch {
id: number
batchNo: string
partnerId: number
status: string
totalCount: number
successCount: number
failCount: number
remark: string | null
createdAt: string
}
/** 获取天卡池列表 */
export function getDayCardPoolList (params?: DayCardPoolListParams): Promise<ManageListResponse<DayCardPoolItem>> {
return http.get(http.adornUrl('/manage/daycard/pool/list'), { params: http.adornParams(params || {}) }).then(res => res.data)
}
/** 获取卡池统计 */
export function getDayCardPoolStats (partnerId?: number): Promise<ManageResponse<{ stats?: DayCardPoolStats }>> {
return http.get(http.adornUrl('/manage/daycard/pool/stats'), { params: http.adornParams({ partnerId }) }).then(res => res.data)
}
/** 导入卡密 */
export function importDayCardPool (data: DayCardPoolImportData): Promise<ManageResponse<DayCardPoolImportResult>> {
return http.post(http.adornUrl('/manage/daycard/pool/import'), http.adornData(data)).then(res => res.data)
}
// ===================== 天卡订单 =====================
/** 天卡订单实体 */
export interface DayCardOrderItem {
id: number
orderNo: string
partnerId: number
deviceId: number
storeOrgId: number
channelOrgId: number
/** 卡号(值为 DayCardPoolEntity.cardCode) */
cardNo: string | null
/** 订单状态: CREATED / PAYING / PAID / PAY_FAILED / CANCELLED */
status: string
amount: number
/** 支付渠道: WECHAT 等 */
payChannel: string | null
/** 微信支付二维码链接 */
codeUrl: string | null
payNo: string | null
payAmount: number | null
payTime: string | null
expireTime: string | null
cancelTime: string | null
createdAt: string
updatedAt: string
/** 非表字段 */
partnerName?: string
deviceMac?: string
}
/** 订单列表参数 */
export interface DayCardOrderListParams extends ManagePageParams {
partnerId?: number
orderNo?: string
status?: string
startDate?: string
endDate?: string
}
/** 获取订单列表 */
export function getDayCardOrderList (params?: DayCardOrderListParams): Promise<ManageListResponse<DayCardOrderItem>> {
return http.get(http.adornUrl('/manage/daycard/list'), { params: http.adornParams(params || {}) }).then(res => res.data)
}
/** 获取订单详情 */
export function getDayCardOrderInfo (orderNo: string): Promise<ManageResponse<{ order?: DayCardOrderItem }>> {
return http.get(http.adornUrl(`/manage/daycard/info/${orderNo}`), { params: http.adornParams() }).then(res => res.data)
}
// ===================== 设备权益 =====================
/** 设备天卡权益 */
export interface DeviceBenefits {
hasBenefits: boolean
thirdCardNo?: string
cardCode?: string
expireAt?: string
}
/** 查询设备天卡权益 */
export function getDeviceBenefits (deviceId: number): Promise<ManageResponse<DeviceBenefits>> {
return http.get(http.adornUrl(`/manage/daycard/benefits/${deviceId}`), { params: http.adornParams() }).then(res => res.data)
}

117
src/api/manage/device.ts Normal file
View File

@@ -0,0 +1,117 @@
import http from '@/utils/httpRequest'
import type { ManageListResponse, ManageResponse, ManagePageParams } from './types'
/**
* 终端/设备信息
*/
export interface DeviceInfo {
id: number
storeOrgId: number
mac: string
deviceSn: string
wifiMac?: string
deviceUid?: string
androidId?: string
manufacturer?: string
model?: string
brand?: string
identifierStrategy?: string
deviceName: string
deviceModel: string
verCode?: string
verName?: string
androidVersion?: string
roomNo: string
lastHeartbeat?: string
remark: string
status: string
createdAt: string
updatedAt: string
/** 非表字段,后端 join 返回 */
storeName?: string
channelOrgId?: number
channelName?: string
agentOrgName?: string
/** 设备来源:PLATFORM-平台 / PARTNER-第三方接口注册 */
source?: string
/** 合作伙伴UUID(source=PARTNER 时) */
partnerId?: string
}
/**
* 终端列表查询参数
*/
export interface DeviceListParams extends ManagePageParams {
storeOrgId?: number
status?: string
deviceName?: string
mac?: string
/** 设备来源:PLATFORM / PARTNER */
source?: string
/** 合作伙伴UUID(source=PARTNER 时筛选) */
partnerId?: string
}
/**
* 终端保存/更新数据
*/
export interface DeviceSaveData {
id?: number
storeOrgId: number
mac?: string
wifiMac?: string
deviceUid?: string
deviceSn?: string
deviceName?: string
deviceModel?: string
roomNo?: string
remark?: string
}
/** 终端分页列表 */
export function getDeviceList(params?: DeviceListParams): Promise<ManageListResponse<DeviceInfo>> {
return http.get(http.adornUrl('/manage/device/list'), { params: http.adornParams(params || {}) }).then(res => res.data)
}
/** 终端详情 */
export function getDeviceInfo(id: number): Promise<ManageResponse<{ device?: DeviceInfo }>> {
return http.get(http.adornUrl(`/manage/device/info/${id}`), { params: http.adornParams() }).then(res => res.data)
}
/** 新增/修改终端 */
export function saveOrUpdateDevice(data: DeviceSaveData): Promise<ManageResponse> {
const url = data.id ? '/manage/device/update' : '/manage/device/save'
return http.post(http.adornUrl(url), http.adornData(data)).then(res => res.data)
}
/** 删除终端(批量软删除) */
export function deleteDevice(ids: number[]): Promise<ManageResponse> {
return http.post(http.adornUrl('/manage/device/delete'), http.adornData(ids, false)).then(res => res.data)
}
/** 绑定门店(query 参数传 deviceId 和 storeOrgId) */
export function bindDeviceStore(deviceId: number, storeOrgId: number): Promise<ManageResponse> {
return http.post(
http.adornUrl('/manage/device/bindStore'),
http.adornData({}),
{ params: http.adornParams({ deviceId, storeOrgId }) }
).then(res => res.data)
}
/** 解绑设备(换场所):清门店关联 + 作废 sign + 释放天卡权益 */
export function unbindDeviceOrg(deviceId: number): Promise<ManageResponse> {
return http.post(
http.adornUrl('/manage/daycard/device/unbind-org'),
http.adornData({}),
{ params: http.adornParams({ deviceId }) }
).then(res => res.data)
}
/** 退天卡:仅退卡,不解绑门店 */
export function unbindDayCard(deviceId: number): Promise<ManageResponse> {
return http.post(
http.adornUrl('/manage/daycard/device/unbind'),
http.adornData({}),
{ params: http.adornParams({ deviceId }) }
).then(res => res.data)
}

28
src/api/manage/index.ts Normal file
View File

@@ -0,0 +1,28 @@
/**
* /manage/ 接口模块统一导出
*
* 业务请从各模块按需引入,例如:
* import { getChannelList } from '@/api/manage/channel'
* import { getOverviewStats } from '@/api/manage/stats'
*
* 或从统一入口引入:
* import { getChannelList, getOverviewStats } from '@/api/manage'
*/
export * from './types'
export * from './channel'
export * from './store'
export * from './orgTree'
export * from './device'
export * from './payConfig'
export * from './price'
export * from './stats'
export * from './daycard'
export * from './activationCode'
export * from './profitRule'
export * from './profitReceiver'
export * from './profitSharing'
export * from './refund'
export * from './partner'
export * from './content-package'
export * from './partner-card'
export * from './openapiCallLog'

View File

@@ -0,0 +1,42 @@
import http from '@/utils/httpRequest'
import type { ManageListResponse, ManagePageParams } from './types'
/**
* OpenAPI 调用日志(第三方接口审计日志)
*/
export interface OpenApiCallLogItem {
id: number
/** 合作伙伴UUID */
partnerId: string
/** 应用Key */
appKey: string
/** 接口路径 */
api: string
/** 请求方法:GET / POST */
httpMethod: string
/** 请求参数(consume 记录设备标识,media 记录 query string) */
params: string
/** 结果码:0=成功,400/500=失败 */
resultCode: number
/** 调用方IP */
ip: string
/** 耗时(毫秒) */
costMs: number
/** 调用时间 */
createdAt: string
}
/**
* 查询参数
*/
export interface OpenApiCallLogListParams extends ManagePageParams {
/** 合作伙伴UUID */
partnerId?: string
/** 接口路径(模糊查询) */
api?: string
}
/** OpenAPI 调用日志列表(第三方接口审计日志) */
export function getOpenApiCallLogList(params?: OpenApiCallLogListParams): Promise<ManageListResponse<OpenApiCallLogItem>> {
return http.get(http.adornUrl('/manage/openapi/call-log/list'), { params: http.adornParams(params || {}) }).then(res => res.data)
}

22
src/api/manage/orgTree.ts Normal file
View File

@@ -0,0 +1,22 @@
import http from '@/utils/httpRequest'
import type { ManageResponse } from './types'
/**
* 组织树节点
*/
export interface OrgTreeNode {
id: number
name: string
type: string
mpath: string
code?: string
children: OrgTreeNode[]
}
/**
* 获取完整组织树
* 层级:PLATFORM → CHANNEL → SERVICE_PROVIDER → STORE
*/
export function getOrgTree(): Promise<ManageResponse<{ tree?: OrgTreeNode[] }>> {
return http.get(http.adornUrl('/manage/org/tree'), { params: http.adornParams() }).then(res => res.data)
}

View File

@@ -0,0 +1,98 @@
import http from '@/utils/httpRequest'
import type { ManageListResponse, ManageResponse, ManagePageParams } from './types'
/**
* 合作伙伴天卡(卡密级别)
*/
export interface PartnerCardItem {
id: number
/** 合作伙伴UUID(字符串) */
partnerId: string
/** 平台天卡池ID(day_card_pool.id) */
poolId: number
/** 天卡卡密 */
cardCode: string
/** 橘视厅第三方卡号 */
thirdCardNo: string
/** 状态:AVAILABLE-可用 / CONSUMED-已消耗 / DISABLED-已禁用 */
status: 'AVAILABLE' | 'CONSUMED' | 'DISABLED'
/** 消耗后绑定的设备ID(未消耗=null) */
deviceId: number | null
/** 渠道机构ID(消耗时传入,未消耗=null) */
channelOrgId: number | null
/** 采购批次号(同批次采购的天卡批次号相同) */
purchaseBatch: string
/** 消耗时间(未消耗=null) */
consumedAt: string | null
deleteFlag: string
/** 创建时间(采购时间) */
createdAt: string
updatedAt: string
}
/**
* 库存统计
*/
export interface PartnerCardStats {
total: number
available: number
used: number
}
/**
* 库存列表查询参数
*/
export interface PartnerCardListParams extends ManagePageParams {
/** 合作伙伴UUID(字符串) */
partnerId?: string
/** 状态:AVAILABLE / CONSUMED / DISABLED */
status?: string
/** 采购批次号 */
purchaseBatch?: string
}
/**
* 采购天卡请求体(后端 @RequestParam,参数走 URL query)
*/
export interface PartnerCardPurchaseBody {
/** 合作伙伴UUID(字符串) */
partnerId: string
/** 采购卡数 */
quantity: number
/** 金额(分) */
amount?: number
remark?: string
}
/** 天卡库存列表(卡密级别) */
export function getPartnerCardList(params?: PartnerCardListParams): Promise<ManageListResponse<PartnerCardItem>> {
return http.get(http.adornUrl('/manage/partner-card/list'), { params: http.adornParams(params || {}) }).then(res => res.data)
}
/** 采购天卡(划拨天卡到 partner 池子;后端 @RequestParam,参数走 URL query,不放 JSON body) */
export function purchasePartnerCard(data: PartnerCardPurchaseBody): Promise<ManageResponse> {
return http.post(
http.adornUrl('/manage/partner-card/purchase'),
http.adornData({}),
{ params: http.adornParams({ partnerId: data.partnerId, quantity: data.quantity, amount: data.amount, remark: data.remark }, false) }
).then(res => res.data)
}
/**
* 回退天卡请求体(后端 @RequestParam,参数走 URL query)
*/
export interface PartnerCardRevertBody {
/** 合作伙伴UUID(字符串) */
partnerId: string
/** 回退数量 */
quantity: number
}
/** 回退天卡(从 partner 池取 N 张 AVAILABLE 天卡回退;平台池 RESERVED->UNUSED,partner 池卡 DISABLED;@RequestParam,URL query) */
export function revertPartnerCard(data: PartnerCardRevertBody): Promise<ManageResponse<{ reverted: number }>> {
return http.post(
http.adornUrl('/manage/partner-card/revert'),
http.adornData({}),
{ params: http.adornParams({ partnerId: data.partnerId, quantity: data.quantity }, false) }
).then(res => res.data)
}

67
src/api/manage/partner.ts Normal file
View File

@@ -0,0 +1,67 @@
import http from '@/utils/httpRequest'
import type { ManageListResponse, ManageResponse, ManagePageParams } from './types'
/**
* 合作伙伴信息
*/
export interface PartnerInfo {
id: number
/** 合作伙伴业务UUID(16位字符串,传给内容包/采购等接口用此字段,非自增 id) */
partnerId: string
name: string
/** 应用标识(新增后由后端自动生成) */
appKey: string
/** 应用密钥(新增后由后端自动生成,仅明文返回一次) */
appSecret: string
/** 状态:ACTIVE-启用 / DISABLED-禁用(禁用后 appKey 签名校验失败) */
status: 'ACTIVE' | 'DISABLED'
/** 限流(次/分钟,0=不限) */
rateLimit?: number
remark?: string
createdAt: string
updatedAt: string
}
/**
* 合作伙伴保存/更新数据
*/
export interface PartnerSaveData {
id?: number
name: string
status?: 'ACTIVE' | 'DISABLED'
rateLimit?: number
remark?: string
}
/**
* 合作伙伴列表查询参数
*/
export interface PartnerListParams extends ManagePageParams {
name?: string
status?: string
}
/** 合作伙伴分页列表 */
export function getPartnerList(params?: PartnerListParams): Promise<ManageListResponse<PartnerInfo>> {
return http.get(http.adornUrl('/manage/partner/list'), { params: http.adornParams(params || {}) }).then(res => res.data)
}
/** 合作伙伴详情(含 appKey/appSecret 明文) */
export function getPartnerInfo(id: number): Promise<ManageResponse<PartnerInfo>> {
return http.get(http.adornUrl(`/manage/partner/info/${id}`), { params: http.adornParams() }).then(res => res.data)
}
/** 新增合作伙伴(自动生成 appKey/appSecret,返回在 data 中) */
export function savePartner(data: PartnerSaveData): Promise<ManageResponse<PartnerInfo>> {
return http.post(http.adornUrl('/manage/partner/save'), http.adornData(data)).then(res => res.data)
}
/** 修改合作伙伴(改名称/状态/限流等;status=DISABLED 禁用) */
export function updatePartner(data: PartnerSaveData): Promise<ManageResponse> {
return http.post(http.adornUrl('/manage/partner/update'), http.adornData(data)).then(res => res.data)
}
/** 删除合作伙伴(软删除,批量) */
export function deletePartner(ids: number[]): Promise<ManageResponse> {
return http.post(http.adornUrl('/manage/partner/delete'), http.adornData(ids, false)).then(res => res.data)
}

View File

@@ -0,0 +1,63 @@
import http from '@/utils/httpRequest'
import type { ManageListResponse, ManageResponse, ManagePageParams } from './types'
/**
* 微信支付配置信息
*/
export interface PayConfigInfo {
id: number
partnerId: number | null
appId: string
mchId: string
apiV3Key: string
certSerialNo: string
privateKeyPath: string
notifyUrl: string
status: string
remark: string
}
/**
* 支付配置列表查询参数
*/
export interface PayConfigListParams extends ManagePageParams {
partnerId?: number
status?: string
}
/**
* 支付配置保存/更新数据
*/
export interface PayConfigSaveData {
id?: number
partnerId?: number
appId: string
mchId: string
apiV3Key: string
certSerialNo?: string
privateKeyPath?: string
notifyUrl: string
status?: string
remark?: string
}
/** 支付配置分页列表 */
export function getPayConfigList(params?: PayConfigListParams): Promise<ManageListResponse<PayConfigInfo>> {
return http.get(http.adornUrl('/manage/payconfig/list'), { params: http.adornParams(params || {}) }).then(res => res.data)
}
/** 支付配置详情 */
export function getPayConfigInfo(id: number): Promise<ManageResponse<{ config?: PayConfigInfo }>> {
return http.get(http.adornUrl(`/manage/payconfig/info/${id}`), { params: http.adornParams() }).then(res => res.data)
}
/** 新增/修改支付配置 */
export function saveOrUpdatePayConfig(data: PayConfigSaveData): Promise<ManageResponse> {
const url = data.id ? '/manage/payconfig/update' : '/manage/payconfig/save'
return http.post(http.adornUrl(url), http.adornData(data)).then(res => res.data)
}
/** 删除支付配置(批量软删除) */
export function deletePayConfig(ids: number[]): Promise<ManageResponse> {
return http.post(http.adornUrl('/manage/payconfig/delete'), http.adornData(ids, false)).then(res => res.data)
}

71
src/api/manage/price.ts Normal file
View File

@@ -0,0 +1,71 @@
import http from '@/utils/httpRequest'
import type { ManageListResponse, ManageResponse, ManagePageParams } from './types'
/**
* 定价策略信息
*/
export interface PriceConfigInfo {
id: number
partnerId: number
channelOrgId: number | null
storeOrgId: number | null
price: number
durationHours: number
name: string
status: string
/** 生效起始日期 yyyy-MM-dd */
effectiveFrom: string | null
/** 生效截止日期 yyyy-MM-dd(null=长期) */
effectiveTo: string | null
createdAt: string
}
/**
* 定价策略列表查询参数
*/
export interface PriceListParams extends ManagePageParams {
partnerId?: number
channelOrgId?: number
storeOrgId?: number
status?: string
}
/**
* 定价策略保存/更新数据
*/
export interface PriceSaveData {
id?: number
partnerId?: number
channelOrgId?: number
storeOrgId?: number
price: number
durationHours?: number
name?: string
status?: string
}
/** 定价策略分页列表 */
export function getPriceList(params?: PriceListParams): Promise<ManageListResponse<PriceConfigInfo>> {
return http.get(http.adornUrl('/manage/price/list'), { params: http.adornParams(params || {}) }).then(res => res.data)
}
/** 定价策略详情 */
export function getPriceInfo(id: number): Promise<ManageResponse<{ config?: PriceConfigInfo }>> {
return http.get(http.adornUrl(`/manage/price/info/${id}`), { params: http.adornParams() }).then(res => res.data)
}
/** 新增/修改定价策略 */
export function saveOrUpdatePrice(data: PriceSaveData): Promise<ManageResponse> {
const url = data.id ? '/manage/price/update' : '/manage/price/save'
return http.post(http.adornUrl(url), http.adornData(data)).then(res => res.data)
}
/** 删除定价策略(批量软删除) */
export function deletePrice(ids: number[]): Promise<ManageResponse> {
return http.post(http.adornUrl('/manage/price/delete'), http.adornData(ids, false)).then(res => res.data)
}
/** 查询生效中的定价(GET /manage/price/effective?channelOrgId=&storeOrgId=) */
export function getEffectivePrice(params: { channelOrgId?: number; storeOrgId?: number }): Promise<ManageResponse<{ config?: PriceConfigInfo }>> {
return http.get(http.adornUrl('/manage/price/effective'), { params: http.adornParams(params) }).then(res => res.data)
}

View File

@@ -0,0 +1,58 @@
import http from '@/utils/httpRequest'
import type { ManageListResponse, ManageResponse, ManagePageParams } from './types'
// ===================== 分账接收方 =====================
export interface ProfitReceiver {
id: number
/** 关联组织ID(渠道/代理商/门店) */
orgId: number
orgName: string
/** 接收方类型: MERCHANT_ID-商户号 / PERSONAL_OPENID-个人openid */
receiverType: 'MERCHANT_ID' | 'PERSONAL_OPENID'
/** 接收方账号(商户号或openid) */
receiverAccount: string
/** 收款方名称 */
receiverName: string
/** 绑定状态: PENDING-待确认 / ACTIVE-已绑定 / FAILED-绑定失败 */
bindStatus: 'PENDING' | 'ACTIVE' | 'FAILED'
}
export interface ProfitReceiverSaveBody {
id?: number
orgId: number
receiverType: 'MERCHANT_ID' | 'PERSONAL_OPENID'
receiverAccount: string
receiverName: string
}
export interface ProfitReceiverListParams extends ManagePageParams {
orgId?: number
bindStatus?: string
}
/** 接收方列表 */
export function getProfitReceiverList (params?: ProfitReceiverListParams): Promise<ManageListResponse<ProfitReceiver>> {
return http.get(http.adornUrl('/manage/profit-receiver/list'), { params: http.adornParams(params || {}) }).then(res => res.data)
}
/** 接收方详情 */
export function getProfitReceiverInfo (id: number): Promise<ManageResponse<{ receiver?: ProfitReceiver }>> {
return http.get(http.adornUrl(`/manage/profit-receiver/info/${id}`), { params: http.adornParams() }).then(res => res.data)
}
/** 保存接收方 */
export function saveProfitReceiver (data: ProfitReceiverSaveBody): Promise<ManageResponse> {
return http.post(http.adornUrl('/manage/profit-receiver/save'), http.adornData(data)).then(res => res.data)
}
/** 删除接收方(body: Long[] ids) */
export function deleteProfitReceiver (ids: number | number[]): Promise<ManageResponse> {
const arr = Array.isArray(ids) ? ids : [ids]
return http.post(http.adornUrl('/manage/profit-receiver/delete'), http.adornData(arr, false)).then(res => res.data)
}
/** 同步接收方到微信(POST /manage/profit-receiver/sync/{id}) */
export function syncProfitReceiver (id: number): Promise<ManageResponse> {
return http.post(http.adornUrl(`/manage/profit-receiver/sync/${id}`), http.adornData({})).then(res => res.data)
}

View File

@@ -0,0 +1,100 @@
import http from '@/utils/httpRequest'
import type { ManageListResponse, ManageResponse, ManagePageParams } from './types'
// ===================== 分润规则 =====================
export interface ProfitRule {
id: number
ruleName: string
scopeType: 'GLOBAL' | 'CHANNEL' | 'AGENT' | 'STORE'
scopeOrgId: number | null
scopeOrgName: string | null
priority: number
status: 'ACTIVE' | 'INACTIVE'
effectiveFrom: string | null
effectiveTo: string | null
}
export interface ProfitRuleItem {
id: number
orgRole: 'PLATFORM' | 'CHANNEL' | 'AGENT' | 'STORE'
shareType: 'RATIO' | 'FIXED'
/** RATIO: 百分比(如 20 表示 20%);FIXED: 分 */
shareValue: number
sortOrder: number
}
export interface ProfitRuleDetail extends ProfitRule {
items: ProfitRuleItem[]
}
export interface ProfitRuleSaveBody {
id?: number
ruleName: string
scopeType: 'GLOBAL' | 'CHANNEL' | 'AGENT' | 'STORE'
scopeOrgId: number | null
priority: number
status: 'ACTIVE' | 'INACTIVE'
effectiveFrom: string | null
effectiveTo: string | null
items: Omit<ProfitRuleItem, 'id'>[]
}
export interface ProfitRuleListParams extends ManagePageParams {
scopeType?: string
}
// ===================== 试算 =====================
export interface ProfitRulePreviewBody {
storeOrgId: number
/** 单位:分 */
amount: number
}
export interface ProfitRulePreviewDetail {
orgRole: 'PLATFORM' | 'CHANNEL' | 'AGENT' | 'STORE'
orgId: number
orgName: string
shareType: 'RATIO' | 'FIXED'
shareValue: number
/** 计算后金额(分) */
amount: number
}
export interface ProfitRulePreviewResp {
ruleId: number
ruleName: string
details: ProfitRulePreviewDetail[]
nonPlatformTotalRatio: number
warning: string | null
}
// ===================== API 方法 =====================
/** 分润规则列表 */
export function getProfitRuleList (params?: ProfitRuleListParams): Promise<ManageListResponse<ProfitRule>> {
return http.get(http.adornUrl('/manage/profit-rule/list'), { params: http.adornParams(params || {}) }).then(res => res.data)
}
/** 分润规则详情(含 items 子表) */
export function getProfitRuleInfo (id: number): Promise<ManageResponse<{ rule?: ProfitRuleDetail }>> {
return http.get(http.adornUrl(`/manage/profit-rule/info/${id}`), { params: http.adornParams() }).then(res => res.data)
}
/** 保存/更新分润规则 */
export function saveOrUpdateProfitRule (data: ProfitRuleSaveBody): Promise<ManageResponse> {
const url = data.id ? '/manage/profit-rule/update' : '/manage/profit-rule/save'
return http.post(http.adornUrl(url), http.adornData(data)).then(res => res.data)
}
/** 删除分润规则(body: Long[] ids) */
export function deleteProfitRule (ids: number | number[]): Promise<ManageResponse> {
const arr = Array.isArray(ids) ? ids : [ids]
return http.post(http.adornUrl('/manage/profit-rule/delete'), http.adornData(arr, false)).then(res => res.data)
}
/** 试算分润(POST /manage/profit-rule/preview) */
export function previewProfitRule (data: ProfitRulePreviewBody): Promise<ManageResponse<ProfitRulePreviewResp>> {
return http.post(http.adornUrl('/manage/profit-rule/preview'), http.adornData(data)).then(res => res.data)
}

View File

@@ -0,0 +1,86 @@
import http from '@/utils/httpRequest'
import type { ManageListResponse, ManageResponse, ManagePageParams } from './types'
// ===================== 分账记录 =====================
export interface ProfitSharingItem {
id: number
/** 支付订单号 */
payOrderNo: string
/** 分账单号 */
outOrderNo: string
status: 'PENDING' | 'SUCCESS' | 'FAILED' | 'PARTIAL'
/** 订单总金额(分) */
totalAmount: number
ruleName: string | null
createdAt: string
storeName: string | null
channelName: string | null
}
export interface ProfitSharingDetailItem {
id: number
orgRole: 'PLATFORM' | 'CHANNEL' | 'AGENT' | 'STORE'
orgName: string | null
receiverAccount: string
/** 分账金额(分) */
amount: number
status: 'PENDING' | 'SUCCESS' | 'FAILED'
successTime: string | null
failReason: string | null
}
export interface ProfitSharingDetail extends ProfitSharingItem {
/** 规则快照 JSON */
ruleSnapshot: string | null
/** 组织链路快照 */
orgPathSnapshot: string | null
details: ProfitSharingDetailItem[]
}
export interface ProfitSharingListParams extends ManagePageParams {
orderNo?: string
status?: string
startDate?: string
endDate?: string
}
/** 分账记录列表(含 details 子表) */
export function getProfitSharingList (params?: ProfitSharingListParams): Promise<ManageListResponse<ProfitSharingItem>> {
return http.get(http.adornUrl('/manage/profit-sharing/list'), { params: http.adornParams(params || {}) }).then(res => res.data)
}
/** 分账记录详情(含明细) */
export function getProfitSharingInfo (id: number): Promise<ManageResponse<{ sharing?: ProfitSharingDetail }>> {
return http.get(http.adornUrl(`/manage/profit-sharing/info/${id}`), { params: http.adornParams() }).then(res => res.data)
}
/** 分账统计 */
export interface ProfitSharingStatsSummary {
totalCount: number
totalAmount: number
successCount: number
successAmount: number
}
export interface ProfitSharingStatsGroup {
orgId: number
orgName: string
orgType: string
count: number
amount: number
}
export interface ProfitSharingStats {
summary: ProfitSharingStatsSummary
groups: ProfitSharingStatsGroup[]
}
export function getProfitSharingStats (params?: { startDate?: string; endDate?: string; groupBy?: string }): Promise<ManageResponse<{ stats?: ProfitSharingStats }>> {
return http.get(http.adornUrl('/manage/profit-sharing/stats'), { params: http.adornParams(params || {}) }).then(res => res.data)
}
/** 重试分账 */
export function retryProfitSharing (id: number): Promise<ManageResponse> {
return http.post(http.adornUrl('/manage/profit-sharing/retry'), http.adornData({ id })).then(res => res.data)
}

60
src/api/manage/refund.ts Normal file
View File

@@ -0,0 +1,60 @@
import http from '@/utils/httpRequest'
import type { ManageListResponse, ManageResponse, ManagePageParams } from './types'
// ===================== 退款记录 =====================
export interface RefundItem {
id: number
/** 退款单号 */
refundNo: string
/** 原支付订单号 */
payOrderNo: string
/** 退款金额(分) */
refundAmount: number
/** 原订单金额(分) */
totalAmount: number
/** 退款状态 */
status: 'PENDING' | 'PROCESSING' | 'SUCCESS' | 'FAILED' | 'CLOSED'
/** 退款原因 */
reason: string | null
/** 微信退款单号 */
wxRefundId: string | null
/** 退款发起人 */
operator: string | null
errorMessage: string | null
refundedAt: string | null
createdAt: string
updatedAt: string
}
export interface RefundListParams extends ManagePageParams {
refundNo?: string
payOrderNo?: string
status?: string
}
/** 发起退款请求体(文档:body {orderNo, reason}) */
export interface RefundApplyBody {
orderNo: string
reason: string
}
/** 退款记录列表 */
export function getRefundList (params?: RefundListParams): Promise<ManageListResponse<RefundItem>> {
return http.get(http.adornUrl('/manage/refund/list'), { params: http.adornParams(params || {}) }).then(res => res.data)
}
/** 退款详情(按退款单号 refundNo 查询) */
export function getRefundInfo (refundNo: string): Promise<ManageResponse<{ refund?: RefundItem }>> {
return http.get(http.adornUrl(`/manage/refund/info/${refundNo}`), { params: http.adornParams() }).then(res => res.data)
}
/** 发起退款(POST /manage/refund/apply) */
export function applyRefund (data: RefundApplyBody): Promise<ManageResponse> {
return http.post(http.adornUrl('/manage/refund/apply'), http.adornData(data)).then(res => res.data)
}
/** 重试退款 */
export function retryRefund (id: number): Promise<ManageResponse> {
return http.post(http.adornUrl('/manage/refund/retry'), http.adornData({ id })).then(res => res.data)
}

73
src/api/manage/stats.ts Normal file
View File

@@ -0,0 +1,73 @@
import http from '@/utils/httpRequest'
import type { ManageResponse } from './types'
/**
* 总览看板统计
*/
export interface OverviewStats {
totalOrders: number
todayOrders: number
totalRevenue: number
todayRevenue: number
totalPool: number
availablePool: number
usedPool: number
activateFailed: number
}
/**
* 订单趋势统计项
*/
export interface OrderTrendItem {
date: string
orderCount: number
revenue: number
}
/**
* 库存统计
* 实际返回:statusStats / activateStats 均为 Map<状态, 数量>
*/
export interface PoolStats {
/** 按库存状态:{ UNUSED: 1, USED: 2 } */
statusStats: Record<string, number>
/** 按激活状态:{ PENDING: 2, FAILED: 1 } */
activateStats: Record<string, number>
}
/**
* 渠道统计项
*/
export interface ChannelStatItem {
channelOrgId: number
orderCount: number
revenue: number
}
/**
* 订单趋势统计查询参数
*/
export interface OrderStatsParams {
startDate: string
endDate: string
}
/** 总览看板 */
export function getOverviewStats(): Promise<ManageResponse<{ overview?: OverviewStats }>> {
return http.get(http.adornUrl('/manage/stats/overview'), { params: http.adornParams() }).then(res => res.data)
}
/** 订单趋势统计 */
export function getOrderStats(params: OrderStatsParams): Promise<ManageResponse<{ orderStats?: { list: OrderTrendItem[] } }>> {
return http.get(http.adornUrl('/manage/stats/orders'), { params: http.adornParams(params) }).then(res => res.data)
}
/** 库存统计 */
export function getPoolStats(): Promise<ManageResponse<{ poolStats?: PoolStats }>> {
return http.get(http.adornUrl('/manage/stats/pool'), { params: http.adornParams() }).then(res => res.data)
}
/** 渠道统计 */
export function getChannelStats(): Promise<ManageResponse<{ channelStats?: { list: ChannelStatItem[] } }>> {
return http.get(http.adornUrl('/manage/stats/channels'), { params: http.adornParams() }).then(res => res.data)
}

63
src/api/manage/store.ts Normal file
View File

@@ -0,0 +1,63 @@
import http from '@/utils/httpRequest'
import type { ManageListResponse, ManageResponse, ManagePageParams } from './types'
/**
* 门店信息
*/
export interface StoreInfo {
id: number
parentId: number
mpath: string
name: string
orderNo?: number
type: string
/** 后端 @JsonProperty("orgCode") 重命名,JSON 中为 orgCode */
orgCode?: string
status: string
createdAt: string
updatedAt: string
/** 非表字段,后端 join 返回 */
parentOrgName?: string
channelName?: string
children?: StoreInfo[]
}
/**
* 门店列表查询参数
*/
export interface StoreListParams extends ManagePageParams {
name?: string
status?: string
channelOrgId?: number
}
/**
* 门店保存/更新数据
*/
export interface StoreSaveData {
id?: number
parentId: number
name: string
orgCode?: string
}
/** 门店分页列表 */
export function getStoreList(params?: StoreListParams): Promise<ManageListResponse<StoreInfo>> {
return http.get(http.adornUrl('/manage/org/store/list'), { params: http.adornParams(params || {}) }).then(res => res.data)
}
/** 门店详情 */
export function getStoreInfo(id: number): Promise<ManageResponse<{ store?: StoreInfo }>> {
return http.get(http.adornUrl(`/manage/org/store/info/${id}`), { params: http.adornParams() }).then(res => res.data)
}
/** 新增/修改门店 */
export function saveOrUpdateStore(data: StoreSaveData): Promise<ManageResponse> {
const url = data.id ? '/manage/org/store/update' : '/manage/org/store/save'
return http.post(http.adornUrl(url), http.adornData(data)).then(res => res.data)
}
/** 删除门店(批量软删除) */
export function deleteStore(ids: number[]): Promise<ManageResponse> {
return http.post(http.adornUrl('/manage/org/store/delete'), http.adornData(ids, false)).then(res => res.data)
}

33
src/api/manage/types.ts Normal file
View File

@@ -0,0 +1,33 @@
/**
* /manage/ 接口共享类型定义
*
* 统一响应格式:{ code, msg, data: {...} }
* - 业务数据统一在 data 字段内
* - 分页结构在 data.page 内:{ data: { page: { totalCount, list, ... } } }
*/
/** /manage/ 接口统一响应基础格式 */
export interface ManageResponse<T = any> {
code: number
msg: string
data: T
}
/** /manage/ 分页 page 对象 */
export interface ManagePage<T = any> {
totalCount: number
pageSize?: number
totalPage?: number
currPage?: number
list: T[]
}
/** /manage/ 分页列表响应 */
export interface ManageListResponse<T = any> extends ManageResponse<{ page: ManagePage<T> }> {}
/** 分页查询参数 */
export interface ManagePageParams {
page?: number
limit?: number
[key: string]: any
}

53
src/api/mediaAsset.ts Executable file
View File

@@ -0,0 +1,53 @@
import http from '@/utils/httpRequest'
import type { ApiResponse, PageParams, PageResult } from '@/types/api'
/**
* 媒资信息
*/
export interface MediaAsset {
id: number
name: string
code: string
isOnline?: number
deleteFlag?: number
region?: string
releaseYear?: number
[key: string]: any
}
/**
* 媒资列表参数
*/
export interface MediaAssetListParams extends PageParams {
name?: string
code?: string
isOnline?: number
deleteFlag?: number
region?: string
releaseYear?: number
}
/**
* 媒资分页列表
*/
export function getMediaAssetList(
params?: MediaAssetListParams
): Promise<ApiResponse<PageResult<MediaAsset>>> {
return http.get(http.adornUrl('/sys/mediaAsset/list'), { params: http.adornParams(params || {}) })
}
/** 媒资详情 */
export function getMediaAssetInfo(id: number): Promise<ApiResponse<{ mediaAsset: MediaAsset }>> {
return http.get(http.adornUrl(`/sys/mediaAsset/info/${id}`), { params: http.adornParams() })
}
/** 修改/添加媒资 */
export function saveMediaAsset(data: Partial<MediaAsset>): Promise<ApiResponse<any>> {
const url = data.id ? '/sys/mediaAsset/update' : '/sys/mediaAsset/save'
return http.post(http.adornUrl(url), http.adornData(data))
}
/** 删除媒资 */
export function deleteMediaAsset(ids: number[]): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/mediaAsset/delete'), http.adornData(ids, false))
}

95
src/api/mediaAssetRank.ts Executable file
View File

@@ -0,0 +1,95 @@
import http from '@/utils/httpRequest'
import type { ApiResponse } from '@/types/api'
/**
* 媒资排行项
*/
export interface MediaAssetRankItem {
code: string
name: string
sortOrder: number
[key: string]: any
}
/**
* 设置排行榜数据
*/
export interface SetRankData {
codeList: string[]
}
/**
* 排序更新数据
*/
export interface UpdateSortData {
code?: string
targetSortOrder?: number
orderList?: Array<{ code: string; sortOrder: number }>
}
/** 获取当前 Top10 榜(含媒资信息) */
export function getMediaAssetRankTop10(): Promise<ApiResponse<{ rankList: MediaAssetRankItem[] }>> {
return http.get(http.adornUrl('/sys/mediaAssetRank/top10'), { params: http.adornParams() })
}
/** 当前排序/序号信息 */
export function getMediaAssetRankGetSortOrder(): Promise<ApiResponse<any>> {
return http.get(http.adornUrl('/sys/mediaAssetRank/getSortOrder'), { params: http.adornParams() })
}
/**
* 批量设置排行榜
* 若依侧通过 adornData 会附带 t 等默认字段,一般与 Jackson 兼容。
* @param data 仅编码数组,或 { codeList }
*/
export function setMediaAssetRank(data: string[] | SetRankData): Promise<ApiResponse<any>> {
const codeList = Array.isArray(data)
? data
: data?.codeList || []
return http.post(
http.adornUrl('/sys/mediaAssetRank/set'),
http.adornData({ codeList }, true)
)
}
/** 单条移除 */
export function removeMediaAssetRank(code: string): Promise<ApiResponse<any>> {
return http.post(
http.adornUrl('/sys/mediaAssetRank/remove'),
http.adornData({ code }, true)
)
}
/**
* 调整排序
* 请求体与后端一致,如 { code, targetSortOrder } 或 { orderList: [...] } 等
*/
export function updateMediaAssetRankSort(data: UpdateSortData): Promise<ApiResponse<any>> {
return http.post(
http.adornUrl('/sys/mediaAssetRank/updateSort'),
http.adornData(data && typeof data === 'object' ? data : {}, true)
)
}
/** 上移一位 */
export function moveUpMediaAssetRank(code: string): Promise<ApiResponse<any>> {
return http.post(
http.adornUrl('/sys/mediaAssetRank/moveUp'),
http.adornData({}),
{ params: http.adornParams({ code }) }
)
}
/** 下移一位 */
export function moveDownMediaAssetRank(code: string): Promise<ApiResponse<any>> {
return http.post(
http.adornUrl('/sys/mediaAssetRank/moveDown'),
http.adornData({}),
{ params: http.adornParams({ code }) }
)
}
/** 清空排行榜 */
export function clearMediaAssetRank(): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/mediaAssetRank/clear'), http.adornData({}))
}

148
src/api/org.ts Executable file
View File

@@ -0,0 +1,148 @@
import http from '@/utils/httpRequest'
import type { ApiResponse, PageParams, PageResult } from '@/types/api'
/**
* 组织信息
*/
export interface OrgInfo {
id: number
name: string
parentId?: number
type?: string
status?: string
[key: string]: any
}
/**
* 组织列表参数
*/
export interface OrgListParams extends PageParams {
name?: string
type?: string
}
/**
* 组织卡统计
*/
export interface OrgCardStats {
allocatable: number
activated: number
pendingActivation: number
}
/**
* 组织卡总览
*/
export interface OrgCardOverview {
totalCount: number
usedCount: number
availableCount: number
}
/**
* 组织版本信息
*/
export interface OrgVersionInfo {
orgId: number
verCode?: string
verName?: string
url?: string
touchUrl?: string
keyUrl?: string
compulsory?: boolean
}
/** 组织树 */
export function getOrgTree(params?: OrgListParams): Promise<ApiResponse<OrgInfo[]>> {
return http.get(http.adornUrl('/manage/org/tree'), { params: http.adornParams(params || {}) })
}
/** 组织树(含门店):全类型组织树,含 STORE 节点,用于门店选择器等 */
export function getOrgAllTree(params?: OrgListParams): Promise<ApiResponse<OrgInfo[]>> {
return http.get(http.adornUrl('/manage/org/all-tree'), { params: http.adornParams(params || {}) })
}
/**
* 解析 /manage/org/list-data 等接口响应体中的扁平组织列表。
* 兼容:顶层 `list`、或 `data` 为数组、或 `data: { list }`。
*/
export function parseOrgListDataBody(body: Record<string, any> | null | undefined): OrgInfo[] {
if (!body) return []
if (Array.isArray(body.list)) return body.list as OrgInfo[]
const inner = body.data
if (Array.isArray(inner)) return inner as OrgInfo[]
if (inner && typeof inner === 'object' && Array.isArray(inner.list)) return inner.list as OrgInfo[]
return []
}
/** 组织列表(扁平,用于下拉/树选) */
export function getOrgListData(params?: OrgListParams): Promise<ApiResponse<OrgInfo[]>> {
return http.get(http.adornUrl('/manage/org/list-data'), { params: http.adornParams(params || {}) })
}
/** 组织列表(/list) */
export function getOrgList(params?: OrgListParams): Promise<ApiResponse<PageResult<OrgInfo>>> {
return http.get(http.adornUrl('/manage/org/list'), { params: http.adornParams(params || {}) })
}
/** 当前账号数据范围内全部渠道(type=CHANNEL、ACTIVE)扁平列表 */
export function getOrgChannels(): Promise<ApiResponse<OrgInfo[]>> {
return http.get(http.adornUrl('/manage/org/channels'), { params: http.adornParams() })
}
/** 指定渠道下仅 SERVICE_PROVIDER 的多级树(不含门店) */
export function getChannelAgentTree(channelId: number): Promise<ApiResponse<OrgInfo[]>> {
return http.get(http.adornUrl(`/manage/org/channel/${channelId}/agent-tree`), { params: http.adornParams() })
}
/** 组织详情 */
export function getOrgInfo(id: number): Promise<ApiResponse<OrgInfo>> {
return http.get(http.adornUrl(`/manage/org/info/${id}`), { params: http.adornParams() })
}
/** 删除组织(单个或批量) */
export function deleteOrg(ids: number[]): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/manage/org/delete'), http.adornData(ids, false))
}
/** 组织下卡统计(可分配/已激活/待激活) */
export function getOrgCardStats(orgId: number): Promise<ApiResponse<OrgCardStats>> {
return http.get(http.adornUrl(`/manage/org/${orgId}/card-stats`), { params: http.adornParams() })
}
/** 组织卡总览统计(用于设备导入页顶部数据概览) */
export function getOrgCardOverview(params?: { orgId?: number }): Promise<ApiResponse<OrgCardOverview>> {
return http.get(http.adornUrl('/manage/org/card-overview'), { params: http.adornParams(params || {}) })
}
/** 按卡类型维度的明细统计(首页/全库口径) */
export function getOrgCardTypeDetailStats(params?: { orgId?: number }): Promise<ApiResponse<any>> {
return http.get(http.adornUrl('/manage/org/card-type-detail-stats'), { params: http.adornParams(params || {}) })
}
/** 同渠道组织树(用于设备卡转移选择目标组织) */
export function getSameChannelOrgs(orgId: number): Promise<ApiResponse<OrgInfo[]>> {
return http.get(http.adornUrl(`/manage/org/${orgId}/same-channel-orgs`), { params: http.adornParams() })
}
/** 组织保存/更新(根据是否有 id 决定) */
export function saveOrUpdateOrg(data: Partial<OrgInfo>): Promise<ApiResponse<any>> {
const url = data.id ? '/manage/org/update' : '/manage/org/save'
return http.post(http.adornUrl(url), http.adornData(data))
}
/** 组织版本详情 */
export function getOrgVersionInfo(orgId: number): Promise<ApiResponse<OrgVersionInfo>> {
return http.get(http.adornUrl('/sys/org-version/info'), { params: http.adornParams({ orgId }) })
}
/** 组织版本保存 { orgId, verCode, ver_name, url, compulsory } */
export function saveOrgVersion(data: OrgVersionInfo): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/org-version/save'), http.adornData(data))
}
/** 删除组织版本 */
export function deleteOrgVersion(orgId: number): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/org-version/delete'), http.adornData({ orgId }))
}

60
src/api/oss.ts Executable file
View File

@@ -0,0 +1,60 @@
import http from '@/utils/httpRequest'
/**
* 后端 STS 临时凭证(字段名兼容常见驼峰写法;与 COS getAuthorization 入参对齐)
*/
export interface OssStsCredentialPayload {
TmpSecretId?: string
tmpSecretId?: string
TmpSecretKey?: string
tmpSecretKey?: string
SecurityToken?: string
securityToken?: string
sessionToken?: string
/** 过期时间戳(秒,或毫秒则由上传工具归一化) */
ExpiredTime?: number
expiredTime?: number
bucket?: string
Bucket?: string
region?: string
Region?: string
/** 对象 Key(须与 STS 策略一致,不可自行改写) */
key?: string
Key?: string
/** 上传成功后的访问地址 */
url?: string
/** 以下字段不参与 COS 前端上传,仅占位兼容接口 */
appId?: number
startTime?: number
durationSeconds?: number
}
/** GET /sys/oss/sts-credential 实际响应:凭证在顶层 `credential`(非标准 `data`) */
export interface OssStsCredentialApiResponse {
code: number
msg: string
credential?: OssStsCredentialPayload
/** 兼容若后端改为包在 data 内 */
data?: OssStsCredentialPayload
}
export interface OssStsCredentialOptions {
/** 为 true 时请求保留原始文件名(不去重哈希),需后端 sts-credential 支持 */
keepOriginalFileName?: boolean
}
/** GET /sys/oss/sts-credential?filename=xxx */
export function getOssStsCredential (
filename: string,
options?: OssStsCredentialOptions
): Promise<OssStsCredentialApiResponse> {
const params: Record<string, string | number> = { filename }
if (options?.keepOriginalFileName) {
params.keepOriginalFileName = 1
params.dedupe = 0
}
return http
.get(http.adornUrl('/sys/oss/sts-credential'), {
params: http.adornParams(params),
})
.then(res => res.data)
}

54
src/api/store.ts Executable file
View File

@@ -0,0 +1,54 @@
import http from '@/utils/httpRequest'
import type { ApiResponse, PageParams, PageResult } from '@/types/api'
/**
* 门店信息
*/
export interface StoreInfo {
id: number
name: string
orgId: number
status?: string
[key: string]: any
}
/**
* 门店列表参数
*/
export interface StoreListParams extends PageParams {
name?: string
orgId?: number
}
/**
* 门店卡信息
*/
export interface StoreCard {
id: number
cardNo: string
status: string
[key: string]: any
}
/** 门店列表(下拉等场景) */
export function getStoreList(params?: StoreListParams): Promise<ApiResponse<StoreInfo[]>> {
return http.get(http.adornUrl('/manage/store/list'), { params: http.adornParams(params || {}) })
}
/** 按代理商组织查询门店(与 list + orgId=代理商 等价;会校验目标为 SERVICE_PROVIDER) */
export function getStoreListByAgent(agentOrgId: number): Promise<ApiResponse<StoreInfo[]>> {
return http.get(http.adornUrl(`/manage/store/list-by-agent/${agentOrgId}`), { params: http.adornParams() })
}
/** 门店搜索(分页) */
export function searchStore(params?: StoreListParams): Promise<ApiResponse<PageResult<StoreInfo>>> {
return http.get(http.adornUrl('/manage/store/search'), { params: http.adornParams(params || {}) })
}
/** 门店下的卡列表 */
export function getStoreCards(
storeId: number,
params?: PageParams
): Promise<ApiResponse<PageResult<StoreCard>>> {
return http.get(http.adornUrl(`/manage/store/${storeId}/cards`), { params: http.adornParams(params || {}) })
}

351
src/api/sys.ts Executable file
View File

@@ -0,0 +1,351 @@
import http from '@/utils/httpRequest'
import type { ApiResponse, PageParams, PageResult } from '@/types/api'
import { uploadFileViaStsCos } from '@/utils/ossCosUpload'
// ==================== 类型定义 ====================
/**
* 登录表单数据
*/
export interface LoginData {
username: string
password: string
captcha: string
uuid: string
}
/**
* 登录响应
*/
export interface LoginResult {
token: string
expire: number
refreshToken?: string
refreshExpire?: number
}
/**
* 用户信息
*/
export interface UserInfo {
id: number
username: string
realName?: string
avatar?: string
roleIdList?: number[]
orgId?: number
orgName?: string
[key: string]: any
}
/**
* 菜单信息
*/
export interface MenuInfo {
id: number
parentId?: number
name: string
url?: string
icon?: string
sort?: number
show?: number
perms?: string
list?: MenuInfo[]
[key: string]: any
}
/**
* 菜单导航响应
*/
export interface MenuNavResponse {
code: number
menuList: MenuInfo[]
permissions: string[]
}
/**
* 角色信息
*/
export interface RoleInfo {
id: number
roleName: string
remark?: string
[key: string]: any
}
/**
* 参数配置
*/
export interface ConfigInfo {
id: number
paramKey: string
paramValue: string
remark?: string
[key: string]: any
}
/**
* 定时任务
*/
export interface ScheduleInfo {
jobId?: number
beanName: string
methodName: string
params?: string
cronExpression: string
status?: number
remark?: string
[key: string]: any
}
/**
* 日志信息
*/
export interface LogInfo {
id: number
operation: string
method: string
params?: string
time?: number
ip?: string
createDate?: string
[key: string]: any
}
/**
* 审计日志
*/
export interface AuditLogInfo extends LogInfo {
module?: string
action?: string
[key: string]: any
}
/** 吉客云 / JST API 调用日志(设备与组织可为空) */
export interface ApiJstCallLogInfo {
id?: number
apiPath?: string | null
requestBody?: string | null
dataId?: string | number | null
createTime?: string | null
mac?: string | null
deviceSn?: string | null
deviceUid?: string | null
storeOrgId?: number | null
storeOrgName?: string | null
storeOrgCode?: string | null
storeOrgType?: string | null
[key: string]: any
}
/**
* 定时任务日志
*/
export interface ScheduleLogInfo {
logId: number
jobId: number
beanName: string
methodName: string
params?: string
status?: number
error?: string
times?: number
createTime?: string
[key: string]: any
}
// ==================== 登录 / 认证 ====================
export function login(data: LoginData): Promise<ApiResponse<LoginResult>> {
return http.post(http.adornUrl('/sys/login'), http.adornData(data)).then(res => res.data)
}
export function logout(): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/logout'), http.adornData({})).then(res => res.data)
}
/** 获取当前登录用户信息;若传入 userId,则获取指定用户信息 */
export function getUserInfo(userId?: number | string | null): Promise<ApiResponse<UserInfo>> {
const url = userId !== null && userId !== undefined && userId !== ''
? `/manage/user/info/${userId}`
: '/manage/user/info'
return http.get(http.adornUrl(url), { params: http.adornParams() }).then(res => res.data)
}
export function updatePassword(data: { password: string; newPassword: string }): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/manage/user/password'), http.adornData(data)).then(res => res.data)
}
// ==================== 菜单 ====================
export function getMenuNav(): Promise<ApiResponse<MenuNavResponse>> {
return http.get(http.adornUrl('/manage/menu/nav'), { params: http.adornParams() }).then(res => res.data)
}
/** 验证码图片地址(img src 需完整路径 /api/xxx,走代理) */
export function getCaptchaUrl(uuid: string): string {
return http.adornUrl(`/captcha.jpg?uuid=${uuid}`)
}
export function getMenuList(params?: PageParams): Promise<ApiResponse<PageResult<MenuInfo>>> {
return http.get(http.adornUrl('/manage/menu/list'), { params: http.adornParams(params || {}) }).then(res => res.data)
}
export function getMenuSelect(): Promise<ApiResponse<{ menuList: MenuInfo[] }>> {
return http.get(http.adornUrl('/manage/menu/select'), { params: http.adornParams() }).then(res => res.data)
}
export function getMenuInfo(id: number): Promise<ApiResponse<MenuInfo>> {
return http.get(http.adornUrl(`/manage/menu/info/${id}`), { params: http.adornParams() }).then(res => res.data)
}
export function saveMenu(data: Partial<MenuInfo>): Promise<ApiResponse<any>> {
const url = data.id ? '/manage/menu/update' : '/manage/menu/save'
return http.post(http.adornUrl(url), http.adornData(data)).then(res => res.data)
}
export function deleteMenu(id: number): Promise<ApiResponse<any>> {
return http.post(http.adornUrl(`/manage/menu/delete/${id}`), http.adornData({})).then(res => res.data)
}
// ==================== 用户 ====================
export function getUserList(params?: PageParams): Promise<ApiResponse<PageResult<UserInfo>>> {
return http.get(http.adornUrl('/manage/user/list'), { params: http.adornParams(params || {}) }).then(res => res.data)
}
export function getUserInfoById(id: number): Promise<ApiResponse<UserInfo>> {
return getUserInfo(id)
}
export function saveUser(data: Partial<UserInfo>): Promise<ApiResponse<any>> {
const url = data.id ? '/manage/user/update' : '/manage/user/save'
return http.post(http.adornUrl(url), http.adornData(data)).then(res => res.data)
}
export function deleteUser(ids: number[]): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/manage/user/delete'), http.adornData(ids, false)).then(res => res.data)
}
export function getRoleSelect(): Promise<ApiResponse<{ list: RoleInfo[] }>> {
return http.get(http.adornUrl('/manage/role/select'), { params: http.adornParams() }).then(res => res.data)
}
// ==================== 角色 ====================
export function getRoleList(params?: PageParams): Promise<ApiResponse<PageResult<RoleInfo>>> {
return http.get(http.adornUrl('/manage/role/list'), { params: http.adornParams(params || {}) }).then(res => res.data)
}
export function getRoleInfo(id: number): Promise<ApiResponse<RoleInfo>> {
return http.get(http.adornUrl(`/manage/role/info/${id}`), { params: http.adornParams() }).then(res => res.data)
}
export function saveRole(data: Partial<RoleInfo>): Promise<ApiResponse<any>> {
const url = data.id ? '/manage/role/update' : '/manage/role/save'
return http.post(http.adornUrl(url), http.adornData(data)).then(res => res.data)
}
export function deleteRole(ids: number[]): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/manage/role/delete'), http.adornData(ids, false)).then(res => res.data)
}
// ==================== 参数配置 ====================
export function getConfigList(params?: PageParams): Promise<ApiResponse<PageResult<ConfigInfo>>> {
return http.get(http.adornUrl('/sys/config/list'), { params: http.adornParams(params || {}) }).then(res => res.data)
}
export function getConfigInfo(id: number): Promise<ApiResponse<ConfigInfo>> {
return http.get(http.adornUrl(`/sys/config/info/${id}`), { params: http.adornParams() }).then(res => res.data)
}
export function saveConfig(data: Partial<ConfigInfo>): Promise<ApiResponse<any>> {
const url = data.id ? '/sys/config/update' : '/sys/config/save'
return http.post(http.adornUrl(url), http.adornData(data)).then(res => res.data)
}
export function deleteConfig(ids: number[]): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/config/delete'), http.adornData(ids, false)).then(res => res.data)
}
// ==================== 日志 ====================
export function getLogList(params?: PageParams): Promise<ApiResponse<PageResult<LogInfo>>> {
return http.get(http.adornUrl('/sys/log/list'), { params: http.adornParams(params || {}) }).then(res => res.data)
}
/** 审计日志;分页结构含 totalCount、list 等,与系统日志分页一致 */
export function getAuditLogList(params?: PageParams): Promise<ApiResponse<PageResult<AuditLogInfo>>> {
return http.get(http.adornUrl('/sys/auditLog/list'), { params: http.adornParams(params || {}) }).then(res => res.data)
}
/** API 调用日志(JST 等);分页结构与审计日志一致 */
export function getApiJstCallLogList(params?: PageParams): Promise<ApiResponse<PageResult<ApiJstCallLogInfo>>> {
return http.get(http.adornUrl('/sys/apiJstCallLog/list'), { params: http.adornParams(params || {}) }).then(res => res.data)
}
// ==================== 定时任务 ====================
export function getScheduleList(params?: PageParams): Promise<ApiResponse<PageResult<ScheduleInfo>>> {
return http.get(http.adornUrl('/sys/schedule/list'), { params: http.adornParams(params || {}) }).then(res => res.data)
}
export function getScheduleInfo(id: number): Promise<ApiResponse<ScheduleInfo>> {
return http.get(http.adornUrl(`/sys/schedule/info/${id}`), { params: http.adornParams() }).then(res => res.data)
}
export function saveSchedule(data: Partial<ScheduleInfo>): Promise<ApiResponse<any>> {
const url = data.jobId ? '/sys/schedule/update' : '/sys/schedule/save'
return http.post(http.adornUrl(url), http.adornData(data)).then(res => res.data)
}
export function deleteSchedule(ids: number[]): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/schedule/delete'), http.adornData(ids, false)).then(res => res.data)
}
export function pauseSchedule(jobId: number): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/schedule/pause'), http.adornData({ jobId })).then(res => res.data)
}
export function resumeSchedule(jobId: number): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/schedule/resume'), http.adornData({ jobId })).then(res => res.data)
}
export function runSchedule(jobId: number): Promise<ApiResponse<any>> {
return http.post(http.adornUrl('/sys/schedule/run'), http.adornData({ jobId })).then(res => res.data)
}
// ==================== 定时任务日志 ====================
export function getScheduleLogList(params?: PageParams): Promise<ApiResponse<PageResult<ScheduleLogInfo>>> {
return http.get(http.adornUrl('/sys/scheduleLog/list'), { params: http.adornParams(params || {}) }).then(res => res.data)
}
export function getScheduleLogInfo(id: number): Promise<ApiResponse<ScheduleLogInfo>> {
return http.get(http.adornUrl(`/sys/scheduleLog/info/${id}`), { params: http.adornParams() }).then(res => res.data)
}
// ==================== OSS 上传 ====================
/** 直传 COS:GET STS 凭证后前端 putObject,成功返回 data.url(与后端下发 key 一致) */
export async function uploadOssDedupe (file: File): Promise<ApiResponse<{ url: string }>> {
try {
const url = await uploadFileViaStsCos(file)
return { code: 0, msg: 'success', data: { url } }
} catch (e: unknown) {
const message = e instanceof Error ? e.message : '上传失败'
return { code: 500, msg: message, data: { url: '' } }
}
}
/** 直传 COS 且保留原始文件名(版本 APK 等场景,需后端 sts-credential 支持 keepOriginalFileName) */
export async function uploadOssKeepFileName (file: File): Promise<ApiResponse<{ url: string }>> {
try {
const url = await uploadFileViaStsCos(file, { keepOriginalFileName: true })
return { code: 0, msg: 'success', data: { url } }
} catch (e: unknown) {
const message = e instanceof Error ? e.message : '上传失败'
return { code: 500, msg: message, data: { url: '' } }
}
}