diff --git a/apps/web-antd/src/adapter/vxe-table.ts b/apps/web-antd/src/adapter/vxe-table.ts index 9c0cd73..c1e21fc 100644 --- a/apps/web-antd/src/adapter/vxe-table.ts +++ b/apps/web-antd/src/adapter/vxe-table.ts @@ -62,14 +62,27 @@ setupVbenVxeTable({ }, }); - // 表格配置项可以用 cellRender: { name: 'CellLink' }, + // 表格配置项可以用 cellRender: { name: 'CellLink' };未传 text 时默认展示当前列字段值 vxeUI.renderer.add('CellLink', { - renderTableDefault(renderOpts) { + renderTableDefault(renderOpts, params) { const { props } = renderOpts; + const { column, row } = params; + const raw = + props?.text !== undefined && props?.text !== null && props?.text !== '' + ? props.text + : get(row, column.field); + const display = + raw === null || raw === undefined || raw === '' ? '—' : String(raw); return h( Button, - { size: 'small', type: 'link' }, - { default: () => props?.text }, + { + size: 'small', + type: 'link', + onClick: isFunction(props?.onClick) + ? () => (props.onClick as (r: Recordable) => void)(row) + : undefined, + }, + { default: () => display }, ); }, }); @@ -160,10 +173,10 @@ setupVbenVxeTable({ return presets[opt] ? { code: opt, ...presets[opt], ...defaultProps } : { - code: opt, - text: $te(`common.${opt}`) ? $t(`common.${opt}`) : opt, - ...defaultProps, - }; + code: opt, + text: $te(`common.${opt}`) ? $t(`common.${opt}`) : opt, + ...defaultProps, + }; } else { return { ...defaultProps, ...presets[opt.code], ...opt }; } @@ -177,6 +190,17 @@ setupVbenVxeTable({ }) .filter((opt) => opt.show !== false); + function isOperationDisabled(opt: Recordable, r: Recordable) { + const d = opt.disabled; + if (d === true) { + return true; + } + if (isFunction(d)) { + return !!d(r); + } + return false; + } + function renderBtn(opt: Recordable, listen = true) { return h( Button, @@ -185,11 +209,15 @@ setupVbenVxeTable({ ...opt, icon: undefined, onClick: listen - ? () => + ? () => { + if (isOperationDisabled(opt, row)) { + return; + } attrs?.onClick?.({ code: opt.code, row, - }) + }); + } : undefined, }, { @@ -225,6 +253,9 @@ setupVbenVxeTable({ ...opt, icon: undefined, onConfirm: () => { + if (isOperationDisabled(opt, row)) { + return; + } attrs?.onClick?.({ code: opt.code, row, diff --git a/apps/web-antd/src/api/agent/agent.ts b/apps/web-antd/src/api/agent/agent.ts index fca6505..2f661da 100644 --- a/apps/web-antd/src/api/agent/agent.ts +++ b/apps/web-antd/src/api/agent/agent.ts @@ -2,8 +2,11 @@ import { requestClient } from '#/api/request'; export namespace AgentApi { export interface AgentListItem { - id: number; - user_id: number; + id: string | number; + user_id: string | number; + level?: number; + agent_code?: number; + team_leader_id?: string; level_name: string; region: string; mobile: string; @@ -13,10 +16,17 @@ export namespace AgentApi { frozen_balance: number; withdrawn_amount: number; create_time: string; - is_real_name_verified: boolean; + is_real_name_verified?: boolean; + /** 与后端 json 字段 is_real_name 一致 */ + is_real_name?: boolean; real_name: string; id_card: string; real_name_status: 'approved' | 'pending' | 'rejected'; + // 订单统计相关字段 + total_orders?: number; // 订单总数 + total_order_amount?: number; // 订单总金额 + total_agent_profit?: number; // 代理总收益 + subordinate_count?: number; // 下级数量 } export interface AgentList { @@ -24,17 +34,34 @@ export namespace AgentApi { items: AgentListItem[]; } + /** 后台代理团队树节点 */ + export interface AgentTeamTreeNode { + id: string; + agent_code: number; + level: number; + level_name: string; + mobile: string; + is_anchor: boolean; + children?: AgentTeamTreeNode[]; + } + export interface GetAgentListParams { page: number; pageSize: number; mobile?: string; + agent_code?: string; + agent_id?: string; region?: string; parent_agent_id?: number; + level?: number; + team_leader_id?: string; id?: number; create_time_start?: string; create_time_end?: string; order_by?: string; order_type?: 'asc' | 'desc'; + /** 实名姓名模糊筛选(须已三要素核验) */ + real_name?: string; } export interface AgentLinkListItem { @@ -54,15 +81,18 @@ export namespace AgentApi { page: number; pageSize: number; agent_id?: number; + agent_code?: string; product_name?: string; link_identifier?: string; } // 代理佣金相关接口 export interface AgentCommissionListItem { - id: number; - agent_id: number; - order_id: number; + id: string | number; + agent_id: string | number; + agent_code?: number; + order_id: string | number; + order_no: string; amount: number; product_name: string; status: number; @@ -78,7 +108,8 @@ export namespace AgentApi { page: number; pageSize: number; agent_id?: number; - product_name?: string; + agent_code?: string; + order_no?: string; status?: number; } @@ -109,6 +140,7 @@ export namespace AgentApi { export interface AgentWithdrawalListItem { id: string; agent_id: string; + agent_code?: number; withdraw_no: string; amount: number; tax_amount: number; @@ -132,9 +164,12 @@ export namespace AgentApi { page: number; pageSize: number; agent_id?: number | string; - status?: number; + agent_code?: string; withdraw_no?: string; - withdrawal_type?: number; + status?: number | string; + withdrawal_type?: number | string; + payee_account?: string; + payee_name?: string; } export interface AuditWithdrawalParams { @@ -313,11 +348,55 @@ export namespace AgentApi { items: T[]; } + /** 后台代理订单列表行(与 AdminGetAgentOrderList 对齐) */ + export interface AgentOrderListItem { + id: string; + agent_id: string; + agent_code: number; + order_id: string; + order_no: string; + product_id: string; + product_name: string; + order_amount: number; + set_price: number; + actual_base_price: number; + price_cost: number; + agent_profit: number; + process_status: number; + order_status: string; + create_time: string; + } + export interface GetAgentOrderListParams { page: number; pageSize: number; agent_id?: number | string; - [key: string]: any; + agent_code?: string; + order_id?: string; + order_no?: string; + process_status?: number; + order_status?: string; + } + + /** 单笔订单分账(佣金 + 返佣) */ + export interface AdminGetAgentOrderSettlementResp { + commissions: AgentCommissionListItem[]; + rebates: AgentRebateListItem[]; + } + + /** 后台返佣列表行 */ + export interface AgentRebateListItem { + id: string; + agent_id: string; + agent_code: number; + source_agent_id: string; + source_agent_code: number; + order_id: string; + order_no: string; + rebate_type: number; + amount: number; + status: number; + create_time: string; } export interface GetAgentRealNameListParams { @@ -331,21 +410,28 @@ export namespace AgentApi { page: number; pageSize: number; agent_id?: number | string; - [key: string]: any; + agent_code?: string; + source_agent_code?: string; + order_no?: string; + rebate_type?: number; + status?: number; } export interface GetAgentUpgradeListParams { page: number; pageSize: number; agent_id?: number | string; - [key: string]: any; + agent_code?: string; + upgrade_type?: number; + status?: number; } export interface GetInviteCodeListParams { page: number; pageSize: number; + code?: string; + status?: number | string; target_level?: number; - [key: string]: any; } export interface GenerateDiamondInviteCodeParams { @@ -408,6 +494,16 @@ async function getAgentList(params: AgentApi.GetAgentListParams) { }); } +/** 后台:代理团队树(同钻石团队 + 邀请关系) */ +async function getAgentTeamTree(agentId: string) { + return requestClient.get<{ root: AgentApi.AgentTeamTreeNode }>( + '/agent/team/tree', + { + params: { agent_id: agentId }, + }, + ); +} + /** * 获取代理推广链接列表 */ @@ -602,12 +698,20 @@ async function getInviteCodeList(params: AgentApi.GetInviteCodeListParams) { * 获取代理订单列表(后台) */ async function getAgentOrderList(params: AgentApi.GetAgentOrderListParams) { - return requestClient.get>>( + return requestClient.get>( '/agent/order/list', { params }, ); } +/** 单笔订单分账视图(单次请求,避免双接口重复鉴权) */ +async function getAgentOrderSettlement(params: { order_no: string }) { + return requestClient.get( + '/agent/order/settlement', + { params }, + ); +} + /** * 获取代理实名认证列表(后台) */ @@ -624,7 +728,7 @@ async function getAgentRealNameList( * 获取代理返佣列表(后台) */ async function getAgentRebateList(params: AgentApi.GetAgentRebateListParams) { - return requestClient.get>>( + return requestClient.get>( '/agent/rebate/list', { params }, ); @@ -659,8 +763,10 @@ export { getAgentConfig, getAgentLinkList, getAgentList, + getAgentTeamTree, getAgentMembershipConfigList, getAgentOrderList, + getAgentOrderSettlement, getAgentPlatformDeductionList, getAgentProductionConfigList, getAgentRealNameList, diff --git a/apps/web-antd/src/api/notification/index.ts b/apps/web-antd/src/api/notification/index.ts index c74fcb3..5e11b53 100644 --- a/apps/web-antd/src/api/notification/index.ts +++ b/apps/web-antd/src/api/notification/index.ts @@ -58,11 +58,27 @@ async function getNotificationList(params: Recordable) { return requestClient.get( '/notification/list', { - params, + params: { + ...params, + _ts: Date.now(), + }, + headers: { + 'Cache-Control': 'no-cache', + Pragma: 'no-cache', + }, }, ); } +/** + * 获取通知详情(按 ID) + */ +async function getNotificationDetail(id: number) { + return requestClient.get( + `/notification/detail/${id}`, + ); +} + /** * 创建通知 */ @@ -100,6 +116,7 @@ async function deleteNotification(id: number) { export { createNotification, deleteNotification, + getNotificationDetail, getNotificationList, updateNotification, }; diff --git a/apps/web-antd/src/api/order/order.ts b/apps/web-antd/src/api/order/order.ts index a990724..6351c9d 100644 --- a/apps/web-antd/src/api/order/order.ts +++ b/apps/web-antd/src/api/order/order.ts @@ -17,6 +17,10 @@ export namespace OrderApi { pay_time: null | string; refund_time: null | string; update_time: string; + // 代理相关字段 + is_agent_order: boolean; // 是否是代理订单 + agent_code?: string; // 代理编号 + agent_process_status?: string; // 代理处理状态 } export interface OrderList { diff --git a/apps/web-antd/src/api/product-manage/product.ts b/apps/web-antd/src/api/product-manage/product.ts index 93fb3f2..cb21162 100644 --- a/apps/web-antd/src/api/product-manage/product.ts +++ b/apps/web-antd/src/api/product-manage/product.ts @@ -25,7 +25,6 @@ export namespace ProductApi { product_en: string; description: string; notes?: string; - cost_price: number; sell_price: number; } @@ -34,7 +33,6 @@ export namespace ProductApi { product_en?: string; description?: string; notes?: string; - cost_price?: number; sell_price?: number; } @@ -44,6 +42,8 @@ export namespace ProductApi { feature_id: number; api_id: string; name: string; + /** 模块成本(元),来自 feature,用于产品侧展示与汇总 */ + cost_price: number; sort: number; enable: number; is_important: number; diff --git a/apps/web-antd/src/api/system/user.ts b/apps/web-antd/src/api/system/user.ts index 9f0649e..d025c9b 100644 --- a/apps/web-antd/src/api/system/user.ts +++ b/apps/web-antd/src/api/system/user.ts @@ -58,7 +58,7 @@ async function deleteUser(id: string) { * @param data.password 新密码 */ async function resetPassword(id: string, data: { password: string }) { - return requestClient.post(`/reset-password/${id}`, data); + return requestClient.put(`/user/reset-password/${id}`, data); } export { createUser, deleteUser, getUserList, resetPassword, updateUser }; diff --git a/apps/web-antd/src/composables/use-agent-list-navigate.ts b/apps/web-antd/src/composables/use-agent-list-navigate.ts new file mode 100644 index 0000000..c63c85c --- /dev/null +++ b/apps/web-antd/src/composables/use-agent-list-navigate.ts @@ -0,0 +1,121 @@ +import type { Router } from 'vue-router'; + +/** 跨页进入代理列表时的一次性定位数据(不写 URL,避免重置后仍被 query 合并) */ +export const AGENT_LIST_FOCUS_STORAGE_KEY = 'qnc_admin_agent_list_focus_v1'; + +export const AGENT_LIST_FOCUS_EVENT = 'qnc:agent-list-focus'; + +/** 旧版曾把面包屑栈写入 sessionStorage;已不再持久化,进入列表时应清除以免把 team_leader_id 写回 URL */ +export const AGENT_LIST_NAV_STACK_KEY = 'qnc_admin_agent_list_nav_stack_v1'; + +export type AgentListNavEntry = + | { kind: 'full' } + | { kind: 'subs'; leaderId: string; leaderCode?: number } + | { kind: 'focus'; agentId?: string; agentCode?: number }; + +export type AgentListFocusPayload = { + agent_code?: string; + agent_id?: string; +}; + +/** 清除历史上保存在 sessionStorage 的导航栈(避免新开/重进列表仍恢复下级视图 URL) */ +export function clearStaleAgentListNavStackStorage() { + if (typeof sessionStorage === 'undefined') { + return; + } + sessionStorage.removeItem(AGENT_LIST_NAV_STACK_KEY); +} + +/** 从定位 payload 生成导航栈节点(用于面包屑) */ +export function navEntryFromFocusPayload( + p: AgentListFocusPayload, +): AgentListNavEntry | null { + const agentId = + p.agent_id != null && String(p.agent_id).trim() !== '' + ? String(p.agent_id) + : undefined; + let agentCode: number | undefined; + if (p.agent_code != null && String(p.agent_code).trim() !== '') { + const n = Number(p.agent_code); + if (!Number.isNaN(n)) { + agentCode = n; + } + } + if (!agentId && agentCode == null) { + return null; + } + return { kind: 'focus', agentId, agentCode }; +} + +function buildPayload(opts: { + agentCode?: string | number | null; + agentId?: string | null; +}): AgentListFocusPayload | null { + const payload: AgentListFocusPayload = {}; + if (opts.agentCode != null && opts.agentCode !== '') { + payload.agent_code = String(opts.agentCode); + } + if (opts.agentId != null && opts.agentId !== '') { + payload.agent_id = String(opts.agentId); + } + if (!payload.agent_code && !payload.agent_id) { + return null; + } + return payload; +} + +/** + * 从 sessionStorage 读取并清除一次性定位数据(用于代理列表页首次进入)。 + */ +export function consumeAgentListFocusFromStorage(): AgentListFocusPayload | null { + if (typeof sessionStorage === 'undefined') { + return null; + } + const raw = sessionStorage.getItem(AGENT_LIST_FOCUS_STORAGE_KEY); + if (!raw) { + return null; + } + sessionStorage.removeItem(AGENT_LIST_FOCUS_STORAGE_KEY); + try { + const v = JSON.parse(raw) as AgentListFocusPayload; + if (!v || typeof v !== 'object') { + return null; + } + return v; + } catch { + return null; + } +} + +/** + * 跳转到代理列表并定位到指定代理。 + * 不写 agent_code / agent_id 到 URL,避免点击「重置」后仍被地址栏参数合并进请求。 + * 已在代理列表页内跳转时通过 CustomEvent 通知当前页应用定位。 + */ +export function navigateToAgentList( + router: Router, + opts: { agentCode?: string | number | null; agentId?: string | null }, +) { + const payload = buildPayload(opts); + if (!payload) { + return; + } + + const isAlreadyOnList = router.currentRoute.value.name === 'AgentList'; + + if (isAlreadyOnList) { + // 先同步写入 ephemeral,再清空 URL。否则仍带着 team_leader_id 时,第一次请求后 ephemeral 被清空, + // 后续请求会重新按 URL 筛「下级列表」,表现为「查看上级」后再点「查看下级」无效或列表错乱。 + window.dispatchEvent( + new CustomEvent(AGENT_LIST_FOCUS_EVENT, { detail: payload }), + ); + void router.replace({ name: 'AgentList', query: {} }); + return; + } + + sessionStorage.setItem(AGENT_LIST_FOCUS_STORAGE_KEY, JSON.stringify(payload)); + router.push({ + name: 'AgentList', + query: {}, + }); +} diff --git a/apps/web-antd/src/composables/use-order-list-navigate.ts b/apps/web-antd/src/composables/use-order-list-navigate.ts new file mode 100644 index 0000000..65d8469 --- /dev/null +++ b/apps/web-antd/src/composables/use-order-list-navigate.ts @@ -0,0 +1,64 @@ +import type { Router } from 'vue-router'; + +/** 跨页进入订单列表时的一次性定位数据(不写 URL,避免重置后仍被 query 合并) */ +export const ORDER_LIST_FOCUS_STORAGE_KEY = 'qnc_admin_order_list_focus_v1'; + +export const ORDER_LIST_FOCUS_EVENT = 'qnc:order-list-focus'; + +export type OrderListFocusPayload = { + order_no?: string; +}; + +export function consumeOrderListFocusFromStorage(): OrderListFocusPayload | null { + if (typeof sessionStorage === 'undefined') { + return null; + } + const raw = sessionStorage.getItem(ORDER_LIST_FOCUS_STORAGE_KEY); + if (!raw) { + return null; + } + sessionStorage.removeItem(ORDER_LIST_FOCUS_STORAGE_KEY); + try { + const v = JSON.parse(raw) as OrderListFocusPayload; + if (!v || typeof v !== 'object') { + return null; + } + return v; + } catch { + return null; + } +} + +/** + * 跳转到订单列表并按商户订单号筛选。 + * 不写 order_no 到 URL,避免点击「重置」后仍被地址栏参数合并进请求。 + * 已在订单列表页内跳转时通过 CustomEvent 通知当前页应用筛选。 + */ +export function navigateToOrderList( + router: Router, + opts: { orderNo?: string | null }, +) { + const orderNo = opts.orderNo != null ? String(opts.orderNo).trim() : ''; + if (!orderNo) { + return; + } + + const payload: OrderListFocusPayload = { order_no: orderNo }; + const r = router.currentRoute.value; + const onOrderList = + r.name === 'Order' || r.path === '/order' || r.path.startsWith('/order?'); + + if (onOrderList) { + window.dispatchEvent( + new CustomEvent(ORDER_LIST_FOCUS_EVENT, { detail: payload }), + ); + void router.replace({ path: '/order', query: {} }); + return; + } + + sessionStorage.setItem( + ORDER_LIST_FOCUS_STORAGE_KEY, + JSON.stringify(payload), + ); + router.push({ path: '/order', query: {} }); +} diff --git a/apps/web-antd/src/composables/use-platform-user-list-navigate.ts b/apps/web-antd/src/composables/use-platform-user-list-navigate.ts new file mode 100644 index 0000000..ecf7562 --- /dev/null +++ b/apps/web-antd/src/composables/use-platform-user-list-navigate.ts @@ -0,0 +1,130 @@ +import type { RouteLocationNormalizedLoaded, Router } from 'vue-router'; + +import { message } from 'ant-design-vue'; + +/** 跨页进入平台用户列表时的一次性筛选(不写 URL query,避免点「重置」后仍合并进请求) */ +export const PLATFORM_USER_LIST_FOCUS_STORAGE_KEY = + 'qnc_admin_platform_user_list_focus_v1'; + +export const PLATFORM_USER_LIST_FOCUS_EVENT = + 'qnc:platform-user-list-focus'; + +export type PlatformUserListFocusPayload = { + user_id?: string; +}; + +function normPath(p: string) { + return p.replace(/\/+/g, '/').replace(/\/+$/, '') || '/'; +} + +function routeScore( + r: Pick, +): number { + const p = normPath(r.path || ''); + const n = String(r.name ?? ''); + if (p.includes('platform-user') && p.includes('list')) { + return 100; + } + if (/platformuserlist/i.test(n)) { + return 90; + } + if (/platform[-_]?user/i.test(p) && /list$/i.test(p)) { + return 80; + } + return 0; +} + +function resolvePlatformUserListTarget(router: Router): { + name?: string | symbol; + path?: string; +} | null { + const routes = router.getRoutes(); + let best: (typeof routes)[0] | null = null; + let bestScore = 0; + for (const r of routes) { + const s = routeScore(r); + if (s > bestScore) { + bestScore = s; + best = r; + } + } + if (best && bestScore >= 80) { + if (best.name != null && String(best.name) !== '') { + return { name: best.name }; + } + return { path: best.path }; + } + const fallbackPath = '/platform-user'; + const fb = routes.find((r) => normPath(r.path || '') === normPath(fallbackPath)); + if (fb?.name != null && String(fb.name) !== '') { + return { name: fb.name }; + } + if (fb?.path) { + return { path: fb.path }; + } + return null; +} + +export function consumePlatformUserListFocusFromStorage(): PlatformUserListFocusPayload | null { + if (typeof sessionStorage === 'undefined') { + return null; + } + const raw = sessionStorage.getItem(PLATFORM_USER_LIST_FOCUS_STORAGE_KEY); + if (!raw) { + return null; + } + sessionStorage.removeItem(PLATFORM_USER_LIST_FOCUS_STORAGE_KEY); + try { + const v = JSON.parse(raw) as PlatformUserListFocusPayload; + if (!v || typeof v !== 'object') { + return null; + } + return v; + } catch { + return null; + } +} + +/** + * 跳转到平台用户列表并按用户主键 ID 精确筛选。 + */ +export function navigateToPlatformUserList( + router: Router, + opts: { userId: string | number | null | undefined }, +) { + const userId = opts.userId != null ? String(opts.userId).trim() : ''; + if (!userId) { + return; + } + + const payload: PlatformUserListFocusPayload = { user_id: userId }; + const r = router.currentRoute.value; + const onPlatformUserList = routeScore(r) >= 80; + + if (onPlatformUserList) { + window.dispatchEvent( + new CustomEvent(PLATFORM_USER_LIST_FOCUS_EVENT, { detail: payload }), + ); + void router.replace({ path: r.path, query: {} }); + return; + } + + const target = resolvePlatformUserListTarget(router); + if (!target) { + message.warning( + '未找到「平台用户」菜单路由,请确认后台菜单组件为 platform-user', + ); + return; + } + + sessionStorage.setItem( + PLATFORM_USER_LIST_FOCUS_STORAGE_KEY, + JSON.stringify(payload), + ); + + if (target.name != null && String(target.name) !== '') { + router.push({ name: target.name as string, query: {} }); + } else if (target.path) { + router.push({ path: target.path, query: {} }); + } +} diff --git a/apps/web-antd/src/locales/langs/en-US/system.json b/apps/web-antd/src/locales/langs/en-US/system.json index b8ec114..2a32d51 100644 --- a/apps/web-antd/src/locales/langs/en-US/system.json +++ b/apps/web-antd/src/locales/langs/en-US/system.json @@ -90,7 +90,8 @@ "setPermissions": "Set Permissions", "createTime": "Create Time", "operation": "Operation", - "resetPassword": "Reset Password", + "changePassword": "Change Password", + "changePasswordSuccess": "Password changed successfully", "newPassword": "New Password", "confirmPassword": "Confirm Password", "confirmPasswordRequired": "Please confirm password", diff --git a/apps/web-antd/src/locales/langs/zh-CN/system.json b/apps/web-antd/src/locales/langs/zh-CN/system.json index 904ea1f..27ac5b3 100644 --- a/apps/web-antd/src/locales/langs/zh-CN/system.json +++ b/apps/web-antd/src/locales/langs/zh-CN/system.json @@ -92,7 +92,8 @@ "setPermissions": "设置权限", "createTime": "创建时间", "operation": "操作", - "resetPassword": "重置密码", + "changePassword": "修改密码", + "changePasswordSuccess": "密码修改成功", "newPassword": "新密码", "confirmPassword": "确认密码", "confirmPasswordRequired": "请确认密码", diff --git a/apps/web-antd/src/router/routes/modules/agent.ts b/apps/web-antd/src/router/routes/modules/agent.ts index a01cc63..0f99323 100644 --- a/apps/web-antd/src/router/routes/modules/agent.ts +++ b/apps/web-antd/src/router/routes/modules/agent.ts @@ -32,6 +32,7 @@ const routes: RouteRecordRaw[] = [ path: '/agent/commission', name: 'AgentCommission', meta: { + hideInMenu: true, icon: 'mdi:cash-multiple', title: '佣金记录', }, @@ -41,6 +42,7 @@ const routes: RouteRecordRaw[] = [ path: '/agent/rebate', name: 'AgentRebate', meta: { + hideInMenu: true, icon: 'mdi:currency-usd', title: '返佣记录', }, diff --git a/apps/web-antd/src/router/routes/modules/dashboard.ts b/apps/web-antd/src/router/routes/modules/dashboard.ts index 5254dc6..a49b360 100644 --- a/apps/web-antd/src/router/routes/modules/dashboard.ts +++ b/apps/web-antd/src/router/routes/modules/dashboard.ts @@ -22,15 +22,6 @@ const routes: RouteRecordRaw[] = [ title: $t('page.dashboard.analytics'), }, }, - { - name: 'Workspace', - path: '/workspace', - component: () => import('#/views/dashboard/workspace/index.vue'), - meta: { - icon: 'carbon:workspace', - title: $t('page.dashboard.workspace'), - }, - }, ], }, ]; diff --git a/apps/web-antd/src/utils/agent.ts b/apps/web-antd/src/utils/agent.ts index 7997ff4..51af7e3 100644 --- a/apps/web-antd/src/utils/agent.ts +++ b/apps/web-antd/src/utils/agent.ts @@ -65,7 +65,7 @@ export function getOrderProcessStatusName(status: number): string { */ export function getUpgradeStatusName(status: number): string { const map: Record = { - 1: '待处理', + 1: '待支付', 2: '已完成', 3: '已失败', }; diff --git a/apps/web-antd/src/views/_core/about/index.vue b/apps/web-antd/src/views/_core/about/index.vue deleted file mode 100644 index 0ee5243..0000000 --- a/apps/web-antd/src/views/_core/about/index.vue +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/apps/web-antd/src/views/agent/agent-commission/data.ts b/apps/web-antd/src/views/agent/agent-commission/data.ts index f34d762..4d8e9f2 100644 --- a/apps/web-antd/src/views/agent/agent-commission/data.ts +++ b/apps/web-antd/src/views/agent/agent-commission/data.ts @@ -1,18 +1,36 @@ import type { VbenFormSchema } from '#/adapter/form'; import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { AgentApi } from '#/api/agent'; + +type OrderNoClickFn = (row: AgentApi.AgentCommissionListItem) => void; // 佣金记录列表列配置 -export function useCommissionColumns(): VxeTableGridOptions['columns'] { +export function useCommissionColumns( + onAgentCodeClick?: (row: AgentApi.AgentCommissionListItem) => void, + onOrderNoClick?: OrderNoClickFn, +): VxeTableGridOptions['columns'] { return [ { - field: 'agent_id', - title: '代理ID', - width: 100, + field: 'agent_code', + title: '代理编号', + width: 110, + cellRender: onAgentCodeClick + ? { + name: 'CellLink', + props: { onClick: onAgentCodeClick }, + } + : undefined, }, { - field: 'order_id', - title: '订单ID', - width: 100, + field: 'order_no', + title: '商户订单号', + minWidth: 180, + cellRender: onOrderNoClick + ? { + name: 'CellLink', + props: { onClick: onOrderNoClick }, + } + : undefined, }, { field: 'amount', @@ -54,8 +72,21 @@ export function useCommissionFormSchema(): VbenFormSchema[] { return [ { component: 'Input', - fieldName: 'product_name', - label: '产品名称', + fieldName: 'agent_code', + label: '代理编号', + componentProps: { + placeholder: '请输入代理编号', + allowClear: true, + }, + }, + { + component: 'Input', + fieldName: 'order_no', + label: '商户订单号', + componentProps: { + placeholder: '请输入商户订单号', + allowClear: true, + }, }, { component: 'Select', diff --git a/apps/web-antd/src/views/agent/agent-commission/list.vue b/apps/web-antd/src/views/agent/agent-commission/list.vue index b60e1f0..11cb4d5 100644 --- a/apps/web-antd/src/views/agent/agent-commission/list.vue +++ b/apps/web-antd/src/views/agent/agent-commission/list.vue @@ -1,15 +1,24 @@ diff --git a/apps/web-antd/src/views/agent/agent-config/list.vue b/apps/web-antd/src/views/agent/agent-config/list.vue index 03c25e2..6987f4c 100644 --- a/apps/web-antd/src/views/agent/agent-config/list.vue +++ b/apps/web-antd/src/views/agent/agent-config/list.vue @@ -1,18 +1,31 @@ + + + + diff --git a/apps/web-antd/src/views/agent/agent-invite-code/data.ts b/apps/web-antd/src/views/agent/agent-invite-code/data.ts index 3e4f523..068671d 100644 --- a/apps/web-antd/src/views/agent/agent-invite-code/data.ts +++ b/apps/web-antd/src/views/agent/agent-invite-code/data.ts @@ -3,22 +3,31 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import { getLevelName } from '#/utils/agent'; -export function useInviteCodeColumns(): VxeTableGridOptions['columns'] { +export type InviteCodeRow = Record & { + agent_code?: number; + used_agent_code?: number; +}; + +export function useInviteCodeColumns( + onIssuerAgentCodeClick?: (row: InviteCodeRow) => void, + onUsedAgentCodeClick?: (row: InviteCodeRow) => void, +): VxeTableGridOptions['columns'] { return [ - { - field: 'id', - title: 'ID', - width: 80, - }, { field: 'code', title: '邀请码', width: 200, }, { - field: 'agent_id', - title: '发放代理ID', + field: 'agent_code', + title: '发放代理编号', width: 120, + cellRender: onIssuerAgentCodeClick + ? { + name: 'CellLink', + props: { onClick: onIssuerAgentCodeClick }, + } + : undefined, }, { field: 'agent_mobile', @@ -52,9 +61,15 @@ export function useInviteCodeColumns(): VxeTableGridOptions['columns'] { width: 120, }, { - field: 'used_agent_id', - title: '使用代理ID', + field: 'used_agent_code', + title: '使用代理编号', width: 120, + cellRender: onUsedAgentCodeClick + ? { + name: 'CellLink', + props: { onClick: onUsedAgentCodeClick }, + } + : undefined, }, { field: 'used_time', @@ -77,7 +92,7 @@ export function useInviteCodeColumns(): VxeTableGridOptions['columns'] { width: 160, sortable: true, }, - ] as const; + ]; } export function useInviteCodeFormSchema(): VbenFormSchema[] { @@ -86,11 +101,10 @@ export function useInviteCodeFormSchema(): VbenFormSchema[] { component: 'Input', fieldName: 'code', label: '邀请码', - }, - { - component: 'InputNumber', - fieldName: 'agent_id', - label: '发放代理ID', + componentProps: { + placeholder: '', + allowClear: true, + }, }, { component: 'Select', diff --git a/apps/web-antd/src/views/agent/agent-invite-code/list.vue b/apps/web-antd/src/views/agent/agent-invite-code/list.vue index 758285c..a4142c1 100644 --- a/apps/web-antd/src/views/agent/agent-invite-code/list.vue +++ b/apps/web-antd/src/views/agent/agent-invite-code/list.vue @@ -1,19 +1,23 @@