import Mock from 'mockjs' const getIdNumber = (id) => Number(String(id || '').replace(/\D/g, '')) || 0 const sortByIdDesc = (list) => [...list].sort((a, b) => getIdNumber(b.id) - getIdNumber(a.id)) // ============================================= // 登录 // ============================================= Mock.mock(/\/api\/login/, 'post', (options) => { const { username, password } = JSON.parse(options.body || '{}') if (!username || !password) { return { code: 400, data: null, msg: '账号或密码不能为空' } } if (username === 'admin' && password === '123456') { return { code: 200, data: { token: 'mock-token-' + Date.now(), username }, msg: '登录成功' } } return { code: 401, data: null, msg: '账号或密码错误' } }) // ============================================= // 页面管理 - 权益介绍页配置 // ============================================= const homeConfigData = { premier: { tabName: '卓越理财', privilegeImageEnabled: false, buttons: { unlocked: '进入权益专区', locked: '待解锁' }, header: { imageUrl: 'https://images.unsplash.com/photo-1518893494013-481c1d8ed3fd?w=800', mainTitle: '卓越理财', subTitle: '为您和您的家人提供尊崇专属礼遇和权益' }, privileges: [ { imageUrl: '', title: '国际教育', desc: '享专属国际化学校优惠及背景提升项目' }, { imageUrl: '', title: '酒店礼遇', desc: '高端酒店及商场会籍匹配' } ] }, elite: { tabName: '卓越理财·尊尚', privilegeImageEnabled: false, buttons: { unlocked: '进入权益专区', locked: '待解锁' }, header: { imageUrl: 'https://images.unsplash.com/photo-1518893494013-481c1d8ed3fd?w=800', mainTitle: '卓越理财·尊尚', subTitle: '为您和您的家人提供尊崇专属礼遇和权益' }, privileges: [ { imageUrl: '', title: '国际教育', desc: '享专属国际化学校优惠及背景提升项目' }, { imageUrl: '', title: '酒店礼遇', desc: '高端酒店及商场会籍匹配' } ] }, global: { tabName: '环球私人银行', privilegeImageEnabled: false, buttons: { unlocked: '进入权益专区', locked: '待解锁' }, header: { imageUrl: 'https://images.unsplash.com/photo-1518893494013-481c1d8ed3fd?w=800', mainTitle: '环球私人银行', subTitle: '为您和您的家人提供尊崇专属礼遇和权益' }, privileges: [ { imageUrl: '', title: '国际教育', desc: '享专属国际化学校优惠及背景提升项目' }, { imageUrl: '', title: '酒店礼遇', desc: '高端酒店及商场会籍匹配' } ] } } let homeStatus = 'published' Mock.mock(/\/api\/page-config\/home/, 'get', () => { return { code: 200, data: { config: homeConfigData, status: homeStatus }, msg: 'ok' } }) Mock.mock(/\/api\/page-config\/home/, 'put', (options) => { const body = JSON.parse(options.body) Object.assign(homeConfigData, body.config || {}) homeStatus = body.status || homeStatus return { code: 200, data: null, msg: '保存成功' } }) // ============================================= // 页面管理 - 权益首页配置 // ============================================= const zoneConfigData = { identityModule: { advance: { bgImage: 'https://images.unsplash.com/photo-1486406146926-c627a92ad1ab?w=800', showAvgBalance: true, avgBalanceName: '账户月内日均余额', avgBalanceRule: '

1.指从当月第一天起到截止日期为止,同一客户号码下所有账户月内日均总余额。

2. 计算公式=当月第一天到截止日期的累计账户总余额当月已过的自然天数。

' }, premier: { bgImage: 'https://images.unsplash.com/photo-1583847268964-b28dc8f51f92?w=800', showAvgBalance: true, avgBalanceName: '账户月内日均余额', identityTipContent: '

卓越理财客户身份由客户 MSC Group 自动匹配展示。

', avgBalanceRule: '

1.指从当月第一天起到截止日期为止,同一客户号码下所有账户月内日均总余额。

2. 计算公式=当月第一天到截止日期的累计账户总余额当月已过的自然天数。

' }, premierElite: { bgImage: 'https://images.unsplash.com/photo-1557682250-33bd709cbe85?w=800', showAvgBalance: true, avgBalanceName: '账户月内日均余额', identityTipContent: '

卓越理财·尊尚客户身份由客户 MSC Group 自动匹配展示。

', avgBalanceRule: '

1.指从当月第一天起到截止日期为止,同一客户号码下所有账户月内日均总余额。

2. 计算公式=当月第一天到截止日期的累计账户总余额当月已过的自然天数。

' }, privateBank: { bgImage: 'https://images.unsplash.com/photo-1492684223066-81342ee5ff30?w=800', identityTipContent: '

环球私人银行客户身份由客户 MSC Group 自动匹配展示。

' } }, adCarousel: [{ imageUrl: 'https://images.unsplash.com/photo-1556742049-0cfed4f6a45d?w=800', linkH5: '', linkApp: '', wechatAppId: '', wechatPath: '', title: '汇丰卓越理财新户达标礼', subtitle: '报名参加汇丰活动,体验更多精彩礼遇', tags: ['t1', 't2'] }], exchangeConfig: { items: [ { imageUrl: 'https://images.unsplash.com/photo-1436491865332-7a61a109cc05?w=200', title: '航空里程', link: 'https://test.hsbc.com' }, { imageUrl: 'https://images.unsplash.com/photo-1518893494013-481c1d8ed3fd?w=200', title: '贵宾厅', link: 'https://test.hsbc.com' } ] }, ruleModal: { title: '积分规则', content: '

本积分使用规则为汇丰银行(中国)有限公司...

' } } let zoneStatus = 'published' const availableTags = Array.from({ length: 8 }, (_, i) => ({ id: `t${i + 1}`, name: `人群标签${i + 1}` })) Mock.mock(/\/api\/page-config\/zone/, 'get', () => { return { code: 200, data: { config: zoneConfigData, status: zoneStatus, availableTags }, msg: 'ok' } }) Mock.mock(/\/api\/page-config\/zone/, 'put', (options) => { const body = JSON.parse(options.body) Object.assign(zoneConfigData, body.config || {}) zoneStatus = body.status || zoneStatus return { code: 200, data: null, msg: '保存成功' } }) // ============================================= // 页面管理 - 组装页 // ============================================= let assemblyIdCounter = 2 const assemblyList = [ { id: '1', name: '双十一迎新专属活动页', status: 'published', createTime: '2025-10-01 10:00:00', updateTime: '2025-10-15 14:30:00', shareConfig: { enabled: true, thumbnail: '', title: '', desc: '' }, blocks: [ { type: 'image', id: 'b_init1', data: { imageUrl: 'https://images.unsplash.com/photo-1557683316-973673baf926?w=800' } }, { type: 'privilege', id: 'b_init2', data: { title: '专属权益', items: [{ id: '1', title: '机场贵宾厅服务', desc: '全年免费使用6次指定机场贵宾厅' }, { id: '2', title: '境内礼宾车', desc: '免费2次接送' }] } }, { type: 'richtext', id: 'b_init3', data: { content: '

欢迎参与双十一专属福利活动...

' } }, { type: 'buttonGroup', id: 'b_init4', data: { buttons: [{ text: '立即参与', link: '/join', style: 'primary', actionType: 'link', dialog: { title: '', desc: '', confirmText: '确认', confirmLink: '' } }] } } ] }, { id: '2', name: '私行高净值沙龙引导页', status: 'draft', createTime: '2025-11-20 09:15:00', updateTime: '2025-11-20 09:15:00', shareConfig: { enabled: true, thumbnail: '', title: '', desc: '' }, blocks: [ { type: 'image', id: 'b_init5', data: { imageUrl: 'https://images.unsplash.com/photo-1486406146926-c627a92ad1ab?w=800' } }, { type: 'privilege', id: 'b_init6', data: { title: '尊享体验', items: [{ id: '1', title: '高尔夫权益', desc: 'VIP高尔夫俱乐部免会籍预约' }] } } ] } ] Mock.mock(/\/api\/assembly\/list/, 'get', (options) => { const url = new URL(options.url, 'http://localhost') const id = url.searchParams.get('id') || '' const name = url.searchParams.get('name') || '' let filtered = assemblyList if (id) filtered = filtered.filter(a => a.id.includes(id)) if (name) filtered = filtered.filter(a => a.name.includes(name)) return { code: 200, data: sortByIdDesc(filtered), msg: 'ok' } }) Mock.mock(/\/api\/assembly\/detail/, 'get', (options) => { const url = new URL(options.url, 'http://localhost') const id = url.searchParams.get('id') const item = assemblyList.find(a => a.id === id) return item ? { code: 200, data: item, msg: 'ok' } : { code: 404, data: null, msg: '未找到' } }) Mock.mock(/\/api\/assembly\/save/, 'post', (options) => { const body = JSON.parse(options.body) const now = new Date().toLocaleString('zh-CN', { hour12: false }) if (body.id) { const idx = assemblyList.findIndex(a => a.id === body.id) if (idx >= 0) { assemblyList[idx] = { ...assemblyList[idx], ...body, updateTime: now } } } else { body.id = String(++assemblyIdCounter) body.createTime = now body.updateTime = now assemblyList.unshift(body) } return { code: 200, data: { id: body.id }, msg: '保存成功' } }) Mock.mock(/\/api\/assembly\/delete/, 'post', (options) => { const body = JSON.parse(options.body) const idx = assemblyList.findIndex(a => a.id === body.id) if (idx >= 0) assemblyList.splice(idx, 1) return { code: 200, data: null, msg: '删除成功' } }) // ============================================= // 渠道管理 - Channel // ============================================= const channelDict = { 'Human-assisted': { '汇丰中国客户服务号': ['汇丰中国客户服务号'], 'MGM': ['MGM - Mortgage', 'MGM - Premier'], 'CCSS': ['CCSS SMS'], 'Referral': ['GPB Referral', 'HK referral', 'Non WPB staff Referral', 'Pinnacle Referral', 'RBB Refferal'], 'New staff': ['New staff'], 'IBC': ['IBC referral staff code'], 'Group Acct': ['HTC', 'NIVIDA'] }, 'Unassisted': { '汇丰中国APP': ['Mobile X'], '汇丰中国官网': ['PWS site'], '汇丰中国小程序': ['汇丰中国小程序'], '汇丰中国订阅号': ['汇丰中国订阅号', '汇丰中国订阅号推文', '推文尾部入口'], 'Chatbot': ['Chatbot'], 'SMS': ['SMS'], 'Paid Media': ['汇丰中国订阅号推文', 'others'], 'Others': ['others', 'River APP'] } } let channelIdCounter = 9 const channelRows = [ { id: 'CH0001', type: 'Human-assisted', category: '汇丰中国客户服务号', name: '汇丰中国客户服务号', subName: '', owner: '', createTime: '2025-11-20 09:15:00', updateTime: '2025-11-20 09:15:00' }, { id: 'CH0002', type: 'Human-assisted', category: 'MGM', name: 'MGM - Mortgage', subName: '', owner: '', createTime: '2025-11-20 09:15:00', updateTime: '2025-11-20 09:15:00' }, { id: 'CH0003', type: 'Human-assisted', category: 'MGM', name: 'MGM - Premier', subName: '双十一特惠', owner: '张经理', createTime: '2025-11-20 09:15:00', updateTime: '2025-11-21 14:30:00' }, { id: 'CH0004', type: 'Human-assisted', category: 'CCSS', name: 'CCSS SMS', subName: '', owner: '', createTime: '2025-11-20 09:15:00', updateTime: '2025-11-20 09:15:00' }, { id: 'CH0005', type: 'Human-assisted', category: 'Referral', name: 'GPB Referral', subName: '', owner: '', createTime: '2025-11-20 09:15:00', updateTime: '2025-11-20 09:15:00' }, { id: 'CH0006', type: 'Unassisted', category: '汇丰中国APP', name: 'Mobile X', subName: '', owner: '', createTime: '2025-11-20 09:15:00', updateTime: '2025-11-20 09:15:00' }, { id: 'CH0007', type: 'Unassisted', category: '汇丰中国官网', name: 'PWS site', subName: '私行沙龙引导', owner: '', createTime: '2025-11-20 09:15:00', updateTime: '2025-11-20 09:15:00' }, { id: 'CH0008', type: 'Unassisted', category: '汇丰中国订阅号', name: '汇丰中国订阅号', subName: '', owner: '', createTime: '2025-11-20 09:15:00', updateTime: '2025-11-20 09:15:00' }, { id: 'CH0009', type: 'Unassisted', category: '汇丰中国订阅号', name: '推文尾部入口', subName: '', owner: '', createTime: '2025-11-20 09:15:00', updateTime: '2025-11-20 09:15:00' } ] Mock.mock(/\/api\/channel\/dict/, 'get', () => { return { code: 200, data: channelDict, msg: 'ok' } }) Mock.mock(/\/api\/channel\/dict\/save/, 'post', (options) => { const body = JSON.parse(options.body) const { target, type, category, oldValue, newValue, mode } = body if (target === 'type') { if (mode === 'add' && channelDict[newValue]) return { code: 400, data: null, msg: 'Channel 类型已存在,不能重复新增' } if (mode === 'edit' && oldValue !== newValue && channelDict[newValue]) return { code: 400, data: null, msg: 'Channel 类型已存在,不能修改为重复值' } if (mode === 'add') { channelDict[newValue] = {} } else { channelDict[newValue] = channelDict[oldValue]; delete channelDict[oldValue]; channelRows.forEach(r => { if (r.type === oldValue) r.type = newValue }) } } else if (target === 'category') { if (mode === 'add' && channelDict[type][newValue]) return { code: 400, data: null, msg: 'Channel 类别已存在,不能重复新增' } if (mode === 'edit' && oldValue !== newValue && channelDict[type][newValue]) return { code: 400, data: null, msg: 'Channel 类别已存在,不能修改为重复值' } if (mode === 'add') { channelDict[type][newValue] = [] } else { channelDict[type][newValue] = channelDict[type][oldValue]; delete channelDict[type][oldValue]; channelRows.forEach(r => { if (r.type === type && r.category === oldValue) r.category = newValue }) } } else if (target === 'name') { const list = channelDict[type][category] if (mode === 'add' && list.includes(newValue)) return { code: 400, data: null, msg: 'Channel 名称已存在,不能重复新增' } if (mode === 'edit' && oldValue !== newValue && list.includes(newValue)) return { code: 400, data: null, msg: 'Channel 名称已存在,不能修改为重复值' } if (mode === 'add') { list.push(newValue) } else { const idx = list.indexOf(oldValue); if (idx >= 0) list[idx] = newValue; channelRows.forEach(r => { if (r.type === type && r.category === category && r.name === oldValue) r.name = newValue }) } } return { code: 200, data: channelDict, msg: '保存成功' } }) Mock.mock(/\/api\/channel\/list/, 'get', (options) => { const url = new URL(options.url, 'http://localhost') const sId = (url.searchParams.get('id') || '').toLowerCase() const sType = url.searchParams.get('type') || '' const sCategory = (url.searchParams.get('category') || '').toLowerCase() const sName = (url.searchParams.get('name') || '').toLowerCase() const sSubName = (url.searchParams.get('subName') || '').toLowerCase() const sOwner = (url.searchParams.get('owner') || '').toLowerCase() let filtered = channelRows if (sId) filtered = filtered.filter(c => c.id.toLowerCase().includes(sId)) if (sType) filtered = filtered.filter(c => c.type === sType) if (sCategory) filtered = filtered.filter(c => c.category.toLowerCase().includes(sCategory)) if (sName) filtered = filtered.filter(c => c.name.toLowerCase().includes(sName)) if (sSubName) filtered = filtered.filter(c => c.subName.toLowerCase().includes(sSubName)) if (sOwner) filtered = filtered.filter(c => c.owner.toLowerCase().includes(sOwner)) return { code: 200, data: filtered, msg: 'ok' } }) Mock.mock(/\/api\/channel\/save/, 'post', (options) => { const body = JSON.parse(options.body) const now = new Date().toLocaleString('zh-CN', { hour12: false }) if (body.id) { const idx = channelRows.findIndex(c => c.id === body.id) if (idx >= 0) channelRows[idx] = { ...channelRows[idx], ...body, updateTime: now } } else { body.id = 'CH' + String(++channelIdCounter).padStart(4, '0') body.createTime = now body.updateTime = now channelRows.unshift(body) } return { code: 200, data: { id: body.id }, msg: '保存成功' } }) Mock.mock(/\/api\/channel\/delete/, 'post', (options) => { const body = JSON.parse(options.body) const idx = channelRows.findIndex(c => c.id === body.id) if (idx >= 0) channelRows.splice(idx, 1) return { code: 200, data: null, msg: '删除成功' } }) // ============================================= // 渠道管理 - Campaign // ============================================= let campaignIdCounter = 9002 const campaignRows = [ { id: 'CP9001', name: 'Q3 大客户回馈', owner: 'Market Team', staff: '王专员', createTime: '2025-10-01 10:00:00', updateTime: '2025-10-15 14:30:00' }, { id: 'CP9002', name: '新春开户活动', owner: 'Retail Team', staff: '李专员', createTime: '2025-11-20 09:15:00', updateTime: '2025-11-20 09:15:00' } ] Mock.mock(/\/api\/campaign\/list/, 'get', (options) => { const url = new URL(options.url, 'http://localhost') const sId = (url.searchParams.get('id') || '').toLowerCase() const sName = (url.searchParams.get('name') || '').toLowerCase() const sOwner = (url.searchParams.get('owner') || '').toLowerCase() const sStaff = (url.searchParams.get('staff') || '').toLowerCase() let filtered = campaignRows if (sId) filtered = filtered.filter(c => c.id.toLowerCase().includes(sId)) if (sName) filtered = filtered.filter(c => c.name.toLowerCase().includes(sName)) if (sOwner) filtered = filtered.filter(c => c.owner.toLowerCase().includes(sOwner)) if (sStaff) filtered = filtered.filter(c => c.staff.toLowerCase().includes(sStaff)) return { code: 200, data: filtered, msg: 'ok' } }) Mock.mock(/\/api\/campaign\/save/, 'post', (options) => { const body = JSON.parse(options.body) const now = new Date().toLocaleString('zh-CN', { hour12: false }) if (body.id) { const idx = campaignRows.findIndex(c => c.id === body.id) if (idx >= 0) campaignRows[idx] = { ...campaignRows[idx], ...body, updateTime: now } } else { body.id = 'CP' + (++campaignIdCounter) body.createTime = now body.updateTime = now campaignRows.unshift(body) } return { code: 200, data: { id: body.id }, msg: '保存成功' } }) Mock.mock(/\/api\/campaign\/delete/, 'post', (options) => { const body = JSON.parse(options.body) const idx = campaignRows.findIndex(c => c.id === body.id) if (idx >= 0) campaignRows.splice(idx, 1) return { code: 200, data: null, msg: '删除成功' } }) // ============================================= // 借记卡权益 + 审核中心 // ============================================= // 商品状态:未上架 / 已上架 // 审核状态:草稿 / 上架待审核 / 下架待审核 / 审核通过 // 合法组合(5 种): // 未上架+草稿 = 草稿 // 未上架+上架待审核 = 新增待审核 // 未上架+审核通过 = 已下架 // 已上架+审核通过 = 已上架 // 已上架+下架待审核 = 已上架·下架待审核 const equityList = [ { productId: 'Q100001', equityName: '权益A', source: '银行自有', isPlatformExchange: '是', jumpMethod: '-', jumpLink: '-', exchangeMethod: '权益平台', productType: '券码', skuNo: 'C0000001000000101', stockCount: 5000, merchantName: '商户A', creator: '李运营', createTime: '2026-04-10 09:32:15', reviewer: '王五', reviewTime: '2026-04-15 10:30:00', shelfStatus: '已上架', auditStatus: '审核通过', showOnHome: '显示', showOnAssembly: '不显示', assemblyPages: [] }, { productId: 'Q100002', equityName: '权益B', source: '第三方', isPlatformExchange: '否', jumpMethod: '没有', jumpLink: '太古地产', exchangeMethod: '第三方(列表跳转)', productType: '', skuNo: '', merchantName: '商户B', creator: '王运营', createTime: '2026-04-12 14:08:42', reviewer: '', reviewTime: '', shelfStatus: '未上架', auditStatus: '上架待审核', showOnHome: '显示', showOnAssembly: '不显示', assemblyPages: [] }, { productId: 'Q100003', equityName: '权益C', source: '第三方', isPlatformExchange: '否', jumpMethod: '有', jumpLink: '龙腾', exchangeMethod: '第三方(详情页跳转)', productType: '', skuNo: '', merchantName: '商户C', creator: '李运营', createTime: '2026-04-08 11:20:05', reviewer: '王五', reviewTime: '2026-04-14 16:45:00', shelfStatus: '已上架', auditStatus: '审核通过', showOnHome: '显示', showOnAssembly: '不显示', assemblyPages: [] }, { productId: 'Q100004', equityName: '权益D', source: '第三方', isPlatformExchange: '否', jumpMethod: '有', jumpLink: 'h5链接', exchangeMethod: '第三方(详情页跳转)', productType: '', skuNo: '', merchantName: '商户D', creator: '陈运营', createTime: '2026-04-05 15:50:18', reviewer: '赵六', reviewTime: '2026-04-13 09:15:00', shelfStatus: '已上架', auditStatus: '下架待审核', showOnHome: '显示', showOnAssembly: '不显示', assemblyPages: [] }, { productId: 'Q100005', equityName: '权益E', source: '银行自有', isPlatformExchange: '是', jumpMethod: '-', jumpLink: '-', exchangeMethod: '权益平台', productType: '券码', skuNo: 'C0000001000000501', stockCount: 3000, merchantName: '商户E', creator: '王运营', createTime: '2026-03-28 09:00:11', reviewer: '钱七', reviewTime: '2026-04-12 11:20:00', shelfStatus: '未上架', auditStatus: '审核通过', showOnHome: '显示', showOnAssembly: '不显示', assemblyPages: [] }, { productId: 'Q100006', equityName: '权益F(草稿)', source: '银行自有', isPlatformExchange: '是', jumpMethod: '-', jumpLink: '-', exchangeMethod: '权益平台', productType: '券码', skuNo: 'C0000001000000601', stockCount: 1000, merchantName: '商户F', creator: '李运营', createTime: '2026-05-16 10:00:00', reviewer: '', reviewTime: '', shelfStatus: '未上架', auditStatus: '草稿', showOnHome: '不显示', showOnAssembly: '不显示', assemblyPages: [] }, { productId: 'Q100007', equityName: '微信立减金 5元(满10减5)', source: '荣数商品', isPlatformExchange: '是', jumpMethod: '-', jumpLink: '-', exchangeMethod: '权益平台', productType: '微信立减金', skuNo: 'V0000003900000801', rongshuProduct: '微信立减金 5元(满10减5)', merchantName: '微信支付', stockCount: 2000, creator: '张三', createTime: '2026-05-20 10:00:00', reviewer: '李四', reviewTime: '2026-05-22 15:30:00', shelfStatus: '已上架', auditStatus: '审核通过', showOnHome: '显示', showOnAssembly: '不显示', assemblyPages: [] }, { productId: 'Q100008', equityName: '微信立减金 50元(满200减50)', source: '荣数商品', isPlatformExchange: '是', jumpMethod: '-', jumpLink: '-', exchangeMethod: '权益平台', productType: '微信立减金', skuNo: 'V0000003900000807', rongshuProduct: '微信立减金 50元(满200减50)', merchantName: '微信支付', stockCount: 400, creator: '张三', createTime: '2026-05-18 09:30:00', reviewer: '', reviewTime: '', shelfStatus: '未上架', auditStatus: '上架待审核', showOnHome: '显示', showOnAssembly: '显示', assemblyPages: ['组装页1'] } ] let equityIdCounter = 100008 const auditList = [ { id: 'AR202605150001', auditType: 'new', bizModule: 'equity_product', bizModuleName: '借记卡权益', bizId: 'Q100002', bizName: '权益B', snapshot: { equityName: '权益B', source: '第三方', isPlatformExchange: '否', jumpMethod: '没有', jumpLink: '太古地产', productType: '', skuNo: '', merchantName: '商户B', subTitle: '外部列表页副标题' }, submitReason: '新建第三方权益,链接已对齐', submitterId: 'u001', submitterName: '王运营', submitTime: '2026-05-15 10:00:00', auditorId: null, auditorName: '', auditTime: '', auditStatus: 'pending', auditComment: '' }, { id: 'AR202605170001', auditType: 'offshelf', bizModule: 'equity_product', bizModuleName: '借记卡权益', bizId: 'Q100004', bizName: '权益D', snapshot: { equityName: '权益D', source: '第三方', isPlatformExchange: '否', jumpMethod: '有', jumpLink: 'h5链接', productType: '', skuNo: '', merchantName: '商户D', subTitle: '外部自定义链接副标题' }, submitReason: '业务合作到期,申请下架', submitterId: 'u003', submitterName: '陈运营', submitTime: '2026-05-17 09:00:00', auditorId: null, auditorName: '', auditTime: '', auditStatus: 'pending', auditComment: '' }, { id: 'AR202605120001', auditType: 'new', bizModule: 'equity_product', bizModuleName: '借记卡权益', bizId: 'Q100001', bizName: '权益A', snapshot: { equityName: '权益A', source: '银行自有', isPlatformExchange: '是', jumpMethod: '-', jumpLink: '-', productType: '券码', skuNo: 'C0000001000000101', stockCount: 5000, merchantName: '商户A', subTitle: '副标题示例' }, submitReason: '', submitterId: 'u001', submitterName: '李运营', submitTime: '2026-04-10 09:32:15', auditorId: 'u099', auditorName: '王五', auditTime: '2026-04-15 10:30:00', auditStatus: 'approved', auditComment: '内容合规,准予上架' } ] let auditIdCounter = 4 function nowStr() { return new Date().toLocaleString('zh-CN', { hour12: false }).replace(/\//g, '-') } function nextAuditId() { auditIdCounter += 1 const d = new Date() const ymd = d.getFullYear().toString() + String(d.getMonth() + 1).padStart(2, '0') + String(d.getDate()).padStart(2, '0') return 'AR' + ymd + String(auditIdCounter).padStart(4, '0') } function snapshotOf(equity, couponBatchId) { return { equityName: equity.equityName, source: equity.source, isPlatformExchange: equity.isPlatformExchange || (equity.source === '第三方' ? '否' : '是'), productType: equity.isPlatformExchange === '否' ? '' : (equity.productType || '券码'), jumpMethod: equity.jumpMethod, jumpLink: equity.jumpLink, skuNo: equity.skuNo, merchantName: equity.merchantName, subTitle: equity.subTitle || '', couponBatchId: couponBatchId !== undefined ? (couponBatchId || '') : (equity.couponBatchId || '') } } // 借记卡权益 - 列表 Mock.mock(/\/api\/equity\/list/, 'get', (options) => { const url = new URL(options.url, 'http://localhost') const equityName = url.searchParams.get('equityName') || '' const productId = url.searchParams.get('productId') || '' const shelfStatus = url.searchParams.get('shelfStatus') || '' const auditStatus = url.searchParams.get('auditStatus') || '' let filtered = equityList if (equityName) filtered = filtered.filter(e => e.equityName.includes(equityName)) if (productId) filtered = filtered.filter(e => e.productId.includes(productId)) if (shelfStatus) filtered = filtered.filter(e => e.shelfStatus === shelfStatus) if (auditStatus) filtered = filtered.filter(e => e.auditStatus === auditStatus) return { code: 200, data: filtered, msg: 'ok' } }) // 借记卡权益 - 详情 Mock.mock(/\/api\/equity\/detail/, 'get', (options) => { const url = new URL(options.url, 'http://localhost') const id = url.searchParams.get('id') const item = equityList.find(e => e.productId === id) return item ? { code: 200, data: item, msg: 'ok' } : { code: 404, data: null, msg: '权益不存在' } }) // 保存草稿(新建或修改草稿) Mock.mock(/\/api\/equity\/save-draft/, 'post', (options) => { const body = JSON.parse(options.body) if (body.productId) { // 修改草稿 const idx = equityList.findIndex(e => e.productId === body.productId) if (idx < 0) return { code: 404, data: null, msg: '权益不存在' } const cur = equityList[idx] if (cur.auditStatus !== '草稿') { return { code: 400, data: null, msg: '仅草稿状态可保存为草稿' } } equityList[idx] = { ...cur, ...body, shelfStatus: '未上架', auditStatus: '草稿' } return { code: 200, data: { productId: cur.productId }, msg: '草稿已保存' } } // 新建草稿 equityIdCounter += 1 const newId = 'Q' + String(equityIdCounter) const newRow = { productId: newId, equityName: body.equityName || '未命名权益', source: body.source || '银行自有', isPlatformExchange: body.isPlatformExchange || '是', jumpMethod: body.jumpMethod || '-', jumpLink: body.jumpLink || '-', exchangeMethod: body.exchangeMethod || '权益平台', productType: body.isPlatformExchange === '否' ? '' : (body.productType || '券码'), skuNo: body.skuNo || '', rongshuProduct: body.rongshuProduct || '', stockCount: body.stockCount ?? null, merchantName: body.merchantName || '', creator: body.creator || '李运营', createTime: nowStr(), reviewer: '', reviewTime: '', shelfStatus: '未上架', auditStatus: '草稿', showOnHome: body.showOnHome || '不显示', showOnAssembly: body.showOnAssembly || '不显示', assemblyPages: body.assemblyPages || [], subTitle: body.subTitle || '', couponBatchId: body.couponBatchId || '' } equityList.unshift(newRow) return { code: 200, data: { productId: newId }, msg: '草稿已保存' } }) // 提交审核(新增上架审核 / 已上架编辑提审 / 已下架重新提审) Mock.mock(/\/api\/equity\/submit/, 'post', (options) => { const body = JSON.parse(options.body) let cur let idx = -1 if (body.productId) { idx = equityList.findIndex(e => e.productId === body.productId) if (idx < 0) return { code: 404, data: null, msg: '权益不存在' } cur = equityList[idx] } const submitReason = body.submitReason || '' const submitter = body.submitterName || '李运营' // 新建 + 直接提审 if (!cur) { equityIdCounter += 1 const newId = 'Q' + String(equityIdCounter) const newRow = { productId: newId, equityName: body.equityName || '未命名权益', source: body.source || '银行自有', isPlatformExchange: body.isPlatformExchange || '是', jumpMethod: body.jumpMethod || '-', jumpLink: body.jumpLink || '-', exchangeMethod: body.exchangeMethod || '权益平台', productType: body.isPlatformExchange === '否' ? '' : (body.productType || '券码'), skuNo: body.skuNo || '', rongshuProduct: body.rongshuProduct || '', stockCount: body.stockCount ?? null, merchantName: body.merchantName || '', creator: submitter, createTime: nowStr(), reviewer: '', reviewTime: '', shelfStatus: '未上架', auditStatus: '上架待审核', showOnHome: body.showOnHome || '不显示', showOnAssembly: body.showOnAssembly || '不显示', assemblyPages: body.assemblyPages || [], subTitle: body.subTitle || '', couponBatchId: body.couponBatchId || '' } equityList.unshift(newRow) auditList.unshift({ id: nextAuditId(), auditType: 'new', bizModule: 'equity_product', bizModuleName: '借记卡权益', bizId: newId, bizName: newRow.equityName, snapshot: snapshotOf(newRow), submitReason, submitterId: 'u001', submitterName: submitter, submitTime: nowStr(), auditorId: null, auditorName: '', auditTime: '', auditStatus: 'pending', auditComment: '' }) return { code: 200, data: { productId: newId }, msg: '已提交审核' } } // 草稿 → 上架待审核(new) if (cur.shelfStatus === '未上架' && cur.auditStatus === '草稿') { const merged = { ...cur, ...body } equityList[idx] = { ...merged, shelfStatus: '未上架', auditStatus: '上架待审核' } auditList.unshift({ id: nextAuditId(), auditType: 'new', bizModule: 'equity_product', bizModuleName: '借记卡权益', bizId: cur.productId, bizName: equityList[idx].equityName, snapshot: snapshotOf(equityList[idx]), submitReason, submitterId: 'u001', submitterName: submitter, submitTime: nowStr(), auditorId: null, auditorName: '', auditTime: '', auditStatus: 'pending', auditComment: '' }) return { code: 200, data: { productId: cur.productId }, msg: '已提交审核' } } // 已下架 → 重新上架(也是 new) if (cur.shelfStatus === '未上架' && cur.auditStatus === '审核通过') { equityList[idx] = { ...cur, ...body, shelfStatus: '未上架', auditStatus: '上架待审核' } auditList.unshift({ id: nextAuditId(), auditType: 'new', bizModule: 'equity_product', bizModuleName: '借记卡权益', bizId: cur.productId, bizName: equityList[idx].equityName, snapshot: snapshotOf(equityList[idx]), submitReason, submitterId: 'u001', submitterName: submitter, submitTime: nowStr(), auditorId: null, auditorName: '', auditTime: '', auditStatus: 'pending', auditComment: '' }) return { code: 200, data: { productId: cur.productId }, msg: '已提交审核' } } // 已上架商品禁止直接编辑(需先走下架审核) return { code: 400, data: null, msg: '当前状态不可提交审核' } }) // 申请下架 Mock.mock(/\/api\/equity\/request-offshelf/, 'post', (options) => { const body = JSON.parse(options.body) const idx = equityList.findIndex(e => e.productId === body.productId) if (idx < 0) return { code: 404, data: null, msg: '权益不存在' } const cur = equityList[idx] if (cur.shelfStatus !== '已上架' || cur.auditStatus !== '审核通过') { return { code: 400, data: null, msg: '仅已上架且无审核中的权益可申请下架' } } equityList[idx] = { ...cur, auditStatus: '下架待审核' } auditList.unshift({ id: nextAuditId(), auditType: 'offshelf', bizModule: 'equity_product', bizModuleName: '借记卡权益', bizId: cur.productId, bizName: cur.equityName, snapshot: snapshotOf(cur), submitReason: '', submitterId: 'u001', submitterName: body.submitterName || '李运营', submitTime: nowStr(), auditorId: null, auditorName: '', auditTime: '', auditStatus: 'pending', auditComment: '' }) return { code: 200, data: null, msg: '已提交下架审核' } }) // 删除权益(仅草稿/已下架) Mock.mock(/\/api\/equity\/delete/, 'post', (options) => { const body = JSON.parse(options.body) const idx = equityList.findIndex(e => e.productId === body.productId) if (idx < 0) return { code: 404, data: null, msg: '权益不存在' } const cur = equityList[idx] const canDelete = (cur.shelfStatus === '未上架' && (cur.auditStatus === '草稿' || cur.auditStatus === '审核通过')) if (!canDelete) return { code: 400, data: null, msg: '当前状态不可删除' } equityList.splice(idx, 1) return { code: 200, data: null, msg: '删除成功' } }) // 审核中心 - 列表 Mock.mock(/\/api\/audit\/list/, 'get', (options) => { const url = new URL(options.url, 'http://localhost') const auditStatus = url.searchParams.get('auditStatus') || '' const bizName = url.searchParams.get('bizName') || '' const bizId = url.searchParams.get('bizId') || '' let filtered = auditList if (auditStatus) filtered = filtered.filter(a => a.auditStatus === auditStatus) if (bizName) filtered = filtered.filter(a => a.bizName.includes(bizName)) if (bizId) filtered = filtered.filter(a => String(a.bizId).includes(bizId)) return { code: 200, data: filtered, msg: 'ok' } }) // 审核中心 - 详情 Mock.mock(/\/api\/audit\/detail/, 'get', (options) => { const url = new URL(options.url, 'http://localhost') const id = url.searchParams.get('id') const item = auditList.find(a => a.id === id) return item ? { code: 200, data: item, msg: 'ok' } : { code: 404, data: null, msg: '审核单不存在' } }) // 审核中心 - 通过 Mock.mock(/\/api\/audit\/approve/, 'post', (options) => { const body = JSON.parse(options.body) const idx = auditList.findIndex(a => a.id === body.id) if (idx < 0) return { code: 404, data: null, msg: '审核单不存在' } const audit = auditList[idx] if (audit.auditStatus !== 'pending') return { code: 400, data: null, msg: '该审核单已完成' } const eqIdx = equityList.findIndex(e => e.productId === audit.bizId) if (eqIdx < 0) return { code: 404, data: null, msg: '关联权益不存在' } const eq = equityList[eqIdx] const now = nowStr() const auditor = body.auditorName || '王五' if (audit.auditType === 'new') { equityList[eqIdx] = { ...eq, shelfStatus: '已上架', auditStatus: '审核通过', reviewer: auditor, reviewTime: now } // 券码商品且关联了待导入批次:首次上架通过时模拟 SIP 导入、移入已导入列表 if (audit.snapshot && audit.snapshot.couponBatchId) { importPendingBatch(audit.snapshot.couponBatchId, eq.productId, eq.equityName) } } else if (audit.auditType === 'offshelf') { equityList[eqIdx] = { ...eq, shelfStatus: '未上架', auditStatus: '审核通过', reviewer: auditor, reviewTime: now } } auditList[idx] = { ...audit, auditStatus: 'approved', auditorId: 'u099', auditorName: auditor, auditTime: now, auditComment: body.comment || '' } return { code: 200, data: null, msg: '审核通过' } }) // 审核中心 - 驳回 Mock.mock(/\/api\/audit\/reject/, 'post', (options) => { const body = JSON.parse(options.body) const idx = auditList.findIndex(a => a.id === body.id) if (idx < 0) return { code: 404, data: null, msg: '审核单不存在' } const audit = auditList[idx] if (audit.auditStatus !== 'pending') return { code: 400, data: null, msg: '该审核单已完成' } const eqIdx = equityList.findIndex(e => e.productId === audit.bizId) if (eqIdx < 0) return { code: 404, data: null, msg: '关联权益不存在' } const eq = equityList[eqIdx] const now = nowStr() const auditor = body.auditorName || '王五' // 驳回后权益主表回退到提审前的状态 if (audit.auditType === 'new') { equityList[eqIdx] = { ...eq, shelfStatus: '未上架', auditStatus: '草稿' } } else if (audit.auditType === 'offshelf') { equityList[eqIdx] = { ...eq, shelfStatus: '已上架', auditStatus: '审核通过' } } auditList[idx] = { ...audit, auditStatus: 'rejected', auditorId: 'u099', auditorName: auditor, auditTime: now, auditComment: body.comment || '' } return { code: 200, data: null, msg: '已驳回' } }) // ============================================= // 发放计划 // ============================================= const equityGrantCampaignList = [ { id: 'P000002', name: '夏日畅享权益月', startTime: '2026-05-01 00:00:00', endTime: '2026-08-31 23:59:59', targetType: '潜客', prospectTypes: ['无客户号潜客', '标签潜客'], crowdList: [], isAutoGrant: '是', grantMode: 'claim', equityList: ['Q100001', 'Q100004', 'Q100005'], grantCycle: 'total', grantQuantity: 1, validity: { type: 'relative', fixedRange: [], relativeDays: 30 }, auditStatus: '审核通过', createTime: '2026-04-20 14:10:00', updateTime: '2026-04-20 14:10:00' }, { id: 'P000001', name: '春季会员尊享礼遇', startTime: '2026-04-01 00:00:00', endTime: '2026-06-30 23:59:59', targetType: '客群', prospectTypes: [], crowdList: ['00000120251224'], isAutoGrant: '否', grantMode: 'direct', equityList: ['Q100001'], grantCycle: 'monthly', grantQuantity: 2, validity: { type: 'fixed', fixedRange: ['2026-04-01', '2026-06-30'], relativeDays: 30 }, auditStatus: '新增待审核', createTime: '2026-03-25 10:20:30', updateTime: '2026-03-25 10:20:30' } ] let equityGrantCampaignCounter = equityGrantCampaignList.length function nextGrantCampaignId() { equityGrantCampaignCounter += 1 return 'P' + String(equityGrantCampaignCounter).padStart(6, '0') } Mock.mock(/\/api\/equity-grant-campaign\/list/, 'get', (options) => { const url = new URL(options.url, 'http://localhost') const name = url.searchParams.get('name') || '' const startDate = url.searchParams.get('startDate') || '' const endDate = url.searchParams.get('endDate') || '' let filtered = equityGrantCampaignList if (name) filtered = filtered.filter(c => c.name.includes(name)) if (startDate) filtered = filtered.filter(c => c.endTime.slice(0, 10) >= startDate) if (endDate) filtered = filtered.filter(c => c.startTime.slice(0, 10) <= endDate) return { code: 200, data: filtered, msg: 'ok' } }) Mock.mock(/\/api\/equity-grant-campaign\/save/, 'post', (options) => { const body = JSON.parse(options.body) const now = nowStr() const defaultValidity = { type: 'fixed', fixedRange: [], relativeDays: 30 } if (body.id) { const idx = equityGrantCampaignList.findIndex(c => c.id === body.id) if (idx < 0) return { code: 404, data: null, msg: '发放计划不存在' } equityGrantCampaignList[idx] = { ...equityGrantCampaignList[idx], name: body.name, startTime: body.startTime, endTime: body.endTime, targetType: body.targetType || '客群', prospectTypes: body.prospectTypes || [], crowdList: body.crowdList || [], isAutoGrant: body.isAutoGrant || '是', equityList: body.equityList || [], grantCycle: body.grantCycle || 'total', grantQuantity: body.grantQuantity || 1, validity: body.validity || defaultValidity, updateTime: now } return { code: 200, data: { id: body.id }, msg: '保存成功' } } const newId = nextGrantCampaignId() equityGrantCampaignList.unshift({ id: newId, name: body.name, startTime: body.startTime, endTime: body.endTime, targetType: body.targetType || '客群', prospectTypes: body.prospectTypes || [], crowdList: body.crowdList || [], isAutoGrant: body.isAutoGrant || '是', equityList: body.equityList || [], grantCycle: body.grantCycle || 'total', grantQuantity: body.grantQuantity || 1, validity: body.validity || defaultValidity, auditStatus: '新增待审核', createTime: now, updateTime: now }) return { code: 200, data: { id: newId }, msg: '新建成功' } }) Mock.mock(/\/api\/equity-grant-campaign\/delete/, 'post', (options) => { const body = JSON.parse(options.body) const idx = equityGrantCampaignList.findIndex(c => c.id === body.id) if (idx < 0) return { code: 404, data: null, msg: '发放计划不存在' } equityGrantCampaignList.splice(idx, 1) return { code: 200, data: null, msg: '删除成功' } }) // ============================================= // 发放任务 // ============================================= const grantTaskList = [ { taskId: 'T20260501001', planName: '夏日畅享权益月', planId: 'P000002', taskType: '自动', taskCycle: '2026-05-01 ~ 2026-05-31', status: '已完成', createTime: '2026-05-01 00:00:00', executeTime: '2026-05-01 00:05:12', executor: '系统' }, { taskId: 'T20260401001', planName: '春季会员尊享礼遇', planId: 'P000001', taskType: '手动', taskCycle: '2026-04-01 ~ 2026-04-30', status: '待执行', createTime: '2026-04-01 00:00:00', executeTime: '', executor: '' }, { taskId: 'T20260401002', planName: '春季会员尊享礼遇', planId: 'P000001', taskType: '手动', taskCycle: '2026-05-01 ~ 2026-05-31', status: '执行中', createTime: '2026-05-01 00:00:00', executeTime: '2026-05-01 10:30:00', executor: '张三' } ] Mock.mock(/\/api\/grant-task\/list/, 'get', (options) => { const url = new URL(options.url, 'http://localhost') const planName = url.searchParams.get('planName') || '' const status = url.searchParams.get('status') || '' let filtered = grantTaskList if (planName) filtered = filtered.filter(t => t.planName.includes(planName)) if (status) filtered = filtered.filter(t => t.status === status) return { code: 200, data: filtered, msg: 'ok' } }) Mock.mock(/\/api\/grant-task\/detail/, 'get', (options) => { const url = new URL(options.url, 'http://localhost') const taskId = url.searchParams.get('taskId') || '' const task = grantTaskList.find(t => t.taskId === taskId) if (!task) return { code: 404, data: null, msg: '任务不存在' } const plan = equityGrantCampaignList.find(c => c.id === task.planId) const cycleMap = { 'total': '整个周期', 'monthly': '每月', 'quarterly': '每季度', 'yearly': '每年' } const planData = { ...task, grantMode: plan ? plan.grantMode : 'claim', isAutoGrant: plan ? plan.isAutoGrant : '是', planStartTime: plan ? plan.startTime : '', planEndTime: plan ? plan.endTime : '', grantQuantityLabel: plan ? `${cycleMap[plan.grantCycle] || plan.grantCycle} ${plan.grantQuantity} 个` : '', validityLabel: plan ? (plan.validity.type === 'fixed' ? (plan.validity.fixedRange.join(' 至 ')) : `自发放起 ${plan.validity.relativeDays} 天内有效`) : '', crowdLabel: plan ? (plan.crowdList.length ? plan.crowdList.map(id => { const crowdNames = { '00000120251224': '层层礼圈选客群1' } return crowdNames[id] ? `${crowdNames[id]} (${id})` : id }).join('、') : '-') : '-', equityLabel: plan ? (plan.equityList.length ? plan.equityList.map(id => { const e = equityList.find(p => p.productId === id) return e ? `${e.equityName} (${id})` : id }).join('、') : '-') : '-', smsLabel: plan ? '发放成功通用模板' : '-' } return { code: 200, data: planData, msg: 'ok' } }) Mock.mock(/\/api\/grant-task\/execute/, 'post', (options) => { const body = JSON.parse(options.body) const idx = grantTaskList.findIndex(t => t.taskId === body.taskId) if (idx < 0) return { code: 404, data: null, msg: '任务不存在' } if (grantTaskList[idx].status !== '待执行') return { code: 400, data: null, msg: '该任务不在待执行状态' } grantTaskList[idx].status = '执行中' grantTaskList[idx].executeTime = nowStr() grantTaskList[idx].executor = '运营人员' return { code: 200, data: null, msg: '执行成功' } }) Mock.mock(/\/api\/equity-grant-campaign\/detail/, 'get', (options) => { const url = new URL(options.url, 'http://localhost') const id = url.searchParams.get('id') const item = equityGrantCampaignList.find(c => c.id === id) return item ? { code: 200, data: item, msg: 'ok' } : { code: 404, data: null, msg: '发放计划不存在' } }) Mock.mock(/\/api\/equity-grant-campaign\/end/, 'post', (options) => { const body = JSON.parse(options.body) const idx = equityGrantCampaignList.findIndex(c => c.id === body.id) if (idx < 0) return { code: 404, data: null, msg: '发放计划不存在' } const cur = equityGrantCampaignList[idx] if (cur.auditStatus !== '审核通过') return { code: 400, data: null, msg: '仅审核通过状态可提交结束审核' } // 创建审核单并更新发放计划状态为结束待审核 const auditId = nextCampaignAuditId() const now = nowStr() equityGrantCampaignList[idx] = { ...cur, auditStatus: '结束待审核', updateTime: now } campaignAuditList.unshift({ id: auditId, auditType: 'end', bizModuleName: '发放计划', bizId: cur.id, bizName: cur.name, snapshot: { name: cur.name, startTime: cur.startTime, endTime: cur.endTime, grantMode: cur.grantMode, targetType: cur.targetType || '客群', prospectTypes: cur.prospectTypes || [], crowdList: cur.crowdList || [], equityList: cur.equityList || [], grantCycle: cur.grantCycle, grantQuantity: cur.grantQuantity, validity: cur.validity, smsTemplateId: cur.smsTemplateId || '', smsTemplate: cur.smsTemplate || '' }, submitterName: body.submitterName || '运营', submitTime: now, auditorName: '', auditTime: '', auditStatus: 'pending', auditComment: '' }) return { code: 200, data: { auditId }, msg: '已提交结束审核' } }) // ============================================= // 规则组审核 // ============================================= let ruleGroupAuditIdCounter = 200 function nextRuleGroupAuditId() { ruleGroupAuditIdCounter += 1 const d = new Date() const ymd = d.getFullYear().toString() + String(d.getMonth() + 1).padStart(2, '0') + String(d.getDate()).padStart(2, '0') return 'RGA' + ymd + String(ruleGroupAuditIdCounter).padStart(4, '0') } const ruleGroupAuditList = [ { id: 'RGA202605250001', auditType: 'new', bizModuleName: '规则组', bizId: 'RG20260420003', bizName: '借记卡-跨境候选客群', submitterName: '赵市场', submitTime: '2026-05-25 10:00:00', auditorName: '', auditTime: '', auditStatus: 'pending', auditComment: '' }, { id: 'RGA202605230001', auditType: 'new', bizModuleName: '规则组', bizId: 'RG20260401001', bizName: '层层礼-借记卡新客圈选', submitterName: '张运营', submitTime: '2026-05-23 14:30:00', auditorName: '王审核', auditTime: '2026-05-24 09:00:00', auditStatus: 'approved', auditComment: '规则配置合理,准予上线' } ] Mock.mock(/\/api\/rule-group-audit\/list/, 'get', (options) => { const url = new URL(options.url, 'http://localhost') const auditStatus = url.searchParams.get('auditStatus') || '' const bizName = url.searchParams.get('bizName') || '' const bizId = url.searchParams.get('bizId') || '' let filtered = ruleGroupAuditList if (auditStatus) filtered = filtered.filter(a => a.auditStatus === auditStatus) if (bizName) filtered = filtered.filter(a => a.bizName.includes(bizName)) if (bizId) filtered = filtered.filter(a => String(a.bizId).includes(bizId)) return { code: 200, data: filtered, msg: 'ok' } }) Mock.mock(/\/api\/rule-group-audit\/detail/, 'get', (options) => { const url = new URL(options.url, 'http://localhost') const id = url.searchParams.get('id') const item = ruleGroupAuditList.find(a => a.id === id) return item ? { code: 200, data: item, msg: 'ok' } : { code: 404, data: null, msg: '审核单不存在' } }) Mock.mock(/\/api\/rule-group-audit\/approve/, 'post', (options) => { const body = JSON.parse(options.body) const idx = ruleGroupAuditList.findIndex(a => a.id === body.id) if (idx < 0) return { code: 404, data: null, msg: '审核单不存在' } const audit = ruleGroupAuditList[idx] if (audit.auditStatus !== 'pending') return { code: 400, data: null, msg: '该审核单已完成' } const now = nowStr() ruleGroupAuditList[idx] = { ...audit, auditStatus: 'approved', auditorName: body.auditorName || '王审核', auditTime: now, auditComment: body.comment || '' } return { code: 200, data: null, msg: '审核通过' } }) Mock.mock(/\/api\/rule-group-audit\/reject/, 'post', (options) => { const body = JSON.parse(options.body) const idx = ruleGroupAuditList.findIndex(a => a.id === body.id) if (idx < 0) return { code: 404, data: null, msg: '审核单不存在' } const audit = ruleGroupAuditList[idx] if (audit.auditStatus !== 'pending') return { code: 400, data: null, msg: '该审核单已完成' } const now = nowStr() ruleGroupAuditList[idx] = { ...audit, auditStatus: 'rejected', auditorName: body.auditorName || '王审核', auditTime: now, auditComment: body.comment || '' } return { code: 200, data: null, msg: '已驳回' } }) // ============================================= // 发放计划审核 // ============================================= let campaignAuditIdCounter = 100 function nextCampaignAuditId() { campaignAuditIdCounter += 1 const d = new Date() const ymd = d.getFullYear().toString() + String(d.getMonth() + 1).padStart(2, '0') + String(d.getDate()).padStart(2, '0') return 'CA' + ymd + String(campaignAuditIdCounter).padStart(4, '0') } const campaignAuditList = [ { id: 'CA202605200001', auditType: 'new', bizModuleName: '发放计划', bizId: 'P000003', bizName: '秋季养生权益季', snapshot: { name: '秋季养生权益季', startTime: '2026-09-01 00:00:00', endTime: '2026-11-30 23:59:59', grantMode: 'claim', crowdList: ['00000120251224'], equityList: ['Q100001', 'Q100004'], grantCycle: 'monthly', grantQuantity: 1, validity: { type: 'relative', fixedRange: [], relativeDays: 30 }, smsTemplateId: 'GRANT_SMS_001', smsTemplate: '【银行】尊敬的${customerName},您已获得${productName}权益,发放时间:${grantTime},请于${expireDate}前使用。' }, submitterName: '王运营', submitTime: '2026-05-20 09:30:00', auditorName: '', auditTime: '', auditStatus: 'pending', auditComment: '' }, { id: 'CA202605220001', auditType: 'new', bizModuleName: '发放计划', bizId: 'P000004', bizName: '冬季暖心权益发放', snapshot: { name: '冬季暖心权益发放', startTime: '2026-12-01 00:00:00', endTime: '2027-02-28 23:59:59', grantMode: 'direct', crowdList: ['00000120251224'], equityList: ['Q100001'], grantCycle: 'total', grantQuantity: 3, validity: { type: 'fixed', fixedRange: ['2026-12-01', '2027-02-28'], relativeDays: 30 }, smsTemplateId: 'GRANT_SMS_002', smsTemplate: '【银行】尊敬的${customerName},您已获得${productName}权益,有效期至${expireDate},请登录APP查看详情。' }, submitterName: '陈运营', submitTime: '2026-05-22 10:15:00', auditorName: '', auditTime: '', auditStatus: 'pending', auditComment: '' }, { id: 'CA202605180001', auditType: 'new', bizModuleName: '发放计划', bizId: 'P000001', bizName: '春季会员尊享礼遇', snapshot: { name: '春季会员尊享礼遇', startTime: '2026-04-01 00:00:00', endTime: '2026-06-30 23:59:59', grantMode: 'direct', crowdList: ['00000120251224'], equityList: ['Q100001'], grantCycle: 'monthly', grantQuantity: 2, validity: { type: 'fixed', fixedRange: ['2026-04-01', '2026-06-30'], relativeDays: 30 }, smsTemplateId: 'GRANT_SMS_003', smsTemplate: '【银行】${customerName}您好,${productName}已为您发放成功,有效期至${expireDate}。' }, submitterName: '李运营', submitTime: '2026-05-18 14:20:00', auditorName: '王五', auditTime: '2026-05-19 09:00:00', auditStatus: 'approved', auditComment: '发放计划内容合规,准予通过' } ] Mock.mock(/\/api\/campaign-audit\/list/, 'get', (options) => { const url = new URL(options.url, 'http://localhost') const auditStatus = url.searchParams.get('auditStatus') || '' const bizId = url.searchParams.get('bizId') || '' let filtered = campaignAuditList if (auditStatus) filtered = filtered.filter(a => a.auditStatus === auditStatus) if (bizId) filtered = filtered.filter(a => a.bizId === bizId) return { code: 200, data: filtered, msg: 'ok' } }) Mock.mock(/\/api\/campaign-audit\/detail/, 'get', (options) => { const url = new URL(options.url, 'http://localhost') const id = url.searchParams.get('id') const item = campaignAuditList.find(a => a.id === id) return item ? { code: 200, data: item, msg: 'ok' } : { code: 404, data: null, msg: '审核单不存在' } }) Mock.mock(/\/api\/campaign-audit\/approve/, 'post', (options) => { const body = JSON.parse(options.body) const idx = campaignAuditList.findIndex(a => a.id === body.id) if (idx < 0) return { code: 404, data: null, msg: '审核单不存在' } const audit = campaignAuditList[idx] if (audit.auditStatus !== 'pending') return { code: 400, data: null, msg: '该审核单已完成' } const now = nowStr() campaignAuditList[idx] = { ...audit, auditStatus: 'approved', auditorName: body.auditorName || '王五', auditTime: now, auditComment: body.comment || '' } // 同步更新发放计划主表 const campaignIdx = equityGrantCampaignList.findIndex(c => c.id === audit.bizId) if (campaignIdx >= 0) { if (audit.auditType === 'new') { equityGrantCampaignList[campaignIdx].auditStatus = '审核通过' } else if (audit.auditType === 'end') { // 结束审核通过:实际结束发放计划 equityGrantCampaignList[campaignIdx] = { ...equityGrantCampaignList[campaignIdx], endTime: now, auditStatus: '审核通过', updateTime: now } } } return { code: 200, data: null, msg: '审核通过' } }) Mock.mock(/\/api\/campaign-audit\/reject/, 'post', (options) => { const body = JSON.parse(options.body) const idx = campaignAuditList.findIndex(a => a.id === body.id) if (idx < 0) return { code: 404, data: null, msg: '审核单不存在' } const audit = campaignAuditList[idx] if (audit.auditStatus !== 'pending') return { code: 400, data: null, msg: '该审核单已完成' } const now = nowStr() campaignAuditList[idx] = { ...audit, auditStatus: 'rejected', auditorName: body.auditorName || '王五', auditTime: now, auditComment: body.comment || '' } // 驳回后回退发放计划审核状态为审核通过,允许重新编辑/结束 const campaignIdx = equityGrantCampaignList.findIndex(c => c.id === audit.bizId) if (campaignIdx >= 0) equityGrantCampaignList[campaignIdx] = { ...equityGrantCampaignList[campaignIdx], auditStatus: '审核通过', updateTime: now } return { code: 200, data: null, msg: '已驳回' } }) // ==================== 券码审核 ==================== const couponAuditList = [ { id: 'CPA202606040001', type: 'import', productName: '权益A', productId: 'Q100001', importCount: 1000, effectiveTime: '2026-06-05 00:00:00', expireTime: '2026-12-31 23:59:59', creator: '张三', createTime: '2026-06-04 10:32:18', auditorName: '', auditTime: '', auditStatus: 'pending' }, { id: 'CPA202606030001', type: 'import', productName: '微信立减金 5元(满10减5)', productId: 'Q100007', importCount: 5000, effectiveTime: '2026-06-10 00:00:00', expireTime: '2026-09-30 23:59:59', creator: '李四', createTime: '2026-06-03 15:08:42', auditorName: '', auditTime: '', auditStatus: 'pending' }, { id: 'CPA202605280001', type: 'import', productName: '权益B', productId: 'Q100002', importCount: 500, effectiveTime: '2026-06-01 00:00:00', expireTime: '2026-12-31 23:59:59', creator: '李四', createTime: '2026-05-28 14:15:42', auditorName: '王五', auditTime: '2026-05-29 09:20:00', auditStatus: 'approved' }, { id: 'CPA202605200001', type: 'import', productName: '权益C', productId: 'Q100003', importCount: 800, effectiveTime: '2026-05-25 00:00:00', expireTime: '2026-10-31 23:59:59', creator: '王五', createTime: '2026-05-20 09:08:11', auditorName: '赵管理', auditTime: '2026-05-21 16:30:00', auditStatus: 'approved' }, { id: 'CPA202605150001', type: 'import', productName: '权益D', productId: 'Q100004', importCount: 200, effectiveTime: '2026-05-20 00:00:00', expireTime: '2026-08-31 23:59:59', creator: '赵六', createTime: '2026-05-15 16:45:30', auditorName: '王五', auditTime: '2026-05-16 10:05:00', auditStatus: 'rejected' }, { id: 'CPA202606040002', type: 'recycle_unissued', productName: '权益B', productId: 'Q100002', importCount: 100, effectiveTime: '2026-06-01 00:00:00', expireTime: '2026-12-31 23:59:59', creator: '张三', createTime: '2026-06-04 16:40:00', auditorName: '', auditTime: '', auditStatus: 'pending' }, { id: 'CPA202606020001', type: 'recycle_expired', productName: '权益C', productId: 'Q100003', importCount: 50, effectiveTime: '2026-05-25 00:00:00', expireTime: '2026-06-01 23:59:59', creator: '王五', createTime: '2026-06-02 11:20:00', auditorName: '', auditTime: '', auditStatus: 'pending' }, { id: 'CPA202606010001', type: 'import', productName: '权益C', productId: 'Q100003', importCount: 1500, effectiveTime: '2026-06-08 00:00:00', expireTime: '2026-12-31 23:59:59', creator: '王五', createTime: '2026-06-01 09:15:00', auditorName: '', auditTime: '', auditStatus: 'pending' }, { id: 'CPA202605310001', type: 'recycle_wrong', productName: '权益A', productId: 'Q100001', importCount: 20, effectiveTime: '2026-04-16 00:00:00', expireTime: '2026-12-31 23:59:59', creator: '李四', createTime: '2026-05-31 14:22:00', auditorName: '', auditTime: '', auditStatus: 'pending' }, { id: 'CPA202605300001', type: 'import', productName: '权益D', productId: 'Q100004', importCount: 800, effectiveTime: '2026-06-15 00:00:00', expireTime: '2026-11-30 23:59:59', creator: '赵六', createTime: '2026-05-30 10:05:00', auditorName: '', auditTime: '', auditStatus: 'pending' }, { id: 'CPA202605290001', type: 'recycle_unissued', productName: '权益A', productId: 'Q100001', importCount: 60, effectiveTime: '2026-04-16 00:00:00', expireTime: '2026-12-31 23:59:59', creator: '张三', createTime: '2026-05-29 16:48:00', auditorName: '', auditTime: '', auditStatus: 'pending' }, { id: 'CPA202605270001', type: 'import', productName: '微信立减金 5元(满10减5)', productId: 'Q100007', importCount: 3000, effectiveTime: '2026-06-01 00:00:00', expireTime: '2026-09-30 23:59:59', creator: '李四', createTime: '2026-05-27 11:30:00', auditorName: '', auditTime: '', auditStatus: 'pending' }, { id: 'CPA202605260001', type: 'recycle_expired', productName: '权益B', productId: 'Q100002', importCount: 35, effectiveTime: '2026-04-21 00:00:00', expireTime: '2026-05-20 23:59:59', creator: '王五', createTime: '2026-05-26 09:55:00', auditorName: '', auditTime: '', auditStatus: 'pending' }, { id: 'CPA202605250001', type: 'import', productName: '权益E', productId: 'Q100005', importCount: 1200, effectiveTime: '2026-06-01 00:00:00', expireTime: '2026-10-31 23:59:59', creator: '张三', createTime: '2026-05-25 15:12:00', auditorName: '', auditTime: '', auditStatus: 'pending' }, { id: 'CPA202605240001', type: 'recycle_unissued', productName: '权益C', productId: 'Q100003', importCount: 90, effectiveTime: '2026-05-25 00:00:00', expireTime: '2026-10-31 23:59:59', creator: '赵六', createTime: '2026-05-24 10:40:00', auditorName: '', auditTime: '', auditStatus: 'pending' }, { id: 'CPA202605220001', type: 'recycle_wrong', productName: '权益D', productId: 'Q100004', importCount: 200, effectiveTime: '2026-05-20 00:00:00', expireTime: '2026-08-31 23:59:59', creator: '赵六', createTime: '2026-05-22 10:10:00', auditorName: '王五', auditTime: '2026-05-23 09:30:00', auditStatus: 'approved' } ] Mock.mock(/\/api\/coupon-audit\/list/, 'get', (options) => { const url = new URL(options.url, 'http://localhost') const auditStatus = url.searchParams.get('auditStatus') || '' const productId = url.searchParams.get('productId') || '' // 券码审核类型暂时仅保留「导入」,回收相关类型先去掉 let filtered = couponAuditList.filter(a => a.type === 'import') if (auditStatus === 'reviewed') { // 已审核 = 审核通过 + 审核驳回 filtered = filtered.filter(a => a.auditStatus === 'approved' || a.auditStatus === 'rejected') } else if (auditStatus) { filtered = filtered.filter(a => a.auditStatus === auditStatus) } if (productId) filtered = filtered.filter(a => a.productId === productId) return { code: 200, data: filtered, msg: 'ok' } }) Mock.mock(/\/api\/coupon-audit\/approve/, 'post', (options) => { const body = JSON.parse(options.body) const idx = couponAuditList.findIndex(a => a.id === body.id) if (idx < 0) return { code: 404, data: null, msg: '审核单不存在' } const audit = couponAuditList[idx] if (audit.auditStatus !== 'pending') return { code: 400, data: null, msg: '该审核单已完成' } couponAuditList[idx] = { ...audit, auditStatus: 'approved', auditorName: body.auditorName || '王五', auditTime: nowStr() } // 联动待导入记录:已关联权益商品 → 模拟 SIP 导入、移入已导入列表;未关联 → 仅置为审核通过,留在待导入列表 if (audit.batchId) { const pending = pendingCouponList.find(p => p.batchId === audit.batchId) if (pending) { pending.auditStatus = 'approved' if (pending.productId) importPendingBatch(pending.batchId) } } return { code: 200, data: null, msg: '审核通过' } }) Mock.mock(/\/api\/coupon-audit\/reject/, 'post', (options) => { const body = JSON.parse(options.body) const idx = couponAuditList.findIndex(a => a.id === body.id) if (idx < 0) return { code: 404, data: null, msg: '审核单不存在' } const audit = couponAuditList[idx] if (audit.auditStatus !== 'pending') return { code: 400, data: null, msg: '该审核单已完成' } couponAuditList[idx] = { ...audit, auditStatus: 'rejected', auditorName: body.auditorName || '王五', auditTime: nowStr() } if (audit.batchId) { const pending = pendingCouponList.find(p => p.batchId === audit.batchId) if (pending) pending.auditStatus = 'rejected' } return { code: 200, data: null, msg: '已驳回' } }) // ==================== 已导入券码批次(全部借记卡权益商品) ==================== const couponBatchList = [ { batchId: 'B100001', productId: 'Q100001', equityName: '权益A', importCount: 1000, actualImportCount: 998, failCount: 2, remainingCount: 720, effectiveTime: '2026-04-16 00:00:00', expireTime: '2026-12-31 23:59:59', fileStatus: '处理成功', importTime: '2026-04-15 10:32:18', creator: '张三', recycleRecords: [ { recycleTime: '2026-05-10 14:22:08', type: '未发放券码回收', operator: '张三', amount: 120 }, { recycleTime: '2026-04-28 09:15:33', type: '已过期券码回收', operator: '李四', amount: 80 } ] }, { batchId: 'B100002', productId: 'Q100001', equityName: '权益A', importCount: 500, actualImportCount: 500, failCount: 0, remainingCount: 320, effectiveTime: '2026-04-21 00:00:00', expireTime: '2026-09-30 23:59:59', fileStatus: '处理成功', importTime: '2026-04-20 14:15:42', creator: '李四', recycleRecords: [ { recycleTime: '2026-04-12 16:40:51', type: '未发放券码回收', operator: '王五', amount: 200 } ] }, { batchId: 'B100003', productId: 'Q100002', equityName: '权益B', importCount: 800, actualImportCount: 0, failCount: 0, remainingCount: 0, effectiveTime: '2026-05-08 00:00:00', expireTime: '2026-12-31 23:59:59', fileStatus: '处理中', importTime: '2026-05-07 09:08:11', creator: '王五', recycleRecords: [] }, { batchId: 'B100004', productId: 'Q100002', equityName: '权益B', importCount: 200, actualImportCount: 0, failCount: 200, remainingCount: 0, effectiveTime: '2026-05-02 00:00:00', expireTime: '2026-10-31 23:59:59', fileStatus: '处理失败', importTime: '2026-05-01 16:45:30', creator: '赵六', recycleRecords: [] }, { batchId: 'B100005', productId: 'Q100003', equityName: '权益C', importCount: 1500, actualImportCount: 1500, failCount: 0, remainingCount: 1280, effectiveTime: '2026-04-10 00:00:00', expireTime: '2026-12-31 23:59:59', fileStatus: '处理成功', importTime: '2026-04-09 09:21:05', creator: '张三', recycleRecords: [] }, { batchId: 'B100006', productId: 'Q100003', equityName: '权益C', importCount: 600, actualImportCount: 598, failCount: 2, remainingCount: 420, effectiveTime: '2026-04-05 00:00:00', expireTime: '2026-11-30 23:59:59', fileStatus: '处理成功', importTime: '2026-04-04 14:02:33', creator: '李四', recycleRecords: [] }, { batchId: 'B100007', productId: 'Q100004', equityName: '权益D', importCount: 300, actualImportCount: 300, failCount: 0, remainingCount: 0, effectiveTime: '2026-03-20 00:00:00', expireTime: '2026-09-30 23:59:59', fileStatus: '处理成功', importTime: '2026-03-19 10:45:12', creator: '王五', recycleRecords: [] }, { batchId: 'B100008', productId: 'Q100004', equityName: '权益D', importCount: 2000, actualImportCount: 1995, failCount: 5, remainingCount: 1620, effectiveTime: '2026-03-15 00:00:00', expireTime: '2026-12-31 23:59:59', fileStatus: '处理成功', importTime: '2026-03-14 16:30:48', creator: '张三', recycleRecords: [] }, { batchId: 'B100009', productId: 'Q100005', equityName: '权益E', importCount: 450, actualImportCount: 450, failCount: 0, remainingCount: 130, effectiveTime: '2026-03-01 00:00:00', expireTime: '2026-08-31 23:59:59', fileStatus: '处理成功', importTime: '2026-02-28 11:18:27', creator: '李四', recycleRecords: [] }, { batchId: 'B100010', productId: 'Q100005', equityName: '权益E', importCount: 800, actualImportCount: 796, failCount: 4, remainingCount: 510, effectiveTime: '2026-02-20 00:00:00', expireTime: '2026-10-31 23:59:59', fileStatus: '处理成功', importTime: '2026-02-19 15:55:09', creator: '王五', recycleRecords: [] }, { batchId: 'B100011', productId: 'Q100007', equityName: '微信立减金 5元(满10减5)', importCount: 1200, actualImportCount: 1200, failCount: 0, remainingCount: 60, effectiveTime: '2026-02-10 00:00:00', expireTime: '2026-07-31 23:59:59', fileStatus: '处理成功', importTime: '2026-02-09 09:40:51', creator: '赵六', recycleRecords: [] }, { batchId: 'B100012', productId: 'Q100001', equityName: '权益A', importCount: 350, actualImportCount: 348, failCount: 2, remainingCount: 0, effectiveTime: '2026-01-15 00:00:00', expireTime: '2026-06-30 23:59:59', fileStatus: '处理成功', importTime: '2026-01-14 13:27:36', creator: '张三', recycleRecords: [] } ] // 已导入券码列表:权益编号、批次ID 均为精准匹配 Mock.mock(/\/api\/coupon\/batch-list/, 'get', (options) => { const url = new URL(options.url, 'http://localhost') const productId = url.searchParams.get('productId') || '' const batchId = url.searchParams.get('batchId') || '' let filtered = couponBatchList if (productId) filtered = filtered.filter(b => b.productId === productId) if (batchId) filtered = filtered.filter(b => b.batchId === batchId) return { code: 200, data: filtered, msg: 'ok' } }) // 导入券码:生成「待导入券码记录」+「券码审核单」,券码审核通过后才真正导入 Mock.mock(/\/api\/coupon\/import/, 'post', (options) => { const body = JSON.parse(options.body) let productId = '' let equityName = '' if (body.productId) { const equity = equityList.find(e => e.productId === body.productId) if (!equity) return { code: 404, data: null, msg: '权益商品不存在' } productId = equity.productId equityName = equity.equityName } const batchId = nextPendingBatchId() // 原型读不了上传文件,导入数量用 mock 随机数模拟 const importCount = 100 + Math.floor(Math.random() * 4900) const createTime = nowStr() const pending = { batchId, productId, equityName, importCount, creator: '当前用户', createTime, auditStatus: 'pending' } pendingCouponList.unshift(pending) couponAuditList.unshift(makeImportAudit(pending)) return { code: 200, data: { batchId }, msg: '已提交,等待券码审核' } }) Mock.mock(/\/api\/coupon\/recycle/, 'post', (options) => { const body = JSON.parse(options.body) const batch = couponBatchList.find(b => b.batchId === body.batchId) if (!batch) return { code: 404, data: null, msg: '批次不存在' } const amount = Number(body.amount) || 0 if (amount < 1) return { code: 400, data: null, msg: '回收数量无效' } // 未发放券码回收会扣减剩余数量;已过期券码回收仅记录,不扣减剩余库存 if (body.type === 'unissued') { batch.remainingCount = Math.max(0, Number(batch.remainingCount) - amount) } const typeLabel = body.type === 'expired' ? '已过期券码回收' : '未发放券码回收' if (!batch.recycleRecords) batch.recycleRecords = [] batch.recycleRecords.unshift({ recycleTime: nowStr(), type: typeLabel, operator: '当前用户', amount }) return { code: 200, data: null, msg: '回收成功' } }) // ==================== 待导入券码记录(券码先导入、后关联权益) ==================== function nextPendingBatchId() { const d = new Date() const p = n => String(n).padStart(2, '0') return 'I' + d.getFullYear() + p(d.getMonth() + 1) + p(d.getDate()) + p(d.getHours()) + p(d.getMinutes()) + p(d.getSeconds()) } const pendingCouponList = [ { batchId: 'I20260620090301', productId: '', equityName: '', importCount: 1000, creator: '张三', createTime: '2026-06-20 09:03:01', auditStatus: 'pending' }, { batchId: 'I20260620143512', productId: 'Q100001', equityName: '权益A', importCount: 500, creator: '李四', createTime: '2026-06-20 14:35:12', auditStatus: 'pending' }, { batchId: 'I20260618101055', productId: '', equityName: '', importCount: 1200, creator: '张三', createTime: '2026-06-18 10:10:55', auditStatus: 'approved' }, { batchId: 'I20260617161820', productId: '', equityName: '', importCount: 800, creator: '王五', createTime: '2026-06-17 16:18:20', auditStatus: 'approved' }, { batchId: 'I20260616113045', productId: 'Q100003', equityName: '权益C', importCount: 300, creator: '赵六', createTime: '2026-06-16 11:30:45', auditStatus: 'rejected' }, { batchId: 'I20260615153000', productId: '', equityName: '', importCount: 600, creator: '李四', createTime: '2026-06-15 15:30:00', auditStatus: 'rejected' } ] // 待导入记录 → 已导入批次(模拟 SIP 导入成功) function importPendingBatch(batchId, productId, equityName) { const idx = pendingCouponList.findIndex(p => p.batchId === batchId) if (idx < 0) return false const p = pendingCouponList[idx] pendingCouponList.splice(idx, 1) couponBatchList.unshift({ batchId: p.batchId, productId: productId || p.productId, equityName: equityName || p.equityName, importCount: p.importCount, actualImportCount: p.importCount, failCount: 0, remainingCount: p.importCount, effectiveTime: '', expireTime: '', fileStatus: '处理成功', importTime: nowStr(), creator: p.creator, recycleRecords: [] }) return true } // 由待导入记录派生对应的券码审核单 let couponAuditSeq = 0 function makeImportAudit(p) { couponAuditSeq += 1 const reviewed = p.auditStatus !== 'pending' return { id: 'CPA' + p.batchId.slice(1) + String(couponAuditSeq).padStart(2, '0'), type: 'import', batchId: p.batchId, productName: p.equityName || '', productId: p.productId || '', importCount: p.importCount, effectiveTime: '', expireTime: '', creator: p.creator, createTime: p.createTime, auditorName: reviewed ? '王五' : '', auditTime: reviewed ? p.createTime : '', auditStatus: p.auditStatus } } // 用待导入记录派生的审核单替换旧的占位 import 审核单(recycle 记录保留) for (let i = couponAuditList.length - 1; i >= 0; i--) { if (couponAuditList[i].type === 'import') couponAuditList.splice(i, 1) } pendingCouponList.forEach(p => couponAuditList.push(makeImportAudit(p))) // 待导入券码列表(券码管理-待导入 Tab;选择批次弹窗传 status=approved&unlinked=1) Mock.mock(/\/api\/coupon\/pending-list/, 'get', (options) => { const url = new URL(options.url, 'http://localhost') const batchId = url.searchParams.get('batchId') || '' const status = url.searchParams.get('status') || '' const unlinked = url.searchParams.get('unlinked') || '' let filtered = pendingCouponList if (batchId) filtered = filtered.filter(p => p.batchId === batchId) if (status) filtered = filtered.filter(p => p.auditStatus === status) if (unlinked === '1') filtered = filtered.filter(p => !p.productId) return { code: 200, data: filtered, msg: 'ok' } }) // 编辑待导入记录(仅审核拒绝可编辑:可改关联权益商品,提交后重新进入待审核) Mock.mock(/\/api\/coupon\/pending-edit/, 'post', (options) => { const body = JSON.parse(options.body) const p = pendingCouponList.find(x => x.batchId === body.batchId) if (!p) return { code: 404, data: null, msg: '记录不存在' } if (p.auditStatus !== 'rejected') return { code: 400, data: null, msg: '仅审核拒绝的记录可编辑' } p.auditStatus = 'pending' const audit = couponAuditList.find(a => a.type === 'import' && a.batchId === p.batchId) if (audit) { audit.auditStatus = 'pending' audit.auditorName = '' audit.auditTime = '' } return { code: 200, data: null, msg: '已重新提交审核' } }) // 删除待导入记录(仅审核拒绝可删除) Mock.mock(/\/api\/coupon\/pending-delete/, 'post', (options) => { const body = JSON.parse(options.body) const idx = pendingCouponList.findIndex(p => p.batchId === body.batchId) if (idx < 0) return { code: 404, data: null, msg: '记录不存在' } if (pendingCouponList[idx].auditStatus !== 'rejected') return { code: 400, data: null, msg: '仅审核拒绝的记录可删除' } pendingCouponList.splice(idx, 1) const aIdx = couponAuditList.findIndex(a => a.type === 'import' && a.batchId === body.batchId) if (aIdx >= 0) couponAuditList.splice(aIdx, 1) return { code: 200, data: null, msg: '已删除' } }) export default Mock