新增和优化以下功能:
优化 对接微信转账,调整接口
优化 会员提现流程
优化 微信开放平台小程序同步流程
修复 开发模式时安装插件文件未能正常安装的问题
修复 redis存在密码时无法正常连接的问题
修复 签到报错的问题
修复 提现设置设置异常的问题
修复 分销商品设置为默认规则时分销商品列表接口异常的问题
This commit is contained in:
wangchen147 2025-04-11 14:29:14 +08:00
parent 76b899b1b1
commit 5dbd3b4cd6
1281 changed files with 13387 additions and 8994 deletions

View File

@ -1,5 +1,6 @@
// Generated by 'unplugin-auto-import' // Generated by 'unplugin-auto-import'
export {} export {}
declare global { declare global {
const ElMessageBox: typeof import('element-plus/es')['ElMessageBox']
const ElNotification: typeof import('element-plus/es')['ElNotification'] const ElNotification: typeof import('element-plus/es')['ElNotification']
} }

13
admin/components.d.ts vendored
View File

@ -11,8 +11,15 @@ declare module '@vue/runtime-core' {
DiyLink: typeof import('./src/components/diy-link/index.vue')['default'] DiyLink: typeof import('./src/components/diy-link/index.vue')['default']
Editor: typeof import('./src/components/editor/index.vue')['default'] Editor: typeof import('./src/components/editor/index.vue')['default']
ElAlert: typeof import('element-plus/es')['ElAlert'] ElAlert: typeof import('element-plus/es')['ElAlert']
ElAside: typeof import('element-plus/es')['ElAside']
ElAvatar: typeof import('element-plus/es')['ElAvatar']
ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb']
ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem']
ElButton: typeof import('element-plus/es')['ElButton'] ElButton: typeof import('element-plus/es')['ElButton']
ElCard: typeof import('element-plus/es')['ElCard'] ElCard: typeof import('element-plus/es')['ElCard']
ElCarousel: typeof import('element-plus/es')['ElCarousel']
ElCarouselItem: typeof import('element-plus/es')['ElCarouselItem']
ElCascader: typeof import('element-plus/es')['ElCascader']
ElCheckbox: typeof import('element-plus/es')['ElCheckbox'] ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup'] ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
ElCol: typeof import('element-plus/es')['ElCol'] ElCol: typeof import('element-plus/es')['ElCol']
@ -40,7 +47,10 @@ declare module '@vue/runtime-core' {
ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
ElLink: typeof import('element-plus/es')['ElLink'] ElLink: typeof import('element-plus/es')['ElLink']
ElMain: typeof import('element-plus/es')['ElMain'] ElMain: typeof import('element-plus/es')['ElMain']
ElMenu: typeof import('element-plus/es')['ElMenu']
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
ElOption: typeof import('element-plus/es')['ElOption'] ElOption: typeof import('element-plus/es')['ElOption']
ElOptionGroup: typeof import('element-plus/es')['ElOptionGroup']
ElPageHeader: typeof import('element-plus/es')['ElPageHeader'] ElPageHeader: typeof import('element-plus/es')['ElPageHeader']
ElPagination: typeof import('element-plus/es')['ElPagination'] ElPagination: typeof import('element-plus/es')['ElPagination']
ElPopover: typeof import('element-plus/es')['ElPopover'] ElPopover: typeof import('element-plus/es')['ElPopover']
@ -48,6 +58,7 @@ declare module '@vue/runtime-core' {
ElRadio: typeof import('element-plus/es')['ElRadio'] ElRadio: typeof import('element-plus/es')['ElRadio']
ElRadioButton: typeof import('element-plus/es')['ElRadioButton'] ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup'] ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
ElRate: typeof import('element-plus/es')['ElRate']
ElResult: typeof import('element-plus/es')['ElResult'] ElResult: typeof import('element-plus/es')['ElResult']
ElRow: typeof import('element-plus/es')['ElRow'] ElRow: typeof import('element-plus/es')['ElRow']
ElScrollbar: typeof import('element-plus/es')['ElScrollbar'] ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
@ -56,6 +67,7 @@ declare module '@vue/runtime-core' {
ElStatistic: typeof import('element-plus/es')['ElStatistic'] ElStatistic: typeof import('element-plus/es')['ElStatistic']
ElStep: typeof import('element-plus/es')['ElStep'] ElStep: typeof import('element-plus/es')['ElStep']
ElSteps: typeof import('element-plus/es')['ElSteps'] ElSteps: typeof import('element-plus/es')['ElSteps']
ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
ElSwitch: typeof import('element-plus/es')['ElSwitch'] ElSwitch: typeof import('element-plus/es')['ElSwitch']
ElTable: typeof import('element-plus/es')['ElTable'] ElTable: typeof import('element-plus/es')['ElTable']
ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
@ -66,6 +78,7 @@ declare module '@vue/runtime-core' {
ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem'] ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
ElTimePicker: typeof import('element-plus/es')['ElTimePicker'] ElTimePicker: typeof import('element-plus/es')['ElTimePicker']
ElTooltip: typeof import('element-plus/es')['ElTooltip'] ElTooltip: typeof import('element-plus/es')['ElTooltip']
ElTree: typeof import('element-plus/es')['ElTree']
ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect'] ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect']
ElUpload: typeof import('element-plus/es')['ElUpload'] ElUpload: typeof import('element-plus/es')['ElUpload']
ExportSure: typeof import('./src/components/export-sure/index.vue')['default'] ExportSure: typeof import('./src/components/export-sure/index.vue')['default']

View File

@ -9,7 +9,7 @@ import request from '@/utils/request'
* @returns * @returns
*/ */
export function getMemberList(params: Record<string, any>) { export function getMemberList(params: Record<string, any>) {
return request.get(`member/member`, {params}) return request.get(`member/member`, { params })
} }
/** /**
@ -35,7 +35,7 @@ export function getMemberNo() {
* @returns * @returns
*/ */
export function addMember(params: Record<string, any>) { export function addMember(params: Record<string, any>) {
return request.post(`member/member`, params, {showSuccessMessage: true}) return request.post(`member/member`, params, { showSuccessMessage: true })
} }
/** /**
@ -61,7 +61,7 @@ export function getRegisterChannelType(params: Record<string, any>) {
* @param member_id * @param member_id
*/ */
export function deleteMember(member_id: number) { export function deleteMember(member_id: number) {
return request.delete(`member/member/${member_id}`, {showSuccessMessage: true}) return request.delete(`member/member/${member_id}`, { showSuccessMessage: true })
} }
/***************************************************** 会员标签 ****************************************************/ /***************************************************** 会员标签 ****************************************************/
@ -72,7 +72,7 @@ export function deleteMember(member_id: number) {
* @returns * @returns
*/ */
export function getMemberLabelList(params: Record<string, any>) { export function getMemberLabelList(params: Record<string, any>) {
return request.get(`member/label`, {params}) return request.get(`member/label`, { params })
} }
/** /**
@ -90,7 +90,7 @@ export function getMemberLabelInfo(label_id: number) {
* @returns * @returns
*/ */
export function addMemberLabel(params: Record<string, any>) { export function addMemberLabel(params: Record<string, any>) {
return request.post('member/label', params, {showSuccessMessage: true}) return request.post('member/label', params, { showSuccessMessage: true })
} }
/** /**
@ -98,7 +98,7 @@ export function addMemberLabel(params: Record<string, any>) {
* @param params * @param params
*/ */
export function updateMemberLabel(params: Record<string, any>) { export function updateMemberLabel(params: Record<string, any>) {
return request.put(`member/label/${params.label_id}`, params, {showSuccessMessage: true}) return request.put(`member/label/${params.label_id}`, params, { showSuccessMessage: true })
} }
/** /**
@ -107,7 +107,7 @@ export function updateMemberLabel(params: Record<string, any>) {
* @returns * @returns
*/ */
export function deleteMemberLabel(label_id: number) { export function deleteMemberLabel(label_id: number) {
return request.delete(`member/label/${label_id}`, {showSuccessMessage: true}) return request.delete(`member/label/${label_id}`, { showSuccessMessage: true })
} }
/** /**
@ -122,7 +122,7 @@ export function getMemberLabelAll() {
* @param params * @param params
*/ */
export function editMemberDetail(params: Record<string, any>) { export function editMemberDetail(params: Record<string, any>) {
return request.put(`member/member/modify/${params.member_id}/${params.field}`, params, {showSuccessMessage: true}) return request.put(`member/member/modify/${params.member_id}/${params.field}`, params, { showSuccessMessage: true })
} }
/***************************************************** 会员零钱 ****************************************************/ /***************************************************** 会员零钱 ****************************************************/
@ -144,7 +144,7 @@ export function getChangeTypeList(change_type: string) {
* @returns * @returns
*/ */
export function getPointList(params: Record<string, any>) { export function getPointList(params: Record<string, any>) {
return request.get(`member/account/point`, {params}) return request.get(`member/account/point`, { params })
} }
/** /**
@ -153,7 +153,7 @@ export function getPointList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getGrowthList(params: Record<string, any>) { export function getGrowthList(params: Record<string, any>) {
return request.get(`member/account/growth`, {params}) return request.get(`member/account/growth`, { params })
} }
/** /**
@ -162,7 +162,7 @@ export function getGrowthList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getBalanceList(params: Record<string, any>) { export function getBalanceList(params: Record<string, any>) {
return request.get(`member/account/balance`, {params}) return request.get(`member/account/balance`, { params })
} }
/** /**
@ -171,7 +171,7 @@ export function getBalanceList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getMoneyList(params: Record<string, any>) { export function getMoneyList(params: Record<string, any>) {
return request.get(`member/account/money`, {params}) return request.get(`member/account/money`, { params })
} }
/** /**
@ -180,7 +180,7 @@ export function getMoneyList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getCommissionList(params: Record<string, any>) { export function getCommissionList(params: Record<string, any>) {
return request.get(`member/account/commission`, {params}) return request.get(`member/account/commission`, { params })
} }
/** /**
@ -189,7 +189,7 @@ export function getCommissionList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function adjustPoint(params: Record<string, any>) { export function adjustPoint(params: Record<string, any>) {
return request.post(`member/account/point`, params, {showSuccessMessage: true}) return request.post(`member/account/point`, params, { showSuccessMessage: true })
} }
/** /**
@ -198,7 +198,7 @@ export function adjustPoint(params: Record<string, any>) {
* @returns * @returns
*/ */
export function adjustBalance(params: Record<string, any>) { export function adjustBalance(params: Record<string, any>) {
return request.post(`member/account/balance`, params, {showSuccessMessage: true}) return request.post(`member/account/balance`, params, { showSuccessMessage: true })
} }
/***************************************************** 会员相关设置 ****************************************************/ /***************************************************** 会员相关设置 ****************************************************/
@ -216,7 +216,7 @@ export function getLoginConfig() {
* @returns * @returns
*/ */
export function setLoginConfig(params: Record<string, any>) { export function setLoginConfig(params: Record<string, any>) {
return request.post(`member/config/login`, params, {showSuccessMessage: true}) return request.post(`member/config/login`, params, { showSuccessMessage: true })
} }
/** /**
@ -232,7 +232,7 @@ export function getMemberConfig() {
* @returns * @returns
*/ */
export function setMemberConfig(params: Record<string, any>) { export function setMemberConfig(params: Record<string, any>) {
return request.post(`member/config/member`, params, {showSuccessMessage: true}) return request.post(`member/config/member`, params, { showSuccessMessage: true })
} }
/** /**
@ -241,7 +241,7 @@ export function setMemberConfig(params: Record<string, any>) {
* @returns * @returns
*/ */
export function setGrowthRuleConfig(params: Record<string, any>) { export function setGrowthRuleConfig(params: Record<string, any>) {
return request.post(`member/config/growth_rule`, params, {showSuccessMessage: true}) return request.post(`member/config/growth_rule`, params, { showSuccessMessage: true })
} }
/** /**
@ -257,7 +257,7 @@ export function getGrowthRuleConfig() {
* @returns * @returns
*/ */
export function setPointRuleConfig(params: Record<string, any>) { export function setPointRuleConfig(params: Record<string, any>) {
return request.post(`member/config/point_rule`, params, {showSuccessMessage: true}) return request.post(`member/config/point_rule`, params, { showSuccessMessage: true })
} }
/** /**
@ -281,7 +281,7 @@ export function getTransfertype() {
* @returns * @returns
*/ */
export function getCommissionSum(params: Record<string, any>) { export function getCommissionSum(params: Record<string, any>) {
return request.get(`member/account/sum_commission`, {params}) return request.get(`member/account/sum_commission`, { params })
} }
/** /**
@ -290,7 +290,7 @@ export function getCommissionSum(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getPointSum(params: Record<string, any>) { export function getPointSum(params: Record<string, any>) {
return request.get(`member/account/sum_point`, {params}) return request.get(`member/account/sum_point`, { params })
} }
/** /**
@ -299,7 +299,7 @@ export function getPointSum(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getBalanceSum(params: Record<string, any>) { export function getBalanceSum(params: Record<string, any>) {
return request.get(`member/account/sum_balance`, {params}) return request.get(`member/account/sum_balance`, { params })
} }
/** /**
@ -332,7 +332,7 @@ export function getCashOutConfig() {
* @returns * @returns
*/ */
export function setCashOutConfig(params: Record<string, any>) { export function setCashOutConfig(params: Record<string, any>) {
return request.post(`member/config/cash_out`, params, {showSuccessMessage: true}) return request.post(`member/config/cash_out`, params, { showSuccessMessage: true })
} }
/** /**
@ -341,7 +341,7 @@ export function setCashOutConfig(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getCashOutList(params: Record<string, any>) { export function getCashOutList(params: Record<string, any>) {
return request.get(`member/cash_out`, {params}) return request.get(`member/cash_out`, { params })
} }
/** /**
@ -357,15 +357,38 @@ export function getCashOutDetail(id: number) {
* @param params * @param params
*/ */
export function memberAudit(params: Record<string, any>) { export function memberAudit(params: Record<string, any>) {
return request.put(`member/cash_out/audit/${params.id}/${params.action}`, params, {showSuccessMessage: true}) return request.put(`member/cash_out/audit/${params.id}/${params.action}`, params, { showSuccessMessage: true })
} }
/**
*
* @param params
*/
export function memberCancel(params: Record<string, any>) {
return request.put(`member/cash_out/cancel/${params.id}`, params, { showSuccessMessage: true,showErrorMessage: true })
}
/** /**
* *
* @param params * @param params
*/ */
export function memberTransfer(params: Record<string, any>) { export function memberTransfer(params: Record<string, any>) {
return request.put(`member/cash_out/transfer/${params.id}`, params, {showSuccessMessage: true}) return request.put(`member/cash_out/transfer/${params.id}`, params, { showSuccessMessage: true })
}
/**
*
* @param params
*/
export function memberRemark(params: Record<string, any>) {
return request.put(`member/cash_out/remark/${params.id}`, params, { showSuccessMessage: true })
}
/**
*
* @param params
*/
export function memberCheck(id: number) {
return request.put(`member/cash_out/check/${id}`, {}, { showSuccessMessage: true })
} }
/** /**
@ -373,7 +396,7 @@ export function memberTransfer(params: Record<string, any>) {
* @param params * @param params
*/ */
export function editMemberStatus(params: Record<string, any>) { export function editMemberStatus(params: Record<string, any>) {
return request.put(`member/setstatus/${params.status}`, params, {showSuccessMessage: true}) return request.put(`member/setstatus/${params.status}`, params, { showSuccessMessage: true })
} }
/** /**
@ -422,7 +445,6 @@ export function getGrowthRuleDict() {
export function getPointRuleDict() { export function getPointRuleDict() {
return request.get(`member/dict/point_rule`) return request.get(`member/dict/point_rule`)
} }
/***************************************************** 会员等级 ****************************************************/ /***************************************************** 会员等级 ****************************************************/
/** /**
@ -431,7 +453,7 @@ export function getPointRuleDict() {
* @returns * @returns
*/ */
export function getMemberLevelPageList(params: Record<string, any>) { export function getMemberLevelPageList(params: Record<string, any>) {
return request.get(`member/level`, {params}) return request.get(`member/level`, { params })
} }
/** /**
@ -449,7 +471,7 @@ export function getMemberLevelInfo(level_id: number) {
* @returns * @returns
*/ */
export function addMemberLevel(params: Record<string, any>) { export function addMemberLevel(params: Record<string, any>) {
return request.post('member/level', params, {showSuccessMessage: true}) return request.post('member/level', params, { showSuccessMessage: true })
} }
/** /**
@ -457,7 +479,7 @@ export function addMemberLevel(params: Record<string, any>) {
* @param params * @param params
*/ */
export function updateMemberLevel(params: Record<string, any>) { export function updateMemberLevel(params: Record<string, any>) {
return request.put(`member/level/${params.level_id}`, params, {showSuccessMessage: true}) return request.put(`member/level/${params.level_id}`, params, { showSuccessMessage: true })
} }
/** /**
@ -466,7 +488,7 @@ export function updateMemberLevel(params: Record<string, any>) {
* @returns * @returns
*/ */
export function deleteMemberLevel(level_id: number) { export function deleteMemberLevel(level_id: number) {
return request.delete(`member/level/${level_id}`, {showSuccessMessage: true}) return request.delete(`member/level/${level_id}`, { showSuccessMessage: true })
} }
/** /**
@ -489,7 +511,7 @@ export function getMemberBenefitsContent() {
* *
*/ */
export function getMemberGiftsContent(params: Record<string, any>) { export function getMemberGiftsContent(params: Record<string, any>) {
return request.post(`member/gifts/content`, params); return request.post(`member/gifts/content`, params );
} }
/** /**
@ -505,14 +527,14 @@ export function getSignConfig() {
* @returns * @returns
*/ */
export function setSignConfig(params: Record<string, any>) { export function setSignConfig(params: Record<string, any>) {
return request.put(`member/sign/config`, params, {showSuccessMessage: true}) return request.put(`member/sign/config`, params, { showSuccessMessage: true })
} }
/** /**
* *
*/ */
export function getMemberSignList(params: Record<string, any>) { export function getMemberSignList(params: Record<string, any>) {
return request.get(`member/sign`, {params}); return request.get(`member/sign`, { params });
} }
/***************************************************** 地址管理 ****************************************************/ /***************************************************** 地址管理 ****************************************************/
@ -521,11 +543,11 @@ export function getMemberSignList(params: Record<string, any>) {
* *
*/ */
export function getMemberAddress(params: Record<string, any>) { export function getMemberAddress(params: Record<string, any>) {
return request.get(`member/address`, {params}); return request.get(`member/address`, { params });
} }
/** /**
* *
*/ */
export function addMemberAddress(params: Record<string, any>) { export function addMemberAddress(params: Record<string, any>) {
return request.post(`member/address`, params); return request.post(`member/address`, params);

View File

@ -98,3 +98,24 @@ export function pay(params: Record<string, any>) {
export function getFriendsPay(tradeType: string, tradeId: number, channel: string) { export function getFriendsPay(tradeType: string, tradeId: number, channel: string) {
return request.get(`pay/friendspay/info/${tradeType}/${tradeId}/${channel}`, {showErrorMessage: false}) return request.get(`pay/friendspay/info/${tradeType}/${tradeId}/${channel}`, {showErrorMessage: false})
} }
/**
*
*/
export function getTransferScene() {
return request.get(`pay/transfer_scene`)
}
/**
* id
*/
export function setSceneId(params: Record<string, any>) {
return request.post(`pay/transfer_scene/set_scene_id/${params.scene}`, params, { showSuccessMessage: true })
}
/**
*
*/
export function setTradeScene(params: Record<string, any>) {
return request.post(`pay/transfer_scene/set_trade_scene/${params.type}`, params)
}

View File

@ -42,8 +42,8 @@ export function getAuthorizationResult(params: Record<string, any>) {
* *
* @returns * @returns
*/ */
export function weappCommit() { export function weappCommit(params: Record<string, any>) {
return request.post('wxoplatform/weapp/version/commit', {}, { showSuccessMessage: true }) return request.post('wxoplatform/weapp/version/commit', params, { showSuccessMessage: true })
} }
/** /**
@ -67,3 +67,11 @@ export function getWeappLastCommitRecord() {
export function siteWeappCommit() { export function siteWeappCommit() {
return request.post('wxoplatform/site/weapp/commit', {}, { showSuccessMessage: true }) return request.post('wxoplatform/site/weapp/commit', {}, { showSuccessMessage: true })
} }
/**
*
*/
export function getSiteGroupCommitRecord(params: Record<string, any>) {
return request.get('wxoplatform/sitegroup/commit', { params })
}

View File

@ -41,10 +41,26 @@
"cashOutMoney": "转账金额", "cashOutMoney": "转账金额",
"auditTime": "审核时间", "auditTime": "审核时间",
"transferTime": "转账时间", "transferTime": "转账时间",
"memberInfoPlaceholder": "请输入会员名称/会员昵称/手机号", "memberInfoPlaceholder": "请输入会员编号/昵称/手机号搜索",
"cashOutNumber": "提现单号", "cashOutNumber": "提现单号",
"cashOutNumberPlaceholder": "请输入提现单号", "cashOutNumberPlaceholder": "请输入提现单号",
"alipayAccount": "支付宝账号", "alipayAccount": "支付宝账号",
"bankName": "银行名称", "bankName": "银行名称",
"bankAccount": "银行卡号" "bankAccount": "银行卡号",
"cashOutInfo":"收款方信息",
"transferCode":"收款码",
"realname":"真实姓名",
"account":"账号",
"bankRealname":"持卡人姓名",
"remark":"备注",
"remarkPlaceholder":"请输入备注",
"passAudit":"通过审核",
"transferVoucher":"转账凭证",
"transferVoucherPlaceholder":"请上传转账凭证",
"transferRemark":"转账补充说明",
"transferRemarkPlaceholder":"请输入转账补充说明",
"notes":"备注",
"check":"检查打款进度",
"cancelWithdrawal":"取消",
"cancelTips":"确定要取消提现吗?"
} }

View File

@ -14,5 +14,8 @@
"automatedTransit": "自动转账", "automatedTransit": "自动转账",
"manualTransfer": "手动转账", "manualTransfer": "手动转账",
"wechat": "微信", "wechat": "微信",
"alipay": "支付宝" "alipay": "支付宝",
"minTips":"注意微信零钱最低提现金额为0.1",
"transferTips":"只有微信零钱支持自动转账,微信零钱可能会遇到资金不足、超过当日转账上限等因素的情况下会导致转账失败,停留在待转账状态下,需要管理员手动在后台操作",
"transferModeTips":"仅有微信零钱这一种转账方式支持线上打款,其余转账方式皆只支持线下打款"
} }

View File

@ -27,5 +27,8 @@
"appPublicCertPathTips": "上传appCertPublicKey文件", "appPublicCertPathTips": "上传appCertPublicKey文件",
"alipayPublicCertPathTips": "上传alipayCertPublicKey文件", "alipayPublicCertPathTips": "上传alipayCertPublicKey文件",
"alipayRootCertPathTips": "上传alipayRootCert文件", "alipayRootCertPathTips": "上传alipayRootCert文件",
"operationTip": "温馨提示:打款设置用于会员提现转账,发放红包等场景" "operationTip": "温馨提示:打款设置用于会员提现转账,发放红包等场景",
"transferTips":"注意:应微信方规定,在2025年1月15日前开通商家转账到零钱服务的商户号可正常使用转账功能,之后开通的不支持使用转账到零钱服务",
"wechatpayPublicCert": "微信支付公钥",
"wechatpayPublicCertId": "微信支付公钥ID"
} }

View File

@ -0,0 +1,10 @@
{
"transferSceneId":"转账场景ID",
"transferType":"业务类型",
"recvPerception":"收款感知",
"recvPerceptionTips":"请选择收款感知",
"reportInfos":"报备背景",
"operation":"操作",
"deploy":"配置",
"noData":"暂无数据"
}

View File

@ -6,6 +6,9 @@
"createTime": "提交时间", "createTime": "提交时间",
"userVersion": "版本号", "userVersion": "版本号",
"failReason": "失败原因", "failReason": "失败原因",
"updateTips": "版本提交成功之后会自动给已授权的小程序进行同步更新,使用该功能必须要启动消息队列", "updateTips": "1、同步小程序时系统通过已绑定的开发小程序同步至微信第三方平台的普通模板库中。\n 2、同步完成后系统将自动为站点套餐下已授权的小程序提交代码。\n 3、一键同步功能支持按所有站点套餐进行批量同步同时也可针对单个站点套餐单独操作。\n 4、使用此功能前请确保已启动消息队列服务。",
"seeUpdateRecord": "查看同步记录" "seeUpdateRecord": "查看同步记录",
"commitRecord": "同步记录",
"oneClickSync": "一键同步",
"syncTemplateError": "未能同步到模板库"
} }

View File

@ -51,7 +51,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item :label="t('tradeNo')" prop="trade_no"> <el-form-item :label="t('tradeNo')" prop="trade_no">
<el-input v-model="siteAccountLogTable.searchParam.trade_no" :placeholder="t('tradeNoPlaceholder')" /> <el-input v-model.trim="siteAccountLogTable.searchParam.trade_no" :placeholder="t('tradeNoPlaceholder')" />
</el-form-item> </el-form-item>
<el-form-item :label="t('createTime')" prop="create_time"> <el-form-item :label="t('createTime')" prop="create_time">
<el-date-picker v-model="siteAccountLogTable.searchParam.create_time" type="datetimerange" <el-date-picker v-model="siteAccountLogTable.searchParam.create_time" type="datetimerange"

View File

@ -40,12 +40,12 @@
:end-placeholder="t('endDate')" /> :end-placeholder="t('endDate')" />
</el-form-item> </el-form-item>
<el-form-item :label="t('cashOutNumber')" prop="cash_out_no"> <el-form-item :label="t('cashOutNumber')" prop="cash_out_no">
<el-input v-model="orderTableData.searchParam.cash_out_no" class="w-[240px]" <el-input v-model.trim="orderTableData.searchParam.cash_out_no" class="w-[240px]"
:placeholder="t('cashOutNumberPlaceholder')" /> :placeholder="t('cashOutNumberPlaceholder')" />
</el-form-item> </el-form-item>
<el-form-item :label="t('memberInfo')" prop="keyword"> <el-form-item :label="t('memberInfo')" prop="keywords">
<el-input v-model="orderTableData.searchParam.keyword" class="w-[240px]" <el-input v-model.trim="orderTableData.searchParam.keywords" class="w-[240px]"
:placeholder="t('memberInfoPlaceholder')" /> :placeholder="t('memberInfoPlaceholder')" />
</el-form-item> </el-form-item>
@ -80,64 +80,124 @@
</el-card> </el-card>
<div class="mt-[10px]"> <div class="mt-[10px]">
<el-table :data="orderTableData.data" size="large" v-loading="orderTableData.loading"> <el-table :data="orderTableData.data" size="large" class="table-top">
<template #empty> <el-table-column :label="t('memberInfo')" min-width="180" />
<span>{{ !orderTableData.loading ? t('emptyData') : '' }}</span> <el-table-column :label="t('cashOutMethod')" align="center" min-width="100" />
</template> <el-table-column :label="t('cashOutInfo')" min-width="180" />
<el-table-column :label="t('applicationForWithdrawalAmount')" align="center" min-width="120" />
<el-table-column :label="t('actualTransferAmount')" align="center" min-width="120" />
<el-table-column :label="t('cashOutCommission')" align="center" min-width="110" />
<el-table-column :label="t('cashOutStatus')" align="center" min-width="150" />
<el-table-column :label="t('applyTime')" align="center" min-width="160" />
<el-table-column :label="t('auditTime')" align="center" min-width="160" />
<el-table-column :label="t('transferTime')" align="center" min-width="160" />
<el-table-column :label="t('operation')" fixed="right" align="right" min-width="120" />
</el-table>
<div class="table-body min-h-[150px]" v-loading="orderTableData.loading">
<div v-if="!orderTableData.loading">
<template v-if="orderTableData.data.length">
<div v-for="(item, index) in orderTableData.data" :key="index">
<el-table :data="[item]" size="large" :show-header="false">
<el-table-column :show-overflow-tooltip="true" min-width="180">
<template #default="{ row }">
<div class="flex items-center cursor-pointer " @click="toMember(row.member.member_id)">
<img class="w-[50px] h-[50px] mr-[10px]" v-if="row.member.headimg" :src="img(row.member.headimg)" alt="">
<img class="w-[50px] h-[50px] mr-[10px] rounded-full" v-else src="@/app/assets/images/member_head.png" alt="">
<div class="flex flex-col items-baseline" style="width: calc(100% - 60px);">
<span class="w-[100%] truncate text-left">{{ row.member.nickname || row.member.username || '' }}</span>
<span class="w-[100%] truncate">{{ row.member.mobile || '' }}</span>
</div>
</div>
</template>
</el-table-column>
<el-table-column align="center" min-width="100">
<template #default="{ row }">
{{ row.transfer_type_name }}
</template>
</el-table-column>
<el-table-column min-width="180">
<template #default="{ row }">
<div class="flex flex-col" v-if="row.transfer_type=='wechat_code' || row.transfer_type=='alipay'">
<div class="flex items-center">
<span class="w-[70px] flex-shrink-0 text-right">{{t('realname') }}</span>
<span class="using-hidden">{{ row.transfer_realname }}</span>
</div>
<div class="flex items-center">
<span class="w-[70px] flex-shrink-0 text-right">{{t('account') }}</span>
<span>{{ row.transfer_account }}</span>
</div>
<div class="flex items-center" v-if="row.transfer_payment_code">
<span class="w-[70px] flex-shrink-0 text-right">{{ t('transferCode') }}</span>
<el-image :src="img(row.transfer_payment_code)" :preview-src-list="[img(row.transfer_payment_code)]" :hide-on-click-modal="true" class="w-[50px] h-[50px]"></el-image>
</div>
</div>
<div class="flex flex-col" v-else-if="row.transfer_type=='bank'">
<span>{{t('bankRealname') }}{{ row.transfer_realname }}</span>
<span>{{ t('bankAccount') }}{{ row.transfer_account }}</span>
<span>{{ t('bankName') }}{{ row.transfer_bank }}</span>
</div>
<div class="flex items-center" v-else-if="row.transfer_type=='wechatpay'">
<img class="w-[50px] h-[50px] mr-[10px]" v-if="row.member.headimg" :src="img(row.member.headimg)" alt="">
<img class="w-[50px] h-[50px] mr-[10px] rounded-full" v-else src="@/app/assets/images/member_head.png" alt="">
<div class="flex flex-col items-baseline" style="width: calc(100% - 60px);">
<span class="w-[100%] truncate text-left">{{ row.member.nickname || row.member.username || '' }}</span>
<span class="w-[100%] truncate">{{ row.member.mobile || '' }}</span>
</div>
</div>
</template>
</el-table-column>
<el-table-column prop="apply_money" min-width="120" align="center" />
<el-table-column prop="order_no" :show-overflow-tooltip="true" :label="t('memberInfo')" align="center" min-width="140"> <el-table-column prop="money" min-width="120" align="center" />
<template #default="{ row }">
<div class="flex items-center cursor-pointer " @click="toMember(row.member.member_id)"> <el-table-column prop="service_money" align="center" min-width="110" />
<img class="w-[50px] h-[50px] mr-[10px]" v-if="row.member.headimg" :src="img(row.member.headimg)" alt="">
<img class="w-[50px] h-[50px] mr-[10px]" v-else src="@/app/assets/images/default_headimg.png" alt=""> <el-table-column prop="status_name" align="center" min-width="150">
<div class="flex flex flex-col"> <template #default="{ row }">
<span>{{ row.member.nickname || '' }}</span> <div>{{ row.status_name }}</div>
<span>{{ row.member.mobile || '' }}</span> <div v-if="row.status == 2 && row.transfer_type == 'wechatpay'" class="text-[12px] text-[var(--el-color-success)]">(等待用户收款)</div>
</div> </template>
</el-table-column>
<el-table-column min-width="160" align="center">
<template #default="{ row }">
{{ row.create_time || '' }}
</template>
</el-table-column>
<el-table-column min-width="160" align="center">
<template #default="{ row }">
{{ row.audit_time || '' }}
</template>
</el-table-column>
<el-table-column min-width="160" align="center">
<template #default="{ row }">
{{ row.transfer_time || '' }}
</template>
</el-table-column>
<el-table-column align="right" fixed="right" width="120">
<template #default="{ row }">
<el-button type="primary" link @click="successfulAuditFn(row)" v-if="row.status == 1"> {{ t('successfulAudit') }}</el-button>
<el-button type="primary" link @click="auditFailureFn(row)" v-if="row.status == 1"> {{ t('auditFailure') }}</el-button>
<el-button type="primary" link @click="memberCancelFn(row)" v-if="row.status == 1 || row.status == 2 || row.status == 4"> {{ t('cancelWithdrawal') }}</el-button>
<el-button type="primary" link @click="transferFn(row)" v-if="row.status == 2 && row.transfer_type !== 'wechatpay'"> {{ t('transfer') }}</el-button>
<el-button type="primary" link @click="detailFn(row.id)"> {{ t('detail') }}</el-button>
<el-button type="primary" link @click="handleRemark(row)"> {{ t('remark') }}</el-button>
</template>
</el-table-column>
</el-table>
<div v-if="item.remark" class="text-[14px] min-h-[30px] leading-[30px] px-3 bg-[#fff0e5] text-[#ff7f5b] mb-[10px] relative remark">
<span class="mr-[5px]">{{ t('notes') }}</span>
<span>{{ item.remark }}</span>
</div>
</div> </div>
</template> </template>
</el-table-column> <el-empty v-else :image-size="1" :description="t('emptyData')" />
<el-table-column :label="t('cashOutMethod')" align="center" min-width="140"> </div>
<template #default="{ row }"> </div>
{{ row.transfer_type_name }}
</template>
</el-table-column>
<el-table-column prop="apply_money" :label="t('applicationForWithdrawalAmount')" min-width="140" align="center" />
<el-table-column prop="money" :label="t('actualTransferAmount')" min-width="200" align="center" />
<el-table-column prop="service_money" :label="t('cashOutCommission')" align="center" min-width="140" />
<el-table-column prop="status_name" :label="t('cashOutStatus')" align="center" min-width="100" />
<el-table-column :label="t('applyTime')" min-width="180" align="center">
<template #default="{ row }">
{{ row.create_time || '' }}
</template>
</el-table-column>
<el-table-column :label="t('auditTime')" min-width="180" align="center">
<template #default="{ row }">
{{ row.audit_time || '' }}
</template>
</el-table-column>
<el-table-column :label="t('transferTime')" min-width="180" align="center">
<template #default="{ row }">
{{ row.transfer_time || '' }}
</template>
</el-table-column>
<el-table-column :label="t('operation')" align="right" fixed="right" width="230">
<template #default="{ row }">
<el-button v-for="(item, index) in operationBtn[row.status.toString()].value" :key="index + 'a'"
@click="fnProcessing(operationBtn[row.status.toString()].clickArr[index], row)"
type="primary" link>{{ item }}</el-button>
</template>
</el-table-column>
</el-table>
<div class="mt-[16px] flex justify-end"> <div class="mt-[16px] flex justify-end">
<el-pagination v-model:current-page="orderTableData.page" v-model:page-size="orderTableData.limit" <el-pagination v-model:current-page="orderTableData.page" v-model:page-size="orderTableData.limit"
layout="total, sizes, prev, pager, next, jumper" :total="orderTableData.total" layout="total, sizes, prev, pager, next, jumper" :total="orderTableData.total"
@ -147,29 +207,104 @@
</el-card> </el-card>
<!-- 详情 --> <!-- 详情 -->
<el-dialog v-model="cashOutShowDialog" :title="t('cashOutDetail')" width="500px" :destroy-on-close="true"> <el-dialog v-model="cashOutShowDialog" :title="t('cashOutDetail')" width="650px" :destroy-on-close="true">
<el-form :model="cashOutInfo" label-width="120px" ref="formRef" :rules="formRules" class="page-form" v-loading="cashOutLoading"> <el-form :model="cashOutInfo" label-width="120px" ref="formRef" class="page-form" v-loading="cashOutLoading">
<el-form-item :label="t('nickname')"> <el-row>
<div class="input-width"> {{ cashOutInfo.nickname }} </div> <el-col :span="12">
</el-form-item> <el-form-item :label="t('nickname')">
<el-form-item :label="t('cashOutAccountType')"> <div class="input-width"> {{ cashOutInfo.nickname|| cashOutInfo.username }} </div>
<div class="input-width"> {{ cashOutInfo.account_type_name }} </div> </el-form-item>
</el-form-item> </el-col>
<el-form-item :label="t('cashOutMethod')"> <el-col :span="12">
<div class="input-width"> {{ Transfertype[cashOutInfo.transfer_type].name }} </div> <el-form-item :label="t('cashOutAccountType')">
</el-form-item> <div class="input-width"> {{ cashOutInfo.account_type_name }} </div>
<el-form-item :label="t('applicationForWithdrawalAmount')"> </el-form-item>
<div class="input-width"> {{ cashOutInfo.apply_money }} </div> </el-col>
</el-form-item> <el-col :span="12">
<el-form-item :label="t('cashOutCommission')"> <el-form-item :label="t('cashOutMethod')">
<div class="input-width"> {{ cashOutInfo.service_money }} </div> <div class="input-width"> {{ Transfertype[cashOutInfo.transfer_type].name }} </div>
</el-form-item> </el-form-item>
<el-form-item :label="t('actualTransferAmount')"> </el-col>
<div class="input-width"> {{ cashOutInfo.money }} </div> <template v-if="cashOutInfo.transfer_type == 'alipay' || cashOutInfo.transfer_type == 'wechat_code'">
</el-form-item> <el-col :span="12">
<el-form-item :label="t('cashOutStatus')"> <el-form-item :label="t('realname')">
<div class="input-width"> {{ cashOutInfo.status_name }} </div> <div class="input-width"> {{ cashOutInfo.transfer_realname }} </div>
</el-form-item> </el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('alipayAccount')">
<div class="input-width"> {{ cashOutInfo.transfer_account }} </div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('transferCode')">
<el-image :src="img(cashOutInfo.transfer_payment_code)" :preview-src-list="[img(cashOutInfo.transfer_payment_code)]" :hide-on-click-modal="true" class="mr-[10px] w-[50px] h-[50px]"></el-image>
</el-form-item>
</el-col>
</template>
<template v-if="cashOutInfo.transfer_type == 'bank'">
<el-col :span="12">
<el-form-item :label="t('bankName')">
<div class="input-width"> {{ cashOutInfo.transfer_bank }} </div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('bankAccount')">
<div class="input-width"> {{ cashOutInfo.transfer_account }} </div>
</el-form-item>
</el-col>
</template>
<el-col :span="12">
<el-form-item :label="t('applicationForWithdrawalAmount')">
<div class="input-width"> {{ cashOutInfo.apply_money }} </div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('cashOutCommission')">
<div class="input-width"> {{ cashOutInfo.service_money }} </div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('actualTransferAmount')">
<div class="input-width"> {{ cashOutInfo.money }} </div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('cashOutStatus')">
<div class="input-width"> {{ cashOutInfo.status_name }} </div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('applyTime')">
<div class="input-width"> {{ cashOutInfo.create_time }} </div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('auditTime')">
<div class="input-width"> {{ cashOutInfo.audit_time }} </div>
</el-form-item>
</el-col>
<el-col :span="12" v-if="cashOutInfo.remark">
<el-form-item :label="t('remark')">
<div class="input-width"> {{ cashOutInfo.remark }} </div>
</el-form-item>
</el-col>
<el-col :span="12" v-if="cashOutInfo.transfer && cashOutInfo.transfer.transfer_voucher">
<el-form-item :label="t('transferVoucher')">
<el-image :src="img(cashOutInfo.transfer.transfer_voucher)" :preview-src-list="[img(cashOutInfo.transfer.transfer_voucher)]" :hide-on-click-modal="true" class="w-[50px] h-[50px]"></el-image>
</el-form-item>
</el-col>
<el-col :span="12" v-if="cashOutInfo.transfer && cashOutInfo.transfer.transfer_remark">
<el-form-item :label="t('transferRemark')">
<div class="input-width"> {{ cashOutInfo.transfer.transfer_remark }} </div>
</el-form-item>
</el-col>
<el-col :span="12" v-if="cashOutInfo.refuse_reason">
<el-form-item :label="t('remark')">
<div class="input-width"> {{ cashOutInfo.refuse_reason }} </div>
</el-form-item>
</el-col>
</el-row>
</el-form> </el-form>
<template #footer> <template #footer>
@ -178,12 +313,93 @@
</span> </span>
</template> </template>
</el-dialog> </el-dialog>
<!-- 审核通过 -->
<!-- 是否审核 --> <el-dialog v-model="auditPassShowDialog" :title="t('passAudit')" width="650px" :destroy-on-close="true">
<el-form :model="curData" label-width="120px" ref="formRef" class="page-form">
<el-row>
<el-col :span="12">
<el-form-item :label="t('nickname')">
<div class="input-width"> {{ curData.member.nickname ||curData.member.username }} </div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('cashOutAccountType')">
<div class="input-width"> {{ curData.account_type_name }} </div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('cashOutMethod')">
<div class="input-width"> {{ curData.transfer_type_name }} </div>
</el-form-item>
</el-col>
<template v-if="curData.transfer_type == 'alipay' || curData.transfer_type == 'wechat_code'">
<el-col :span="12">
<el-form-item :label="t('realname')">
<div class="input-width"> {{ curData.transfer_realname }} </div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('account')">
<div class="input-width"> {{ curData.transfer_account }} </div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('transferCode')">
<el-image :src="img(curData.transfer_payment_code)" :preview-src-list="[img(curData.transfer_payment_code)]" :hide-on-click-modal="true" class="w-[50px] h-[50px]"></el-image>
</el-form-item>
</el-col>
</template>
<template v-if="curData.transfer_type == 'bank'">
<el-col :span="12">
<el-form-item :label="t('bankName')">
<div class="input-width"> {{ curData.transfer_bank }} </div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('bankRealname')">
<div class="input-width"> {{ curData.transfer_realname }} </div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('bankAccount')">
<div class="input-width"> {{ curData.transfer_account }} </div>
</el-form-item>
</el-col>
</template>
<el-col :span="12">
<el-form-item :label="t('applicationForWithdrawalAmount')">
<div class="input-width"> {{ curData.apply_money }} </div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('cashOutCommission')">
<div class="input-width"> {{ curData.service_money }} </div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('actualTransferAmount')">
<div class="input-width"> {{ curData.money }} </div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('applyTime')">
<div class="input-width"> {{ curData.create_time }} </div>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="auditPassShowDialog = false">{{ t('cancel') }}</el-button>
<el-button type="primary" @click="handlePass()">{{ t('confirm') }}</el-button>
</span>
</template>
</el-dialog>
<!-- 是否审核拒绝 -->
<el-dialog v-model="auditShowDialog" :title="t('rejectionAudit')" width="500px" :destroy-on-close="true"> <el-dialog v-model="auditShowDialog" :title="t('rejectionAudit')" width="500px" :destroy-on-close="true">
<el-form :model="auditFailure" label-width="90px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading"> <el-form :model="auditFailure" label-width="90px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
<el-form-item :label="t('reasonsRefusal')" prop="label_name"> <el-form-item :label="t('reasonsRefusal')" prop="refuse_reason">
<el-input v-model="auditFailure.refuse_reason" clearable maxlength="200" :show-word-limit="true" :placeholder="t('reasonsRefusalPlaceholder')" :rows="4" class="input-width" type="textarea" /> <el-input v-model.trim="auditFailure.refuse_reason" clearable maxlength="200" :show-word-limit="true" :placeholder="t('reasonsRefusalPlaceholder')" :rows="4" class="input-width" type="textarea" />
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
@ -195,12 +411,88 @@
</el-dialog> </el-dialog>
<!-- 是否转账 --> <!-- 是否转账 -->
<el-dialog v-model="transferShowDialog" :title="t('rejectionAudit')" width="500px" :destroy-on-close="true"> <el-dialog v-model="transferShowDialog" :title="t('transfer')" width="650px" :destroy-on-close="true">
<p>{{ t('isTransfer') }}</p> <el-form :model="transferData" label-width="120px" ref="formRef" class="page-form">
<el-row>
<template v-if="transferData.transfer_type == 'alipay' || transferData.transfer_type == 'wechat_code'">
<el-col :span="12">
<el-form-item :label="t('realname')">
<div class="input-width"> {{ transferData.transfer_realname }} </div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('account')">
<div class="input-width"> {{ transferData.transfer_account }} </div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('transferCode')">
<el-image :src="img(transferData.transfer_payment_code)" :preview-src-list="[img(transferData.transfer_payment_code)]" :hide-on-click-modal="true" class="w-[50px] h-[50px]"></el-image>
</el-form-item>
</el-col>
</template>
<template v-if="transferData.transfer_type == 'bank'">
<el-col :span="12">
<el-form-item :label="t('bankName')">
<div class="input-width"> {{ transferData.transfer_bank }} </div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('bankRealname')">
<div class="input-width"> {{ transferData.transfer_realname }} </div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('bankAccount')">
<div class="input-width"> {{ transferData.transfer_account }} </div>
</el-form-item>
</el-col>
</template>
<el-col :span="12">
<el-form-item :label="t('applicationForWithdrawalAmount')">
<div class="input-width"> {{ transferData.apply_money }} </div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('cashOutCommission')">
<div class="input-width"> {{ transferData.service_money }} </div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('actualTransferAmount')">
<div class="input-width"> {{ transferData.money }} </div>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-form :model="formTransfer" label-width="120px" ref="formTransferRef" :rules="formTransferRules" class="page-form">
<el-form-item :label="t('transferVoucher')" prop="transfer_voucher">
<upload-image v-model="formTransfer.transfer_voucher" :limit="1" />
</el-form-item>
<el-form-item :label="t('transferRemark')" prop="transfer_remark">
<el-input v-model.trim="formTransfer.transfer_remark" type="textarea" rows="4" clearable
:placeholder="t('transferRemarkPlaceholder')" class="input-width" maxlength="200" show-word-limit />
</el-form-item>
</el-form>
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer">
<el-button @click="transferShowDialog = false">{{ t('cancel') }}</el-button> <el-button @click="transferShowDialog = false">{{ t('cancel') }}</el-button>
<el-button type="primary" @click="confirm()">{{ t('confirm') }}</el-button> <el-button type="primary" @click="handleTransfer(formTransferRef)">{{ t('confirm') }}</el-button>
</span>
</template>
</el-dialog>
<!-- 备注 -->
<el-dialog v-model="remarkShowDialog" :title="t('remark')" width="500px" :destroy-on-close="true">
<el-form :model="formData" label-width="90px" ref="formRemarkRef" :rules="formRemarkRules" class="page-form">
<el-form-item :label="t('remark')" prop="remark">
<el-input v-model.trim="formData.remark" type="textarea" rows="4" clearable
:placeholder="t('remarkPlaceholder')" class="input-width" maxlength="200" show-word-limit />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="remarkShowDialog = false">{{ t('cancel') }}</el-button>
<el-button type="primary" @click="save(formRemarkRef)">{{ t('confirm') }}</el-button>
</span> </span>
</template> </template>
</el-dialog> </el-dialog>
@ -208,45 +500,21 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { reactive, ref } from 'vue' import { reactive, ref, computed } from 'vue'
import { t } from '@/lang' import { t } from '@/lang'
import { getCashOutList, getTransfertype, memberTransfer, memberAudit, getCashOutDetail, getCashOutStatusList, getCashOutStat } from '@/app/api/member' import { getCashOutList, getTransfertype, memberTransfer, memberAudit, getCashOutDetail, getCashOutStatusList, getCashOutStat, memberRemark, memberCheck, memberCancel } from '@/app/api/member'
import { img } from '@/utils/common' import { img } from '@/utils/common'
import { ElMessageBox, FormInstance, FormRules } from 'element-plus' import { ElMessageBox, FormInstance, FormRules } from 'element-plus'
import { useRouter, useRoute } from 'vue-router' import { useRouter, useRoute } from 'vue-router'
import { AnyObject } from '@/types/global'
const cashOutStatusList = ref([]) const cashOutStatusList = ref([])
const checkStatusList = async () => { const checkStatusList = async () => {
cashOutStatusList.value = await (await getCashOutStatusList()).data cashOutStatusList.value = await (await getCashOutStatusList()).data
} }
checkStatusList() checkStatusList()
const transferShowDialog = ref(false)
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
const pageName = route.meta.title const pageName = route.meta.title
const operationBtn = ref<AnyObject>({
1: {
value: [t('successfulAudit'), t('auditFailure'), t('detail')],
clickArr: ['successfulAuditFn', 'auditFailureFn', 'detailFn']
},
2: {
value: [t('transfer'), t('detail')],
clickArr: ['transferFn', 'detailFn']
},
3: {
value: [t('detail')],
clickArr: ['detailFn']
},
'-1': {
value: [t('detail')],
clickArr: ['detailFn']
},
'-2': {
value: [t('detail')],
clickArr: ['detailFn']
}
})
// //
const formRules = reactive<FormRules>({}) const formRules = reactive<FormRules>({})
@ -263,7 +531,7 @@ const orderTableData = reactive({
create_time: [], create_time: [],
status: '', status: '',
cash_out_no: '', cash_out_no: '',
keyword: '', keywords: '',
audit_time: '', audit_time: '',
transfer_time: '', transfer_time: '',
transfer_type: '' transfer_type: ''
@ -317,43 +585,43 @@ const loadOrderList = (page: number = 1) => {
} }
loadOrderList() loadOrderList()
//
const auditFailure = ref({ refuse_reason: '', id: 0, action: 0 })
const auditShowDialog = ref(false)
const fnProcessing = (type: string, data: any) => {
const obj = {}
if (['successfulAuditFn', 'auditFailureFn'].includes(type)) {
obj.id = data.id
if (type == 'successfulAuditFn') {
obj.action = 'agree'
cashOutAuditFn(obj)
} else {
obj.action = 'refuse'
auditFailure.value = Object.assign(auditFailure.value, obj)
auditShowDialog.value = true
}
} else if (type == 'transferFn') {
obj.id = data.id
ElMessageBox.confirm(`${t('isTransfer')}`, `${t('transfer')}`)
.then(() => {
transferFn(obj)
})
} else {
detailFn(data.id)
}
}
/** /**
* 转账 * 转账
* @param data * @param data
*/ */
const transferFn = (data:any) => { const transferData = ref<any>({})
memberTransfer({ ...data }).then(res => { const transferShowDialog = ref(false)
auditFailure.value = { refuse_reason: '', id: 0, action: 0 } const formTransferRef = ref<FormInstance>()
loadOrderList() const formTransfer = reactive<any>({
id: 0,
transfer_voucher: '',
transfer_remark: ''
})
const formTransferRules = computed(() => {
return {
transfer_voucher: [
{ required: true, message: t('transferVoucherPlaceholder'), trigger: 'blur' }
]
}
})
}).catch(() => { const transferFn = (data:any) => {
loadOrderList() transferData.value = data
formTransfer.id = data.id
transferShowDialog.value = true
}
const handleTransfer = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate(async (valid) => {
if (valid) {
memberTransfer({ ...formTransfer }).then(res => {
transferShowDialog.value = false
loadOrderList()
}).catch(() => {
transferShowDialog.value = false
loadOrderList()
})
}
}) })
} }
@ -386,25 +654,108 @@ const detailFn = (id:any) => {
* 提现审核 * 提现审核
* @param data * @param data
*/ */
const cashOutAuditFn = (data:any) => {
memberAudit({
...data
}).then(res => {
loadOrderList()
}).catch(() => { const auditPassShowDialog = ref(false)
loadOrderList() const curData = ref<any>({})
})
//
const successfulAuditFn = (data: any) => {
curData.value = data
auditPassShowDialog.value = true
}
const handlePass = () => {
const obj = {
id: curData.value.id,
action: 'agree'
}
cashOutAuditFn(obj)
} }
/** /**
* 拒绝审核 * 拒绝审核
*/ */
const auditFailure = ref({ refuse_reason: '', id: 0, action: '' })
const auditShowDialog = ref(false)
const loading = ref(false)
const auditFailureFn = (data: any) => {
auditFailure.value.id = data.id
auditFailure.value.action = 'refuse'
auditShowDialog.value = true
}
const confirm = () => { const confirm = () => {
auditShowDialog.value = false auditShowDialog.value = false
cashOutAuditFn(auditFailure.value) cashOutAuditFn(auditFailure.value)
} }
const repeat = ref(false)
const cashOutAuditFn = (data:any) => {
if (repeat.value) return
repeat.value = true
memberAudit({
...data
}).then(res => {
repeat.value = false
auditPassShowDialog.value = false
loadOrderList()
}).catch(() => {
repeat.value = false
auditPassShowDialog.value = false
loadOrderList()
})
}
//
const memberCancelFn = (data: any) => {
ElMessageBox.confirm(t('cancelTips'), t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning'
}
).then(() => {
memberCancel({ id: data.id }).then((res) => {
loadOrderList()
})
})
}
/**
* 备注
*/
const formRemarkRef = ref<FormInstance>()
const remarkShowDialog = ref(false)
const formData = reactive({
id: 0,
remark: ''
})
const formRemarkRules = computed(() => {
return {
remark: [
{ required: true, message: t('remarkPlaceholder'), trigger: 'blur' }
]
}
})
const handleRemark = (data: any) => {
formData.id = data.id
formData.remark = ''
remarkShowDialog.value = true
}
const save = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate(async (valid) => {
if (valid) {
memberRemark(formData).then((res: any) => {
loadOrderList()
remarkShowDialog.value = false
}).catch(() => {
remarkShowDialog.value = false
})
}
})
}
/** /**
* 会员详情 * 会员详情
*/ */
@ -412,6 +763,30 @@ const toMember = (memberId: number) => {
router.push(`/member/detail?id=${memberId}`) router.push(`/member/detail?id=${memberId}`)
} }
//
const checkFn = (id: number) => {
memberCheck(id).then(res => {
})
}
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped>
.table-top :deep(.el-table__body-wrapper) {
display: none;
}
:deep(.el-table) {
--el-table-row-hover-bg-color: var(--el-transfer-border-color);
}
.remark{
&::after{
content: '';
border-bottom: solid 1px var(--el-border-color-light);
width: 100%;
position: absolute;
bottom: -10px;
left: 0;
}
}
</style>

View File

@ -0,0 +1,159 @@
<template>
<el-drawer v-model="showDialog" title="退款详情" direction="rtl" :before-close="handleClose" class="member-detail-drawer">
<div class="main-container" v-loading="loading">
<div class="relative" v-if="formData">
<div class="flex mb-[20px] justify-between text-[15px]">
<span>{{ t('refundMoney') }}<span>{{ formData.money }}</span></span>
<span>{{ t('refundNo') }}<span>{{ formData.refund_no }}</span></span>
</div>
<el-table :data="refundList" size="large">
<el-table-column prop="out_trade_no" :label="t('outTradeNo')" min-width="200" />
<el-table-column prop="create_time" :label="t('createTime')" min-width="160" />
<el-table-column prop="refund_type_name" :label="t('refundTypeName')" min-width="120" />
<el-table-column :label="t('refundMoney')" min-width="120">
<template #default="{ row }">
<span>{{ row.money }}</span>
</template>
</el-table-column>
<el-table-column prop="status_name" :label="t('statusName')" min-width="120" />
<el-table-column :label="t('operation')" fixed="right" align="right" min-width="120">
<template #default="{ row }">
<el-button type="primary" v-if="row.status == 'wait'" link @click="transferEvent(row)">{{ t('transfer') }}</el-button>
</template>
</el-table-column>
</el-table>
</div>
<el-dialog v-model="transferDialog" :title="title" width="500px" class="diy-dialog-wrap" :destroy-on-close="true">
<el-form :model="transferFormData" label-width="120px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
<el-form-item :label="t('transferType')">
<el-radio-group v-model="transferFormData.refund_type">
<el-radio :label="item.value" v-for="(item, index) in refundTypeData" :key="index">{{ item.name }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('refundMoney')">
<span>{{ transferFormData.refund_money }}</span>
</el-form-item>
<el-form-item :label="t('voucher')" v-if="transferFormData.refund_type == 'offline'">
<upload-image v-model="transferFormData.voucher" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="transferDialog = false">{{ t('cancel') }}</el-button>
<el-button type="primary" :loading="loading" @click="confirm(formRef)">{{ t('confirm') }}</el-button>
</span>
</template>
</el-dialog>
</div>
</el-drawer>
</template>
<script lang="ts" setup>
import { reactive, ref, computed } from 'vue'
import { t } from '@/lang'
import { getPayRefundInfo, getRefundType, getRefundTransfer } from '@/app/api/pay'
import { FormInstance, ElMessage } from 'element-plus'
import { useRouter, useRoute } from 'vue-router'
import { img, filterNumber } from '@/utils/common'
import useAppStore from '@/stores/modules/app'
const route = useRoute()
const router = useRouter()
let popTitle: string = '退款详情';
const showDialog = ref(false)
const loading = ref(false)
let refundNo = '';
const refundList = ref([])
const formData: Record<string, any> = ref(null)
const handleClose = (done: () => void) => {
showDialog.value = false;
}
/**
* 表单数据
*/
const formRef = ref<FormInstance>()
const setFormData = async (row: any = null) => {
refundNo = row.no;
getRefundListInfo(refundNo)
}
const getRefundListInfo = async (no) => {
loading.value = true
formData.value = null
refundList.value = [];
await getPayRefundInfo(no).then(({ data }) => {
formData.value = data
refundList.value.push(data)
})
loading.value = false
}
const refundTypeData = ref([])
getRefundType().then((data) => {
Object.keys(data.data).forEach((key: string) => {
refundTypeData.value.push({ value: key, name: data.data[key] })
})
})
const transferDialog = ref(false)
const transferEvent = (data:any) => {
transferDialog.value = true
transferFormData.refund_no = data.refund_no
transferFormData.refund_money = data.money
}
const initialFormData = {
refund_no: '',
refund_type: 'back',
voucher: '',
refund_money: 0.00
}
const transferFormData: Record<string, any> = reactive({ ...initialFormData })
//
const formRules = computed(() => {
return {
label_name: [
{ required: true, message: t('labelNamePlaceholder'), trigger: 'blur' }
]
}
})
const confirm = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
const data = transferFormData
getRefundTransfer(data).then(res => {
loading.value = false
transferDialog.value = false
refundList.value = []
getRefundListInfo(refundNo)
}).catch(() => {
transferDialog.value = false
loading.value = false
})
}
})
}
defineExpose({
showDialog,
setFormData
})
</script>
<style lang="scss">
.member-detail-drawer{
width: 1300px !important;
}
</style>

View File

@ -9,8 +9,7 @@
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never"> <el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
<el-form :inline="true" :model="payListTable.searchParam" ref="searchFormRef"> <el-form :inline="true" :model="payListTable.searchParam" ref="searchFormRef">
<el-form-item :label="t('outTradeNo')" prop="trade_no"> <el-form-item :label="t('outTradeNo')" prop="trade_no">
<el-input v-model="payListTable.searchParam.out_trade_no" <el-input v-model.trim="payListTable.searchParam.out_trade_no" :placeholder="t('outTradeNoPlaceholder')" />
:placeholder="t('outTradeNoPlaceholder')" />
</el-form-item> </el-form-item>
<el-form-item :label="t('createTime')" prop="create_time"> <el-form-item :label="t('createTime')" prop="create_time">
<el-date-picker v-model="payListTable.searchParam.create_time" type="datetimerange" <el-date-picker v-model="payListTable.searchParam.create_time" type="datetimerange"
@ -137,21 +136,17 @@ loadPayList()
const passEvent = (row: AnyObject) => { const passEvent = (row: AnyObject) => {
ElMessageBox.confirm( ElMessageBox.confirm(
t('passTips'), t('passTips'),
t('warning'), t('warning'),
{ {
confirmButtonText: t('confirm'), confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'), cancelButtonText: t('cancel'),
type: 'warning' type: 'warning'
} }
).then(({ value }) => { ).then(({ value }) => {
payAuditPass(row.out_trade_no) payAuditPass(row.out_trade_no).then(() => {
.then(() => { loadPayList()
loadPayList() })
})
.catch()
}).catch(() => {
}) })
} }
@ -163,13 +158,9 @@ const refuseEvent = (row: AnyObject) => {
inputPattern: /\S/, inputPattern: /\S/,
inputType: 'textarea' inputType: 'textarea'
}).then(({ value }) => { }).then(({ value }) => {
payAuditRefuse({ out_trade_no: row.out_trade_no, reason: value }) payAuditRefuse({ out_trade_no: row.out_trade_no, reason: value }).then(() => {
.then(() => { loadPayList()
loadPayList() })
})
.catch()
}).catch(() => {
}) })
} }

View File

@ -72,34 +72,26 @@ const formData: Record<string, any> | null = ref(null)
const setFormData = async () => { const setFormData = async () => {
loading.value = true loading.value = true
formData.value = null formData.value = null
await getPayDetail(id) await getPayDetail(id).then(({ data }) => {
.then(({ data }) => { formData.value = data
formData.value = data })
})
.catch(() => {
})
loading.value = false loading.value = false
} }
setFormData() setFormData()
const passEvent = () => { const passEvent = () => {
ElMessageBox.confirm( ElMessageBox.confirm(
t('passTips'), t('passTips'),
t('warning'), t('warning'),
{ {
confirmButtonText: t('confirm'), confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'), cancelButtonText: t('cancel'),
type: 'warning' type: 'warning'
} }
).then(({ value }) => { ).then(({ value }) => {
payAuditPass(formData.value.out_trade_no) payAuditPass(formData.value.out_trade_no).then(() => {
.then(() => { setFormData()
setFormData() })
})
.catch()
}).catch(() => {
}) })
} }
@ -113,9 +105,7 @@ const refuseEvent = () => {
}).then(({ value }) => { }).then(({ value }) => {
payAuditRefuse({ out_trade_no: formData.value.out_trade_no, reason: value }).then(() => { payAuditRefuse({ out_trade_no: formData.value.out_trade_no, reason: value }).then(() => {
setFormData() setFormData()
}).catch() })
}).catch(() => {
}) })
} }

View File

@ -10,7 +10,7 @@
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never"> <el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
<el-form :inline="true" :model="payRefundTable.searchParam" ref="searchFormRef"> <el-form :inline="true" :model="payRefundTable.searchParam" ref="searchFormRef">
<el-form-item :label="t('refundNo')" prop="refund_no"> <el-form-item :label="t('refundNo')" prop="refund_no">
<el-input v-model="payRefundTable.searchParam.refund_no" :placeholder="t('refundNoPlaceholder')" /> <el-input v-model.trim="payRefundTable.searchParam.refund_no" :placeholder="t('refundNoPlaceholder')" />
</el-form-item> </el-form-item>
<el-form-item :label="t('createTime')" prop="create_time"> <el-form-item :label="t('createTime')" prop="create_time">
<el-date-picker v-model="payRefundTable.searchParam.create_time" type="datetimerange" <el-date-picker v-model="payRefundTable.searchParam.create_time" type="datetimerange"
@ -49,6 +49,7 @@
</div> </div>
</div> </div>
</el-card> </el-card>
<refund-detail ref="refundDetailDialog"></refund-detail>
</div> </div>
</template> </template>
@ -58,6 +59,7 @@ import { t } from '@/lang'
import { getPayRefundPages } from '@/app/api/pay' import { getPayRefundPages } from '@/app/api/pay'
import { useRouter, useRoute } from 'vue-router' import { useRouter, useRoute } from 'vue-router'
import type { FormInstance } from 'element-plus' import type { FormInstance } from 'element-plus'
import refundDetail from '@/app/views/finance/components/refund-detail.vue'
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
@ -97,9 +99,11 @@ const loadPayRefundList = (page: number = 1) => {
}) })
} }
loadPayRefundList() loadPayRefundList()
const refundDetailDialog: Record<string, any> | null = ref(null)
const infoEvent = (data:any) => { const infoEvent = (res:any) => {
router.push('/finance/refund/detail?refund_no=' + data.refund_no) let data = {no: res.refund_no};
refundDetailDialog.value.setFormData(data);
refundDetailDialog.value.showDialog = true;
} }
const resetForm = (formEl: FormInstance | undefined) => { const resetForm = (formEl: FormInstance | undefined) => {

View File

@ -3,7 +3,7 @@
<div class="main-container"> <div class="main-container">
<el-card class="card !border-none" shadow="never"> <el-card class="card !border-none" shadow="never">
<el-page-header :content="pageName" :icon="ArrowLeft" @back="$router.back()" /> <el-page-header :content="pageName" :icon="ArrowLeft" @back="back()" />
</el-card> </el-card>
<el-card class="box-card mt-[15px] !border-none relative" shadow="never" v-if="formData"> <el-card class="box-card mt-[15px] !border-none relative" shadow="never" v-if="formData">
@ -66,8 +66,11 @@ import { ArrowLeft } from '@element-plus/icons-vue'
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
const pageName = route.meta.title const pageName = route.meta.title
const back = () => {
router.push('/finance/refund')
}
const refundNo: string = route.query.refund_no const refundNo: any = route.query.refund_no
const loading = ref(true) const loading = ref(true)
const refundList = ref([]) const refundList = ref([])
@ -76,15 +79,10 @@ const formData: Record<string, any> | null = ref(null)
const setFormData = async (refundNo: string = '') => { const setFormData = async (refundNo: string = '') => {
loading.value = true loading.value = true
formData.value = null formData.value = null
await getPayRefundInfo(refundNo) await getPayRefundInfo(refundNo).then(({ data }) => {
.then(({ data }) => { formData.value = data
formData.value = data refundList.value.push(data)
refundList.value.push(data) })
})
.catch(() => {
})
loading.value = false loading.value = false
} }
if (refundNo) setFormData(refundNo) if (refundNo) setFormData(refundNo)
@ -119,7 +117,6 @@ const formRules = computed(() => {
return { return {
label_name: [ label_name: [
{ required: true, message: t('labelNamePlaceholder'), trigger: 'blur' } { required: true, message: t('labelNamePlaceholder'), trigger: 'blur' }
] ]
} }
}) })

View File

@ -1,5 +1,5 @@
<template> <template>
<div> <div class="bg-[#F7F9FA] min-h-screen">
<div class="flex justify-between items-center py-[24px] pl-[62px] pr-[64px] home-head"> <div class="flex justify-between items-center py-[24px] pl-[62px] pr-[64px] home-head">
<div class="flex items-center" v-if="webConfig"> <div class="flex items-center" v-if="webConfig">
<img class="w-[32x] h-[32px] rounded-full" v-if="webConfig.icon" :src="img(webConfig.icon)" alt=""> <img class="w-[32x] h-[32px] rounded-full" v-if="webConfig.icon" :src="img(webConfig.icon)" alt="">
@ -12,7 +12,7 @@
</div> </div>
</div> </div>
<div class="w-[1200px] m-auto mt-[62px]"> <div class="w-[1400px] m-auto mt-[62px]">
<div class="flex justify-between items-center"> <div class="flex justify-between items-center">
<span class="text-[24px] font-bold">站点列表</span> <span class="text-[24px] font-bold">站点列表</span>
<el-button type="primary" class="w-[90px] !h-[34px]" :disabled="siteGroupLoading" @click="handleChick">创建站点</el-button> <el-button type="primary" class="w-[90px] !h-[34px]" :disabled="siteGroupLoading" @click="handleChick">创建站点</el-button>
@ -20,11 +20,11 @@
<div class="flex justify-between items-center mt-[18px]"> <div class="flex justify-between items-center mt-[18px]">
<div class="w-[800px] text-[14px] whitespace-nowrap"> <div class="w-[800px] text-[14px] whitespace-nowrap">
<el-scrollbar :always="true"> <el-scrollbar :always="true">
<span :class="['mr-[12px] cursor-pointer', {'text-[var(--el-color-primary)]': params.app == ''}]" @click="cutAppFn('')">所有应用</span> <span :class="['px-[10px] cursor-pointer h-[35px] leading-[35px] inline-block', {'class-select text-[var(--el-color-primary)]': params.app == ''}]" @click="cutAppFn('')">所有应用</span>
<span :class="['mr-[12px] cursor-pointer', {'text-[var(--el-color-primary)]': params.app == item.key}]" @click="cutAppFn(item.key)" v-for="(item,index) in addonList" :key="index">{{item.title}}</span> <span :class="['px-[10px] cursor-pointer h-[35px] leading-[35px] inline-block', {'class-select text-[var(--el-color-primary)]': params.app == item.key}]" @click="cutAppFn(item.key)" v-for="(item,index) in addonList" :key="index">{{item.title}}</span>
</el-scrollbar> </el-scrollbar>
</div> </div>
<el-input v-model="params.keywords" class="!w-[300px] !h-[34px]" placeholder="请输入要搜索的站点名称" @keyup.enter.native="getHomeSiteFn()"> <el-input v-model.trim="params.keywords" class="!w-[300px] !h-[34px]" placeholder="请输入要搜索的站点名称/编号" @keyup.enter.native="getHomeSiteFn()">
<template #suffix> <template #suffix>
<el-icon @click.stop="getHomeSiteFn()" class="cursor-pointer"> <el-icon @click.stop="getHomeSiteFn()" class="cursor-pointer">
<Search /> <Search />
@ -35,30 +35,29 @@
<div class="min-h-[580px]"> <div class="min-h-[580px]">
<div class="flex flex-wrap mt-[30px]" v-loading="loading"> <div class="flex flex-wrap mt-[30px]" v-loading="loading">
<div v-for="(item, index) in tableData" :key="index" @click="selectSite(item)" <div v-for="(item, index) in tableData" :key="index" @click="selectSite(item)" :class="['home-item w-[327px] box-border mb-[30px] cursor-pointer',{'mr-[30px]': index ==0 || (index+1)%4 != 0}]">
:class="['home-item w-[285px] box-border mb-[20px] cursor-pointer',{'mr-[20px]': index ==0 || (index+1)%4 != 0}]"> <div class="flex items-center px-[24px] pt-[22px] pb-[10px] home-item-head relative">
<div class="flex items-center px-[24px] pt-[22px] pb-[16px] bg-[#F0F2F4] home-item-head relative"> <div class="absolute h-[4px] w-full z-1 left-0 top-0" :style="{'background-color': item.theme_color}" v-if="item.theme_color"></div>
<div class="absolute h-[5px] w-full z-1 left-0 top-0" :style="{'background-color': item.theme_color}" v-if="item.theme_color"></div> <img v-if="item.icon" class="w-[46px] h-[46px] mr-[15px] img-shadow rounded-[6px] overflow-hidden" :src="img(item.icon)" />
<img v-if="item.icon" class="w-[48px] h-[48px] mr-[15px] rounded-[50%] overflow-hidden" :src="img(item.icon)" /> <img v-else class="w-[46px] h-[46px] mr-[15px] rounded-[6px] img-shadow overflow-hidden" src="@/app/assets/images/site_default.png" />
<img v-else class="w-[48px] h-[48px] mr-[15px] rounded-[50%] overflow-hidden" src="@/app/assets/images/member_head.png" />
<div class="flex flex-col flex-1 justify-center"> <div class="flex flex-col flex-1 justify-center">
<div class="flex items-center flex-wrap"> <div class="flex items-center flex-wrap">
<span class="text-[16px] text-[#000] max-w-[145px] font-bold truncate mr-[10px]">{{item.site_name}}</span> <span class="text-[16px] text-[#000] max-w-[160px] font-bold truncate mr-[10px]">{{item.site_name}}</span>
<div class="flex items-center justify-center min-w-[42px] h-[18px] bg-[#FF5500] rounded-tl-md rounded-br-md items-tab" v-if="item.app_name"> <div class="flex items-center justify-center min-w-[42px] h-[18px] bg-[#FF5500] rounded-tl-md rounded-br-md items-tab" v-if="item.app_name">
<span class="text-[12px] text-[#fff]">{{item.app_name}}</span> <span class="text-[12px] text-[#000]">{{item.app_name}}</span>
</div> </div>
</div> </div>
<span class="text-[12px] mt-[3px] text-[#555]">{{item.create_time ? item.create_time.split(" ")[0] : '--'}} {{item.expire_time ? item.expire_time.split(" ")[0] : '--'}}</span> <span class="text-[12px] mt-[3px] text-[#666]">{{item.create_time ? item.create_time.split(" ")[0] : '--'}} {{item.expire_time ? item.expire_time.split(" ")[0] : '--'}}</span>
</div> </div>
</div> </div>
<div class="px-[24px] py-[20px] text-[#6D7278]"> <div class="px-[24px] py-[20px] text-[#666]">
<p class="text-[14px]">站点编号{{item.site_id}}</p> <p class="text-[14px]">站点编号{{item.site_id}}</p>
<p class="text-[14px] mt-[2px]">站点套餐{{item.group_name || '--'}}</p> <p class="text-[14px] mt-[2px]">站点套餐{{item.group_name || '--'}}</p>
</div> </div>
</div> </div>
<div v-if="!tableData.length && !loading" class="m-auto mt-[100px]"> <div v-if="!tableData.length && !loading" class="m-auto mt-[100px]">
<img src="@/app/assets/images/site_empty.png"/> <img src="@/app/assets/images/site_empty.png" class="w-[220px] h-[165px]"/>
<p class="text-center text-gray-400 mt-[20px]">暂无站点</p> <p class="text-center text-gray-400 text-[14px] mt-[20px]">暂无站点</p>
</div> </div>
</div> </div>
</div> </div>
@ -73,20 +72,20 @@
<el-dialog v-model="createSiteDialog" width="54vw" :destroy-on-close="true" style="border-radius: 25px;"> <el-dialog v-model="createSiteDialog" width="54vw" :destroy-on-close="true" style="border-radius: 25px;">
<template #title> <template #title>
<div class="text-[#333333] text-[22px] ml-[10px] leading-[1]">创建站点</div> <div class="text-[#333333] text-[22px] ml-[15px] leading-[1] mt-[10px]">创建站点</div>
</template> </template>
<div class="flex flex-col mx-[20px] h-[430px]"> <div class="flex flex-col mx-[25px] h-[430px] mt-[15px]">
<div class="flex items-center"> <div class="flex items-center">
<div class="text-[18px] text-[#333333]">站点名称</div> <div class="text-[18px] text-[#333333]">站点名称</div>
<div class="w-[420px] h-[34px] ml-[10px]"> <div class="w-[350px] h-[34px] ml-[10px]">
<el-form :model="createSiteData.formData" ref="formRef" :rules="formRules"> <el-form :model="createSiteData.formData" ref="formRef" :rules="formRules">
<el-form-item prop="username"> <el-form-item prop="username">
<el-input class="create-site-name" v-model="createSiteData.formData.site_name" maxlength="20" placeholder="请输入站点名称" autocomplete="off"></el-input> <el-input class="create-site-name" v-model.trim="createSiteData.formData.site_name" maxlength="20" placeholder="请输入站点名称" autocomplete="off"></el-input>
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
</div> </div>
<div class="flex-1 mt-[20px] h-[160px]" v-show="createSiteData.step == 1"> <div class="flex-1 mt-[20px] h-[160px]" v-show="createSiteData.step == 1">
<div class="text-[18px] text-[#333333]">店铺套餐</div> <div class="text-[18px] text-[#333333]">店铺套餐</div>
<el-scrollbar class="w-full mt-[10px] meal-site -ml-[10px]" height="350px"> <el-scrollbar class="w-full mt-[10px] meal-site -ml-[10px]" height="350px">
@ -94,9 +93,8 @@
<div v-for="(item, index) in siteGroup" :key="index" <div v-for="(item, index) in siteGroup" :key="index"
class="inline-flex flex-col w-[300px] h-[330px] box-border rounded-[17px] border-transparent border-[2px] border-solid create-site-item my-[10px]" class="inline-flex flex-col w-[300px] h-[330px] box-border rounded-[17px] border-transparent border-[2px] border-solid create-site-item my-[10px]"
:class="{'bg-[#F6F7FF] border-[#466CEA]': createSiteData.formData.group_id == item.group_id ,'ml-[20px]': index > 0, ' ml-[10px]': index == 0, 'mr-[10px]': (siteGroup.length-1) == index }" :class="{'bg-[#F6F7FF] border-[#466CEA]': createSiteData.formData.group_id == item.group_id ,'ml-[20px]': index > 0, ' ml-[10px]': index == 0, 'mr-[10px]': (siteGroup.length-1) == index }"
@click="createSiteData.formData.group_id = item.group_id" @click="createSiteData.formData.group_id = item.group_id">
> <div class="w-[140px] h-[40px] px-[15px] truncate text-white text-[16px] text-center leading-[40px] creatBg relative -left-[1px] -top-[2px]">
<div class="w-[140px] h-[40px] truncate text-white text-[16px] text-center leading-[40px] creatBg relative -left-[1px] -top-[2px]">
{{ item.site_group.group_name }} {{ item.site_group.group_name }}
</div> </div>
<el-scrollbar class="flex pb-[20px] pt-[4px] box-border !h-[260px]"> <el-scrollbar class="flex pb-[20px] pt-[4px] box-border !h-[260px]">
@ -116,7 +114,7 @@
</div> </div>
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer">
<el-button type="primary" @click="createSiteFn" class="w-[118px] h-[44px] text-[16px]">创建站点</el-button> <el-button type="primary" @click="createSiteFn" class="w-[118px] h-[44px] mt-[10px] text-[16px]">创建站点</el-button>
</span> </span>
</template> </template>
</el-dialog> </el-dialog>
@ -265,7 +263,7 @@ const createSiteFn = () => {
getHomeSiteFn() getHomeSiteFn()
}).catch(() => { }).catch(() => {
createSiteData.value.loading = false createSiteData.value.loading = false
}) })
} }
watch(() => createSiteDialog.value, () => { watch(() => createSiteDialog.value, () => {
@ -286,7 +284,21 @@ watch(() => createSiteDialog.value, () => {
:deep(.el-input__wrapper) { :deep(.el-input__wrapper) {
@apply rounded-none; @apply rounded-none;
} }
.class-select {
position: relative;
// font-weight: bold;
color: var(--el-color-primary);
&::after {
content: "";
position: absolute;
bottom: 2px;
height: 2px; /* 下划线的高度 */
background-color: var(--el-color-primary); /* 下划线颜色 */
width: 75%;
left: 12%;
}
}
.border-color { .border-color {
border-color: var(--el-color-primary); border-color: var(--el-color-primary);
} }
@ -295,26 +307,32 @@ watch(() => createSiteDialog.value, () => {
color: var(--el-color-primary); color: var(--el-color-primary);
} }
.home-item{ .home-item{
box-shadow: 0 2px 4px 0 rgba(161,167,183,0.18); // box-shadow: 0 2px 4px 0 rgba(161,167,183,0.18);
background:#fff;
.items-tab span{ .items-tab span{
transform: scale(0.9); transform: scale(0.9);
} }
} }
.home-item:hover { .home-item:hover {
border-color: var(--el-color-primary); box-shadow: 0px 0px 18px rgba(0,0,0, 0.07);
// border-color: var(--el-color-primary);
.title { .title {
color: var(--el-color-primary); color: var(--el-color-primary);
} }
.home-item-head{ .home-item-head{
background-color: #A1A7B7; // background-color: #A1A7B7;
span{ span{
color: #fff !important; // color: #fff !important;
} }
} }
} }
.home-head{ .home-head{
background:#fff;
box-shadow: 0 4px 8px 0 rgba(28,31,55,0.04); box-shadow: 0 4px 8px 0 rgba(28,31,55,0.04);
} }
.img-shadow{
box-shadow: 0px 0px 4px rgba(0,0,0, 0.07);
}
.creatBg{ .creatBg{
background: url('@/app/assets/images/creatBg.png'); background: url('@/app/assets/images/creatBg.png');
background-repeat: no-repeat; background-repeat: no-repeat;
@ -328,6 +346,6 @@ watch(() => createSiteDialog.value, () => {
border-radius: 6px !important; border-radius: 6px !important;
} }
.meal-site{ .meal-site{
height: calc(100% - 30px); height: calc(100% - 30px) !important;
} }
</style> </style>

View File

@ -141,7 +141,21 @@ const regExp: any = {
// //
const formRules = reactive<FormRules>({ const formRules = reactive<FormRules>({
day_award: [ day_award: [
{ required: true, message: t('daySignAwardPlaceholder'), trigger: 'change' } {
required: true,
trigger: 'change',
validator: (rule: any, value: any, callback: any) => {
let isVerify = false
daySignAwardText.value.forEach(item => {
item.is_use && (isVerify = true)
})
if (!isVerify) {
callback(t('daySignAwardPlaceholder'))
} else {
callback()
}
}
}
], ],
sign_period:[{ sign_period:[{
required: true, required: true,

View File

@ -11,7 +11,7 @@
<el-card class="box-card !border-none my-[20px] table-search-wrap" shadow="never"> <el-card class="box-card !border-none my-[20px] table-search-wrap" shadow="never">
<el-form :inline="true" :model="memberTableData.searchParam" ref="searchFormRef"> <el-form :inline="true" :model="memberTableData.searchParam" ref="searchFormRef">
<el-form-item :label="t('memberInfo')" prop="keyword"> <el-form-item :label="t('memberInfo')" prop="keyword">
<el-input v-model="memberTableData.searchParam.keyword" class="w-[240px]" :placeholder="t('memberInfoPlaceholder')" /> <el-input v-model.trim="memberTableData.searchParam.keyword" class="w-[240px]" :placeholder="t('memberInfoPlaceholder')" />
</el-form-item> </el-form-item>
<el-form-item :label="t('registerChannel')" prop="register_channel"> <el-form-item :label="t('registerChannel')" prop="register_channel">
@ -28,7 +28,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item :label="t('memberLevel')" prop="member_label"> <el-form-item :label="t('memberLevel')" prop="member_level">
<el-select v-model="memberTableData.searchParam.member_level" collapse-tags clearable :placeholder="t('memberLevelPlaceholder')" class="input-width"> <el-select v-model="memberTableData.searchParam.member_level" collapse-tags clearable :placeholder="t('memberLevelPlaceholder')" class="input-width">
<el-option :label="t('selectPlaceholder')" value="" /> <el-option :label="t('selectPlaceholder')" value="" />
<el-option :label="item['level_name']" :value="item['level_id']" v-for="(item, index) in levelSelectData" :key="index" /> <el-option :label="item['level_name']" :value="item['level_id']" v-for="(item, index) in levelSelectData" :key="index" />
@ -56,9 +56,11 @@
<el-table-column prop="nickname" :show-overflow-tooltip="true" :label="t('memberInfo')" min-width="170"> <el-table-column prop="nickname" :show-overflow-tooltip="true" :label="t('memberInfo')" min-width="170">
<template #default="{ row }"> <template #default="{ row }">
<div class="flex items-center"> <div class="flex items-center">
<img class="w-[50px] h-[50px] mr-[10px]" v-if="row.headimg" :src="img(row.headimg)" alt=""> <div class="mr-[10px] rounded-full w-[50px] h-[50px] flex items-center justify-center">
<img class="w-[50px] h-[50px] mr-[10px]" v-else src="@/app/assets/images/default_headimg.png" alt=""> <img class="max-w-[50px] max-h-[50px]" v-if="row.headimg" :src="img(row.headimg)" alt="">
<div class="flex flex flex-col"> <img class="max-w-[50px] max-h-[50px]" v-else src="@/app/assets/images/member_head.png" alt="">
</div>
<div class="flex flex-col">
<span>{{ row.nickname || '' }}</span> <span>{{ row.nickname || '' }}</span>
</div> </div>
</div> </div>
@ -122,6 +124,7 @@
<add-member ref="addMemberDialog" @complete="loadMemberList()" /> <add-member ref="addMemberDialog" @complete="loadMemberList()" />
<edit-member ref="editMemberDialog" @complete="loadMemberList()" /> <edit-member ref="editMemberDialog" @complete="loadMemberList()" />
<export-sure ref="exportSureDialog" :show="flag" type="member" :searchParam="memberTableData.searchParam" @close="handleClose" /> <export-sure ref="exportSureDialog" :show="flag" type="member" :searchParam="memberTableData.searchParam" @close="handleClose" />
<detail-member ref="detailMemberDialog" @load="loadMemberList()"></detail-member>
</el-card> </el-card>
</div> </div>
</template> </template>
@ -130,10 +133,11 @@
import { reactive, ref } from 'vue' import { reactive, ref } from 'vue'
import { t } from '@/lang' import { t } from '@/lang'
import { img } from '@/utils/common' import { img } from '@/utils/common'
import { addMember, getRegisterChannelType, getMemberList, getMemberLabelAll, editMemberStatus, deleteMember, getMemberLevelAll } from '@/app/api/member' import { getRegisterChannelType, getMemberList, getMemberLabelAll, editMemberStatus, deleteMember, getMemberLevelAll } from '@/app/api/member'
import { ElMessageBox, FormInstance } from 'element-plus' import { ElMessageBox, FormInstance } from 'element-plus'
import { useRouter, useRoute } from 'vue-router' import { useRouter, useRoute } from 'vue-router'
import AddMember from '@/app/views/member/components/add-member.vue' import AddMember from '@/app/views/member/components/add-member.vue'
import detailMember from '@/app/views/member/components/detail-member.vue'
import EditMember from '@/app/views/member/components/edit-member.vue' import EditMember from '@/app/views/member/components/edit-member.vue'
const route = useRoute() const route = useRoute()
@ -204,19 +208,7 @@ loadMemberList()
const router = useRouter() const router = useRouter()
const addMemberDialog: Record<string, any> | null = ref(null) const addMemberDialog: Record<string, any> | null = ref(null)
const editMemberDialog: Record<string, any> | null = ref(null) const editMemberDialog: Record<string, any> | null = ref(null)
const detailMemberDialog: Record<string, any> | null = ref(null)
/**
* 获取标签
*/
function memberLablel(res: any) {
let data
if (!res.member_label_array) return ''
data = res.member_label_array.map((item: any) => {
return item.label_name
})
data = data.toString()
return data
}
/** /**
* 设置标签 * 设置标签
@ -267,8 +259,10 @@ const editEvent = (data: any) => { }
/** /**
* 会员详情 * 会员详情
*/ */
const detailEvent = (data: any) => { const detailEvent = (res: any) => {
router.push(`/member/detail?id=${data.member_id}`) let data = {id: res.member_id};
detailMemberDialog.value.setFormData(data);
detailMemberDialog.value.showDialog = true;
} }
/** /**

View File

@ -11,15 +11,18 @@
<el-card class="box-card !border-none" shadow="never"> <el-card class="box-card !border-none" shadow="never">
<el-form-item :label="t('isOpen')"> <el-form-item :label="t('isOpen')">
<el-switch v-model="formData.is_open" /> <el-switch v-model="formData.is_open" active-value="1" inactive-value="0" />
</el-form-item> </el-form-item>
<el-form-item :label="t('cashWithdrawalAmount')" v-if="formData.is_open" prop="min"> <el-form-item :label="t('cashWithdrawalAmount')" v-if="formData.is_open" prop="min">
<el-input v-model="formData.min" @keyup="filterDigit($event)" class="input-width" :placeholder="t('cashWithdrawalAmountPlaceholder')" /> <div>
<el-input v-model.trim="formData.min" @keyup="filterDigit($event)" class="input-width" :placeholder="t('cashWithdrawalAmountPlaceholder')" />
<div class="text-[12px] text-[#999] leading-[24px]">{{ t('minTips') }}</div>
</div>
</el-form-item> </el-form-item>
<el-form-item :label="t('commissionRatio')" v-if="formData.is_open" prop="rate"> <el-form-item :label="t('commissionRatio')" v-if="formData.is_open" prop="rate">
<el-input v-model="formData.rate" @keyup="filterDigit($event)" class="input-width" :placeholder="t('commissionRatioPlaceholder')" /> <el-input v-model.trim="formData.rate" @keyup="filterDigit($event)" class="input-width" :placeholder="t('commissionRatioPlaceholder')" />
<span class="ml-2">%</span> <span class="ml-2">%</span>
</el-form-item> </el-form-item>
@ -30,17 +33,22 @@
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item :label="t('transfer')" v-if="formData.is_open" class="items-center"> <!-- <el-form-item :label="t('transfer')" v-if="formData.is_open" class="items-baseline">
<el-radio-group v-model="formData.is_auto_transfer"> <div>
<el-radio label="0" size="large">{{t('manualTransfer')}}</el-radio> <el-radio-group v-model="formData.is_auto_transfer">
<el-radio label="1" size="large">{{t('automatedTransit')}}</el-radio> <el-radio label="0" size="large">{{t('manualTransfer')}}</el-radio>
</el-radio-group> <el-radio label="1" size="large">{{t('automatedTransit')}}</el-radio>
</el-form-item> </el-radio-group>
<div class="text-[12px] text-[#999] leading-[24px]">{{ t('transferTips') }}</div>
<el-form-item :label="t('transferMode')" v-if="formData.is_open" class="items-center"> </div>
<el-checkbox-group v-model="formData.transfer_type" size="large"> </el-form-item> -->
<el-checkbox :label="item.key" v-for="(item,index) in Transfertype" :key="'a'+index">{{item.name}}</el-checkbox> <el-form-item :label="t('transferMode')" v-if="formData.is_open" class="items-baseline">
</el-checkbox-group> <div>
<el-checkbox-group v-model="formData.transfer_type" size="large">
<el-checkbox :label="item.key" v-for="(item,index) in Transfertype" :key="'a'+index">{{item.name}}</el-checkbox>
</el-checkbox-group>
<div class="text-[12px] text-[#999] leading-[24px]">{{ t('transferModeTips') }}</div>
</div>
</el-form-item> </el-form-item>
</el-card> </el-card>
</el-form> </el-form>
@ -67,11 +75,11 @@ const pageName = route.meta.title
const loading = ref(true) const loading = ref(true)
const ruleFormRef = ref<FormInstance>() const ruleFormRef = ref<FormInstance>()
const formData = reactive<Record<string, string | boolean | Array<string> >>({ const formData = reactive({
is_auto_transfer: '0', is_auto_transfer: '0',
is_auto_verify: '0', is_auto_verify: '0',
is_open: '0', is_open: '0',
min: '0.01', min: '0',
rate: '0', rate: '0',
transfer_type: [] transfer_type: []
}) })
@ -84,12 +92,11 @@ const getTransfertypeFn = async () => {
getTransfertypeFn() getTransfertypeFn()
// //
const setFormData = async (id: number = 0) => { const setFormData = async () => {
const data = await (await getCashOutConfig()).data const data = await (await getCashOutConfig()).data
Object.keys(formData).forEach((key: string) => { Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key] if (data[key] != undefined) formData[key] = data[key]
}) })
formData.is_open = Boolean(Number(formData.is_open))
loading.value = false loading.value = false
} }
setFormData() setFormData()
@ -124,7 +131,6 @@ const onSave = async (formEl: FormInstance | undefined) => {
await formEl.validate((valid) => { await formEl.validate((valid) => {
if (valid) { if (valid) {
const save = { ...formData } const save = { ...formData }
save.is_open = Number(save.is_open).toString()
setCashOutConfig(save).then(() => { setCashOutConfig(save).then(() => {
loading.value = false loading.value = false

View File

@ -40,7 +40,15 @@
<el-dialog v-model="showDialog" :title="t('selectLayout')" width="800" :destroy-on-close="true"> <el-dialog v-model="showDialog" :title="t('selectLayout')" width="800" :destroy-on-close="true">
<div class="h-[300px]"> <div class="h-[300px]">
<el-scrollbar > <el-scrollbar >
<h3 class="panel-title !text-sm">{{ t('layout') }}</h3> <div class="flex justify-between items-center mb-[20px]">
<h3 class="!text-sm !text-[#444]">{{ t('layout') }}</h3>
<div class="flex items-center cursor-pointer" @click="toDiyLayout">
<span class="iconfont iconwenhao text-[#999] !text-[14px]"></span>
<div class="ml-[2px] text-[12px] text-[#999]">如何开发自定义布局</div>
</div>
</div>
<div class="flex justify-items-stretch"> <div class="flex justify-items-stretch">
<div class="w-[180px] h-[130px] mr-[10px] mb-[10px] border hover:border-primary cursor-pointer" <div class="w-[180px] h-[130px] mr-[10px] mb-[10px] border hover:border-primary cursor-pointer"
:class="{'border-primary': ((!layoutConfig[currAddon] && item.layout == 'default') || (layoutConfig[currAddon] == item.layout)) }" :class="{'border-primary': ((!layoutConfig[currAddon] && item.layout == 'default') || (layoutConfig[currAddon] == item.layout)) }"
@ -56,8 +64,9 @@
</div> </div>
</div> </div>
<h3 class="panel-title !text-sm">{{ t('themeColor') }}</h3> <h3 class="panel-title !text-sm">{{ t('themeColor') }}</h3>
<div class="flex justify-items-stretch"> <div class="">
<el-color-picker v-model="themeColor[currAddon]" size="large" /> <el-color-picker v-model="themeColor[currAddon]" size="large" />
<div class="form-tip text-[#999] mt-2">设置的色调会在前端站点列表体现[home/index]用于区分不同的应用</div>
</div> </div>
</el-scrollbar> </el-scrollbar>
</div> </div>
@ -106,14 +115,16 @@ getInstalledAddonList().then(({ data }) => {
item.type == 'app' && addonList.value.push(item) item.type == 'app' && addonList.value.push(item)
}) })
loading.value = false loading.value = false
}).catch() })
const getLayoutConfig = () => { const getLayoutConfig = () => {
getLayout().then(({ data }) => { getLayout().then(({ data }) => {
layoutConfig.value = data layoutConfig.value = data
console.log('getLayoutConfig - layoutConfig', layoutConfig.value)
}) })
getThemecolor().then(({ data }) => { getThemecolor().then(({ data }) => {
themeColor.value = data themeColor.value = data
console.log('getLayoutConfig - themeColor', themeColor.value)
}) })
} }
getLayoutConfig() getLayoutConfig()
@ -142,6 +153,13 @@ const confirm = () => {
}) })
showDialog.value = false showDialog.value = false
} }
//
const toDiyLayout = () => {
let url = 'https://doc.niucloud.com/saas.html?keywords=/ru-he-kai-fa-zi-ding-yi-bu-ju-hou-tai-bu-ju';
window.open(url)
}
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>

View File

@ -8,7 +8,11 @@
</div> </div>
<div class="mt-[20px]"> <div class="mt-[20px]">
<el-alert :title="t('operationTip')" type="warning" show-icon /> <el-alert type="warning" show-icon>
<template #title>
<span class="!text-[14px]">{{ t('operationTip') }}</span>
</template>
</el-alert>
</div> </div>
</el-card> </el-card>
@ -17,11 +21,11 @@
<h3 class="panel-title !text-sm">{{t('wechatpay')}}</h3> <h3 class="panel-title !text-sm">{{t('wechatpay')}}</h3>
<el-form-item :label="t('mchId')" prop="wechatpay_config.mch_id"> <el-form-item :label="t('mchId')" prop="wechatpay_config.mch_id">
<el-input v-model="formData.wechatpay_config.mch_id" :placeholder="t('mchIdPlaceholder')" class="input-width" maxlength="32" show-word-limit clearable /> <el-input v-model.trim="formData.wechatpay_config.mch_id" :placeholder="t('mchIdPlaceholder')" class="input-width" maxlength="32" show-word-limit clearable />
<div class="form-tip">{{ t('mchIdTips') }}</div> <div class="form-tip">{{ t('mchIdTips') }}</div>
</el-form-item> </el-form-item>
<el-form-item :label="t('mchSecretKey')" prop="wechatpay_config.mch_secret_key"> <el-form-item :label="t('mchSecretKey')" prop="wechatpay_config.mch_secret_key">
<el-input v-model="formData.wechatpay_config.mch_secret_key" :placeholder="t('mchSecretKeyPlaceholder')" class="input-width" maxlength="32" show-word-limit clearable /> <el-input v-model.trim="formData.wechatpay_config.mch_secret_key" :placeholder="t('mchSecretKeyPlaceholder')" class="input-width" maxlength="32" show-word-limit clearable />
<div class="form-tip">{{ t('mchSecretKeyTips') }}</div> <div class="form-tip">{{ t('mchSecretKeyTips') }}</div>
</el-form-item> </el-form-item>
<el-form-item :label="t('mchSecretCert')" prop="wechatpay_config.mch_secret_cert"> <el-form-item :label="t('mchSecretCert')" prop="wechatpay_config.mch_secret_cert">
@ -36,17 +40,28 @@
</div> </div>
<div class="form-tip">{{ t('mchPublicCertPathTips') }}</div> <div class="form-tip">{{ t('mchPublicCertPathTips') }}</div>
</el-form-item> </el-form-item>
<el-form-item :label="t('wechatpayPublicCert')" prop="wechatpay_config.wechat_public_cert_path">
<div class="input-width">
<upload-file v-model="formData.wechatpay_config.wechat_public_cert_path" api="sys/document/wechat" />
</div>
</el-form-item>
<el-form-item :label="t('wechatpayPublicCertId')" prop="wechatpay_config.wechat_public_cert_id">
<div class="input-width">
<el-input v-model.trim="formData.wechatpay_config.wechat_public_cert_id" placeholder="" class="input-width" show-word-limit clearable />
</div>
</el-form-item>
</el-card> </el-card>
<el-card class="box-card mt-[15px] !border-none" shadow="never"> <!-- <el-card class="box-card mt-[15px] !border-none" shadow="never">
<h3 class="panel-title !text-sm">{{t('alipay')}}</h3> <h3 class="panel-title !text-sm">{{t('alipay')}}</h3>
<el-form-item :label="t('appId')" prop="alipay_config.app_id"> <el-form-item :label="t('appId')" prop="alipay_config.app_id">
<el-input v-model="formData.alipay_config.app_id" :placeholder="t('appIdPlaceholder')" class="input-width" maxlength="32" show-word-limit clearable /> <el-input v-model.trim="formData.alipay_config.app_id" :placeholder="t('appIdPlaceholder')" class="input-width" maxlength="32" show-word-limit clearable />
<div class="form-tip">{{ t('appIdTips') }}</div> <div class="form-tip">{{ t('appIdTips') }}</div>
</el-form-item> </el-form-item>
<el-form-item :label="t('appSecretCert')" prop="alipay_config.app_secret_cert"> <el-form-item :label="t('appSecretCert')" prop="alipay_config.app_secret_cert">
<el-input v-model="formData.alipay_config.app_secret_cert" :placeholder="t('appSecretCertPlaceholder')" class="input-width" type="textarea" rows="4" clearable /> <el-input v-model.trim="formData.alipay_config.app_secret_cert" :placeholder="t('appSecretCertPlaceholder')" class="input-width" type="textarea" rows="4" clearable />
</el-form-item> </el-form-item>
<el-form-item :label="t('appPublicCertPath')" prop="alipay_config.app_public_cert_path"> <el-form-item :label="t('appPublicCertPath')" prop="alipay_config.app_public_cert_path">
<div class="input-width"> <div class="input-width">
@ -63,7 +78,7 @@
<upload-file v-model="formData.alipay_config.alipay_root_cert_path" api="sys/document/aliyun" /> <upload-file v-model="formData.alipay_config.alipay_root_cert_path" api="sys/document/aliyun" />
</div> </div>
</el-form-item> </el-form-item>
</el-card> </el-card> -->
</el-form> </el-form>
<div class="fixed-footer-wrap"> <div class="fixed-footer-wrap">
@ -78,7 +93,6 @@
import { reactive, ref, computed } from 'vue' import { reactive, ref, computed } from 'vue'
import { t } from '@/lang' import { t } from '@/lang'
import { getTransferInfo, setTransferInfo } from '@/app/api/sys' import { getTransferInfo, setTransferInfo } from '@/app/api/sys'
// import { useClipboard } from '@vueuse/core'
import { FormInstance } from 'element-plus' import { FormInstance } from 'element-plus'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
@ -95,7 +109,9 @@ const initialFormData = {
mch_id: '', mch_id: '',
mch_secret_key: '', mch_secret_key: '',
mch_secret_cert: '', mch_secret_cert: '',
mch_public_cert_path: '' mch_public_cert_path: '',
wechat_public_cert_path: '',
wechat_public_cert_id: ''
}, },
alipay_config: { alipay_config: {
app_secret_cert: '', app_secret_cert: '',

View File

@ -0,0 +1,149 @@
<template>
<div class="main-container">
<el-card class="box-card mt-[15px] !border-none" shadow="never" v-for="(item, key) in screne" :key="key">
<div class="flex items-center mb-[20px]">
<h3 class="text-[14px] mr-[20px]">{{ item.name }}</h3>
<div class="flex items-center">
<span class="text-[14px] mr-[10px]">{{ t('transferSceneId') }}</span>
<div class="flex items-center">
<el-input v-model.trim="item.scene_id" maxlength="5" class="!w-[60px]" :disabled="item.disabled" @blur="handleInput($event,key,item)" :ref="(el: any) =>{ if(el) inputRefs[key] = el }" v-show="!item.disabled"/>
<div v-show="item.disabled">{{item.scene_id ? item.scene_id : '--'}}</div>
<div @click="handleDisabled(item, key)" class="w-[40xp] flex items-center ml-[8px]"><el-icon size="20" color="var(--el-color-primary)"><Edit /></el-icon></div>
</div>
</div>
</div>
<div>
<div class="flex items-center justify-between p-[10px] table-item-border bg">
<span class="text-base w-[230px]">{{ t('transferType') }}</span>
<span class="text-base w-[230px]">{{ t('recvPerception') }}</span>
<span class="text-base w-[230px]">{{ t('reportInfos') }}</span>
<span class="text-base w-[80px] text-center">{{ t('operation') }}</span>
</div>
<div v-if="Object.values(item.trade_scene_data).length">
<div class="flex items-center justify-between p-[10px] table-item-border" v-for="(subItem, subKey) in item.trade_scene_data" :key="subKey">
<div class="flex w-[230px] flex-shrink-0 text-base">{{ subItem.name }}</div>
<div class="flex w-[230px] flex-shrink-0 text-base">{{ subItem.perception }}</div>
<div class="w-[230px] flex-shrink-0 text-base">
<div v-for="(childItem,childKey) in subItem.infos" :key="childKey">{{ childKey }}{{ childItem }}</div>
</div>
<div class="flex items-center justify-center w-[80px] select-none">
<button class="text-base text-primary" @click="configFn(item,subItem,subKey)">{{ t('deploy') }}</button>
</div>
</div>
</div>
<div v-else class="min-h-[80px] flex items-center justify-center text-base">
{{ t('noData') }}
</div>
</div>
</el-card>
<el-dialog v-model="showDialog" :title="curData.name" width="550px" :destroy-on-close="true">
<el-form :model="formData" label-width="110px" ref="formRef" class="page-form">
<el-form-item :label="t('recvPerception')" prop="perception" :rules="[{ required: true, message: t('recvPerceptionTips'), trigger: 'blur' }]">
<el-select v-model="formData.perception" :placeholder="t('recvPerceptionTips')" clearable class="!w-[300px]">
<el-option v-for="(item,index) in curData.user_recv_perception" :key="index" :label="item" :value="item" />
</el-select>
</el-form-item>
<template v-for="(item, index) in curData.transfer_scene_report_infos" :key="index">
<el-form-item :label="item" :prop="`infos[${item}]`" :rules="[{ required: true, message: `请输入${item}`, trigger: 'blur' }]">
<el-input v-model.trim="formData.infos[item]" maxlength="40" class="!w-[300px]"/>
</el-form-item>
</template>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="cancel">{{ t('cancel') }}</el-button>
<el-button type="primary" :loading="loading" @click="confirm(formRef)">{{ t('confirm') }}</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import { nextTick, ref } from 'vue'
import { t } from '@/lang'
import { getTransferScene, setSceneId, setTradeScene } from '@/app/api/pay'
import { cloneDeep } from 'lodash-es'
import { FormInstance } from 'element-plus'
const screne = ref<any>({})
const loading = ref(false)
const getTransferSceneFn = () => {
getTransferScene().then(res => {
screne.value = res.data
for (const key in screne.value) {
screne.value[key].disabled = true
}
})
}
getTransferSceneFn()
//
const handleInput = (e: any, key: any, data: any) => {
if (e.target.value) {
setSceneId({
scene: key,
scene_id: e.target.value
}).then(() => {
data.disabled = true
getTransferSceneFn()
})
} else {
data.disabled = true
}
}
const inputRefs = ref<any>({})
const handleDisabled = (data: any, key: any) => {
data.disabled = false
nextTick(() => {
inputRefs.value[key].focus()
})
}
const showDialog = ref(false)
const curData = ref<any>({})
const formData = ref({
type: '',
scene: '',
perception: '',
infos: {}
})
const configFn = (data: any, subData: any, type: any) => {
curData.value = cloneDeep(data)
formData.value.type = type
formData.value.scene = subData.scene
formData.value.perception = subData.perception
formData.value.infos = cloneDeep(subData.infos)
showDialog.value = true
}
const formRef = ref<FormInstance>()
/**
* 确认
* @param formEl
*/
const confirm = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
setTradeScene(formData.value).then(() => {
loading.value = false
showDialog.value = false
getTransferSceneFn()
}).catch(() => {
loading.value = false
})
}
})
}
const cancel = () => {
showDialog.value = false
}
</script>
<style lang="scss" scoped>
.table-item-border {
@apply border-b border-[var(--el-border-color)];
}
</style>

View File

@ -1,18 +1,71 @@
<template> <template>
<div class="main-container"> <div class="main-container">
<el-card class="box-card !border-none" shadow="never"> <el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center"> <div class="flex justify-between items-center">
<span class="text-page-title">{{ pageName }}</span> <span class="text-page-title">{{ pageName }}</span>
<el-button type="primary" class="w-[100px]" @click="commit()">
{{ t('oneClickSync') }}
</el-button>
</div> </div>
<div class="mt-[50px] ml-[100px] h-[60vh]"> <div class="mt-[20px]">
<el-button type="primary" :loading="uploading" @click="commit">{{ t('weappVersionUpdate') }}</el-button> <el-alert :title="t('updateTips')" type="info" show-icon />
<p class="text-secondary text-sm mt-[10px]">{{ t('updateTips') }}</p> </div>
<p class="text-secondary text-sm mt-[10px]" v-if="lastRecord.create_time">
{{ t('lastTime') }}{{ lastRecord.create_time }} <div class="mt-[20px]">
<el-button type="primary" link @click="commitRecordDialogShow = true">{{ t('seeUpdateRecord') }}</el-button> <el-table :data="siteGroupCommitRecordTableData.data" size="large" v-loading="siteGroupCommitRecordTableData.loading">
</p> <template #empty>
<span>{{ !siteGroupCommitRecordTableData.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column prop="group_name" :label="t('groupName')" />
<el-table-column :label="t('userVersion')" :show-overflow-tooltip="true">
<template #default="{ row }">
{{ row.commit_record.user_version || '--' }}
</template>
</el-table-column>
<el-table-column prop="create_time" :label="t('createTime')">
<template #default="{ row }">
{{ row.commit_record.create_time || '--' }}
</template>
</el-table-column>
<el-table-column prop="create_time" :label="t('status')">
<template #default="{ row }">
<div v-if="row.commit_record.user_version">
{{ row.commit_record.status_name }}
<div v-if="row.commit_record.template_id == '0'" class="text-error">
{{ t('syncTemplateError') }}
</div>
</div>
<div>
--
</div>
</template>
</el-table-column>
<el-table-column prop="create_time" :label="t('templateID')">
<template #default="{ row }">
{{ row.commit_record.template_id || '--' }}
</template>
</el-table-column>
<el-table-column :label="t('operation')" align="right" fixed="right" width="330">
<template #default="{ row }">
<el-button type="primary" link @click="showCommitRecordDialog(row.group_id)">{{ t('commitRecord') }}</el-button>
<el-button type="primary" link @click="commit(row.group_id)">{{ t('weappVersionUpdate') }}</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div class="mt-[16px] flex justify-end">
<el-pagination v-model:current-page="siteGroupCommitRecordTableData.page"
v-model:page-size="siteGroupCommitRecordTableData.limit" layout="total, sizes, prev, pager, next, jumper"
:total="siteGroupCommitRecordTableData.total" @size-change="loadSiteGroupCommitRecordTableData()"
@current-change="loadSiteGroupCommitRecordTableData" />
</div> </div>
</el-card> </el-card>
</div> </div>
@ -24,7 +77,6 @@
</template> </template>
<el-table-column prop="user_version" :label="t('userVersion')" /> <el-table-column prop="user_version" :label="t('userVersion')" />
<el-table-column prop="site_group_name" :label="t('groupName')" />
<el-table-column :label="t('status')" prop="status_name"></el-table-column> <el-table-column :label="t('status')" prop="status_name"></el-table-column>
<el-table-column prop="create_time" :label="t('createTime')"></el-table-column> <el-table-column prop="create_time" :label="t('createTime')"></el-table-column>
<el-table-column :label="t('operation')" align="right" fixed="right" width="130"> <el-table-column :label="t('operation')" align="right" fixed="right" width="130">
@ -40,7 +92,7 @@
</el-dialog> </el-dialog>
<el-dialog v-model="failReasonDialogShow" :title="t('failReason')" width="60%"> <el-dialog v-model="failReasonDialogShow" :title="t('failReason')" width="60%">
<el-scrollbar class="h-[60vh] w-full whitespace-pre p-[20px]"> <el-scrollbar class="h-[60vh] w-full whitespace-pre-wrap p-[20px]">
{{ failReason }} {{ failReason }}
</el-scrollbar> </el-scrollbar>
</el-dialog> </el-dialog>
@ -49,7 +101,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import { reactive, ref } from 'vue' import { reactive, ref } from 'vue'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import { getWeappLastCommitRecord, weappCommit, getWeappCommitRecord } from '@/app/api/wxoplatform' import { getWeappLastCommitRecord, weappCommit, getWeappCommitRecord, getSiteGroupCommitRecord } from '@/app/api/wxoplatform'
import { t } from '@/lang' import { t } from '@/lang'
const route = useRoute() const route = useRoute()
@ -64,9 +116,17 @@ const commitRecordTableData = reactive({
loading: true, loading: true,
data: [], data: [],
searchParam: { searchParam: {
search: '' site_group_id: ''
} }
}) })
const siteGroupCommitRecordTableData = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam: {}
})
const failReason = ref('') const failReason = ref('')
const failReasonDialogShow = ref(false) const failReasonDialogShow = ref(false)
@ -79,21 +139,17 @@ getWeappLastCommitRecord().then(({ data }) => {
lastRecord.value = data lastRecord.value = data
}) })
const commit = () => { const commit = (siteGroupId = '') => {
if (uploading.value) return if (uploading.value) return
uploading.value = true uploading.value = true
weappCommit().then(() => { weappCommit({ site_group_id: siteGroupId }).then(() => {
uploading.value = false uploading.value = false
}).catch(() => { }).catch(() => {
uploading.value = false uploading.value = false
}) })
} }
const showUpdateLog = () => {
}
/** /**
* 获取角色列表 * 获取角色列表
*/ */
@ -104,7 +160,7 @@ const loadCommitRecordList = (page: number = 1) => {
getWeappCommitRecord({ getWeappCommitRecord({
page: commitRecordTableData.page, page: commitRecordTableData.page,
limit: commitRecordTableData.limit, limit: commitRecordTableData.limit,
role_name: commitRecordTableData.searchParam.search site_group_id: commitRecordTableData.searchParam.site_group_id
}).then(res => { }).then(res => {
commitRecordTableData.loading = false commitRecordTableData.loading = false
commitRecordTableData.data = res.data.data commitRecordTableData.data = res.data.data
@ -113,7 +169,33 @@ const loadCommitRecordList = (page: number = 1) => {
commitRecordTableData.loading = false commitRecordTableData.loading = false
}) })
} }
loadCommitRecordList()
const loadSiteGroupCommitRecordTableData = (page: number = 1) => {
siteGroupCommitRecordTableData.loading = true
siteGroupCommitRecordTableData.page = page
getSiteGroupCommitRecord({
page: siteGroupCommitRecordTableData.page,
limit: siteGroupCommitRecordTableData.limit
}).then(res => {
siteGroupCommitRecordTableData.loading = false
siteGroupCommitRecordTableData.data = res.data.data
siteGroupCommitRecordTableData.total = res.data.total
}).catch(() => {
siteGroupCommitRecordTableData.loading = false
})
}
loadSiteGroupCommitRecordTableData()
const showCommitRecordDialog = (siteGroupId: number) => {
commitRecordTableData.searchParam.site_group_id = siteGroupId
loadCommitRecordList()
commitRecordDialogShow.value = true
}
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped>
:deep(.el-alert__title) {
white-space: pre;
}
</style>

View File

@ -2,14 +2,26 @@
<template v-if="meta.show"> <template v-if="meta.show">
<el-sub-menu v-if="meta.type == 0 && routes.children" :index="String(routes.name)"> <el-sub-menu v-if="meta.type == 0 && routes.children" :index="String(routes.name)">
<template #title> <template #title>
<icon v-if="meta.icon && systemStore.menuIsCollapse || props.level != 1" :name="meta.icon" :size="(meta.icon && systemStore.menuIsCollapse && props.level == 1) ? '20px' : '16px'" class="absolute" /> <div class="flex h-full flex-col items-center justify-center" v-if="systemStore.menuIsCollapse && props.level == 1">
<icon v-if="meta.icon" :name="meta.icon" :size="'20px'" class="leading-none"/>
<div class="leading-none mt-[5px]">{{ meta.short_title || meta.title }}</div>
</div>
<template v-else>
<icon v-if="meta.icon && props.level != 1" :name="meta.icon" :size="props.level == 1 ? '20px' : '16px'" class="absolute" />
</template>
<span class="text-[14px]" :class="{ 'font-bold': props.level === 1 , ' ml-[20px]': (meta.icon && props.level != 1) }">{{ meta.title }}</span> <span class="text-[14px]" :class="{ 'font-bold': props.level === 1 , ' ml-[20px]': (meta.icon && props.level != 1) }">{{ meta.title }}</span>
</template> </template>
<menu-item v-for="(route, index) in routes.children" :routes="route" :key="index" :level="props.level + 1" /> <menu-item v-for="(route, index) in routes.children" :routes="route" :key="index" :level="props.level + 1" />
</el-sub-menu> </el-sub-menu>
<template v-else> <template v-else>
<el-menu-item :index="String(routes.name)" @click="router.push({ name: routes.name })" > <el-menu-item :index="String(routes.name)" @click="router.push({ name: routes.name })" >
<icon v-if="meta.icon && systemStore.menuIsCollapse || props.level != 1" :name="meta.icon" :size="(meta.icon && systemStore.menuIsCollapse && props.level == 1) ? '20px' : '16px'" class="absolute" /> <div class="flex h-full flex-col items-center justify-center" v-if="systemStore.menuIsCollapse && props.level == 1">
<icon v-if="meta.icon" :name="meta.icon" :size="'20px'" class="leading-none"/>
<div class="leading-none mt-[5px]">{{ meta.short_title || meta.title }}</div>
</div>
<template v-else>
<icon v-if="meta.icon && props.level != 1" :name="meta.icon" :size="props.level == 1 ? '20px' : '16px'" class="absolute" />
</template>
<template #title> <template #title>
<span class="text-[14px]" :class="{ 'font-bold': props.level === 1 , ' ml-[20px]': (meta.icon && props.level != 1) }">{{ meta.title }}</span> <span class="text-[14px]" :class="{ 'font-bold': props.level === 1 , ' ml-[20px]': (meta.icon && props.level != 1) }">{{ meta.title }}</span>
</template> </template>
@ -87,7 +99,7 @@ watch(route, () => {
color: var(--el-color-primary); color: var(--el-color-primary);
} }
} }
.el-icon.el-sub-menu__icon-arrow{ .el-icon.el-sub-menu__icon-arrow{
font-size: 15px; font-size: 15px;
top: 50%; top: 50%;

View File

@ -121,8 +121,10 @@ defaultOpeneds.value = menuData.value.map(item => item.name)
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
&.el-menu--collapse .el-sub-menu__title{ &.el-menu--collapse {
justify-content: center; .el-menu-item, .el-sub-menu__title {
--el-menu-item-height: 60px;
}
} }
} }

View File

@ -1 +1,2 @@
/* addon iconfont */ @import "addon/o2o/iconfont.css";
@import "addon/tourism/iconfont.css";

View File

@ -0,0 +1,38 @@
@font-face {
font-family: "o2o"; /* Project id 4412516 */
src: url('//at.alicdn.com/t/c/font_4412516_cacqsbew46.woff2?t=1705720131974') format('woff2'),
url('//at.alicdn.com/t/c/font_4412516_cacqsbew46.woff?t=1705720131974') format('woff'),
url('//at.alicdn.com/t/c/font_4412516_cacqsbew46.ttf?t=1705720131974') format('truetype');
}
.o2o {
font-family: "o2o" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.o2o-icon-danhanghuadong:before {
content: "\e66f";
}
.o2o-icon-yuanjiao:before {
content: "\e6c0";
}
.o2o-icon-gl-square:before {
content: "\ea92";
}
.o2o-icon-sousuo12:before {
content: "\e699";
}
.o2o-icon-sousuo11:before {
content: "\e6d4";
}
.o2o-icon-jishi:before {
content: "\e600";
}

View File

@ -0,0 +1,51 @@
{
"id": "4412516",
"name": "上门服务",
"font_family": "o2o",
"css_prefix_text": "o2o-icon-",
"description": "",
"glyphs": [
{
"icon_id": "30621139",
"name": "单行滑动",
"font_class": "danhanghuadong",
"unicode": "e66f",
"unicode_decimal": 58991
},
{
"icon_id": "7149037",
"name": "圆角",
"font_class": "yuanjiao",
"unicode": "e6c0",
"unicode_decimal": 59072
},
{
"icon_id": "7594344",
"name": "20gl-square",
"font_class": "gl-square",
"unicode": "ea92",
"unicode_decimal": 60050
},
{
"icon_id": "10133070",
"name": "搜索",
"font_class": "sousuo12",
"unicode": "e699",
"unicode_decimal": 59033
},
{
"icon_id": "14652583",
"name": "搜索",
"font_class": "sousuo11",
"unicode": "e6d4",
"unicode_decimal": 59092
},
{
"icon_id": "6818781",
"name": "技师",
"font_class": "jishi",
"unicode": "e600",
"unicode_decimal": 58880
}
]
}

View File

@ -0,0 +1,58 @@
@font-face {
font-family: "tourism"; /* Project id 4137250 */
src: url('//at.alicdn.com/t/c/font_4137250_st1ha9l0k1e.woff2?t=1687685028672') format('woff2'),
url('//at.alicdn.com/t/c/font_4137250_st1ha9l0k1e.woff?t=1687685028672') format('woff'),
url('//at.alicdn.com/t/c/font_4137250_st1ha9l0k1e.ttf?t=1687685028672') format('truetype');
}
.tourism {
font-family: "tourism" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.tourism-icon-feiji:before {
content: "\e600";
}
.tourism-icon-lvyou:before {
content: "\e6a9";
}
.tourism-icon-lvyouchanpin:before {
content: "\e63b";
}
.tourism-icon-lvyou1:before {
content: "\e623";
}
.tourism-icon-lvyou2:before {
content: "\e601";
}
.tourism-icon-lvyou3:before {
content: "\e60c";
}
.tourism-icon-lvyoubaochedingdan:before {
content: "\e612";
}
.tourism-icon-lvyou4:before {
content: "\e653";
}
.tourism-icon-lvyou5:before {
content: "\e610";
}
.tourism-icon-lvyouguanguang:before {
content: "\e87e";
}
.tourism-icon-lvyou6:before {
content: "\e642";
}

View File

@ -0,0 +1,86 @@
{
"id": "4137250",
"name": "旅游业",
"font_family": "tourism",
"css_prefix_text": "tourism-icon-",
"description": "",
"glyphs": [
{
"icon_id": "1443",
"name": "飞机",
"font_class": "feiji",
"unicode": "e600",
"unicode_decimal": 58880
},
{
"icon_id": "446824",
"name": "旅游",
"font_class": "lvyou",
"unicode": "e6a9",
"unicode_decimal": 59049
},
{
"icon_id": "1167173",
"name": "旅游产品",
"font_class": "lvyouchanpin",
"unicode": "e63b",
"unicode_decimal": 58939
},
{
"icon_id": "1354920",
"name": "旅游",
"font_class": "lvyou1",
"unicode": "e623",
"unicode_decimal": 58915
},
{
"icon_id": "1505555",
"name": "旅游",
"font_class": "lvyou2",
"unicode": "e601",
"unicode_decimal": 58881
},
{
"icon_id": "2121726",
"name": "旅游",
"font_class": "lvyou3",
"unicode": "e60c",
"unicode_decimal": 58892
},
{
"icon_id": "2357494",
"name": "旅游包车订单",
"font_class": "lvyoubaochedingdan",
"unicode": "e612",
"unicode_decimal": 58898
},
{
"icon_id": "3944019",
"name": "旅游",
"font_class": "lvyou4",
"unicode": "e653",
"unicode_decimal": 58963
},
{
"icon_id": "4838220",
"name": "旅游",
"font_class": "lvyou5",
"unicode": "e610",
"unicode_decimal": 58896
},
{
"icon_id": "7444178",
"name": "旅游观光",
"font_class": "lvyouguanguang",
"unicode": "e87e",
"unicode_decimal": 59518
},
{
"icon_id": "9748082",
"name": "旅游",
"font_class": "lvyou6",
"unicode": "e642",
"unicode_decimal": 58946
}
]
}

View File

@ -42,11 +42,6 @@
<artifactId>spring-boot-starter-actuator</artifactId> <artifactId>spring-boot-starter-actuator</artifactId>
</dependency> </dependency>
--> -->
<!-- SpringBoot==>security其它组件依赖了类库 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency> <dependency>
<groupId>jakarta.servlet</groupId> <groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId> <artifactId>jakarta.servlet-api</artifactId>
@ -348,6 +343,11 @@
<version>1.4.0</version> <version>1.4.0</version>
</dependency> </dependency>
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java-sms</artifactId>
</dependency>
<!-- 阿里云短信 --> <!-- 阿里云短信 -->
<dependency> <dependency>
<groupId>com.aliyun</groupId> <groupId>com.aliyun</groupId>

View File

@ -68,7 +68,7 @@ public final class WebAppEnvs {
} else { } else {
appEnvs = new WebAppEnvs(); appEnvs = new WebAppEnvs();
appEnvs.envType = "prod"; appEnvs.envType = "prod";
appEnvs.webRoot = RuntimeTools.getWebRootPath(); appEnvs.webRoot = RuntimeTools.getWebRootPath() + "/";
File webRootFile = new File(appEnvs.webRoot); File webRootFile = new File(appEnvs.webRoot);
appEnvs.projectRoot = webRootFile.getParent(); appEnvs.projectRoot = webRootFile.getParent();
appEnvs.projectNiucloudAddon = appEnvs.projectRoot + "/niucloud-addon/"; appEnvs.projectNiucloudAddon = appEnvs.projectRoot + "/niucloud-addon/";

View File

@ -49,7 +49,7 @@ public class GlobalConfig {
/** /**
* 版本 * 版本
*/ */
public static String version = "0.0.3"; public static String version = "0.0.4";
/** /**
* 应用key * 应用key

View File

@ -12,9 +12,6 @@ import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource; import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.socket.server.standard.ServerEndpointExporter; import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration @Configuration
@ -76,16 +73,6 @@ public class NiuCoreConfig {
return new ServerEndpointExporter(); return new ServerEndpointExporter();
} }
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authorize) -> authorize
.anyRequest().permitAll()
)
.csrf().disable();
return http.build();
}
@Bean("coreMessageSource") @Bean("coreMessageSource")
public MessageSource coreMessageSource() { public MessageSource coreMessageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();

View File

@ -1,29 +0,0 @@
package com.niu.core.common.config.dataization;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.securityContext(securityContext -> securityContext
.requireExplicitSave(false)
)
.headers(headers -> headers
.contentSecurityPolicy(csp -> csp
.policyDirectives("frame-ancestors *")
)
)
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(auth -> auth
.anyRequest().permitAll()
);
;
return http.build();
}
}

View File

@ -9,6 +9,7 @@ import com.niu.core.service.core.pay.vo.PayTypeVo;
import com.niu.core.common.loader.pay.param.PayAsyncNotifyParam; import com.niu.core.common.loader.pay.param.PayAsyncNotifyParam;
import com.niu.core.common.loader.pay.param.PayParam; import com.niu.core.common.loader.pay.param.PayParam;
import com.niu.core.service.core.pay.vo.TransferQueryVo;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
@ -62,7 +63,17 @@ public abstract class BasePay {
/** /**
* 转账 * 转账
*/ */
public abstract void transfer(TransferParam param); public abstract Object transfer(TransferParam param);
/**
* 转账取消
*/
public abstract Object transferCancel(String transferNo);
/**
* 转账查询
*/
public abstract TransferQueryVo transferQuery(String transferNo);
/** /**
* 退款 * 退款

View File

@ -10,6 +10,7 @@ import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.SimpleColumnWidthStyleStrategy; import com.alibaba.excel.write.style.column.SimpleColumnWidthStyleStrategy;
import com.niu.core.common.component.context.SpringContext; import com.niu.core.common.component.context.SpringContext;
import com.niu.core.common.component.context.task.ThreadPoolManager; import com.niu.core.common.component.context.task.ThreadPoolManager;
import com.niu.core.common.utils.file.FileTools;
import com.niu.core.entity.sys.SysExport; import com.niu.core.entity.sys.SysExport;
import com.niu.core.mapper.sys.SysExportMapper; import com.niu.core.mapper.sys.SysExportMapper;
import org.apache.poi.ss.usermodel.IndexedColors; import org.apache.poi.ss.usermodel.IndexedColors;
@ -33,6 +34,8 @@ public class BusinessExcelUtil {
List<List<String>> head = new ArrayList<>(); List<List<String>> head = new ArrayList<>();
// 设置文件名称和文件路径 // 设置文件名称和文件路径
String filePath = exportDynamic.getFilePath(); String filePath = exportDynamic.getFilePath();
FileTools.createDirs(filePath);
String fileName = filePath + exportDynamic.getFileName(); String fileName = filePath + exportDynamic.getFileName();
// 设置动态表头 // 设置动态表头
if (!CollectionUtils.isEmpty(exportDynamic.getHeads())) { if (!CollectionUtils.isEmpty(exportDynamic.getHeads())) {

View File

@ -1,10 +1,9 @@
package com.niu.core.common.utils.crypto; package com.niu.core.common.utils.crypto;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import cn.hutool.crypto.digest.BCrypt;
public class PasswordEncipher { public class PasswordEncipher {
private static BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
/** /**
* 生成密码 * 生成密码
@ -12,7 +11,7 @@ public class PasswordEncipher {
* @return * @return
*/ */
public static String encode(String text) { public static String encode(String text) {
return passwordEncoder.encode(text); return BCrypt.hashpw(text);
} }
/** /**
@ -22,7 +21,7 @@ public class PasswordEncipher {
* @return * @return
*/ */
public static boolean matche(String text, String passwd) { public static boolean matche(String text, String passwd) {
return passwordEncoder.matches(text, passwd); return BCrypt.checkpw(text, passwd);
} }
} }

View File

@ -1,85 +0,0 @@
package com.niu.core.controller.adminapi.member;
import cn.dev33.satoken.annotation.SaCheckLogin;
import com.niu.core.common.domain.Result;
import com.niu.core.common.domain.PageResult;
import com.niu.core.service.admin.member.IMemberCashOutAccountService;
import com.niu.core.service.admin.member.param.MemberCashOutAccountParam;
import com.niu.core.service.admin.member.param.MemberCashOutAccountSearchParam;
import com.niu.core.service.admin.member.vo.MemberCashOutAccountInfoVo;
import com.niu.core.service.admin.member.vo.MemberCashOutAccountListVo;
import com.niu.core.common.domain.PageParam;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
/**
* 会员提现账户控制器
*/
@RestController
@RequestMapping("adminapi/member_cash_out_account")
@SaCheckLogin
public class MemberCashOutAccountController {
@Resource
IMemberCashOutAccountService memberCashOutAccountService;
/**
* 会员提现账户列表
* @param pageParam 分页
* @param searchParam 搜索条件
* @return Result<PageResult<MemberCashOutAccountListVo>>
*/
@GetMapping("/list")
public Result<PageResult<MemberCashOutAccountListVo>> list(@Validated PageParam pageParam,
@Validated MemberCashOutAccountSearchParam searchParam) {
PageResult<MemberCashOutAccountListVo> list = memberCashOutAccountService.list(pageParam, searchParam);
return Result.success(list);
}
/**
* 会员提现账户详情
* @param id 主键ID
* @return Result<MemberCashOutAccountInfoVo>
*/
@GetMapping("/info")
public Result<MemberCashOutAccountInfoVo> info(@Validated @RequestParam("id") Integer id) {
MemberCashOutAccountInfoVo info = memberCashOutAccountService.info(id);
return Result.success(info);
}
/**
* 会员提现账户添加
* @param addParam 添加参数
* @return Result<Object>
*/
@PostMapping("/add")
public Result<Object> add(@Validated @RequestBody MemberCashOutAccountParam addParam) {
memberCashOutAccountService.add(addParam);
return Result.success();
}
/**
* 会员提现账户编辑
* @param editParam 编辑参数
* @return Result<Object>
*/
@PostMapping("/edit")
public Result<Object> edit(Integer id, @Validated @RequestBody MemberCashOutAccountParam editParam) {
memberCashOutAccountService.edit(id, editParam);
return Result.success();
}
/**
* 会员提现账户删除
* @param id 参数
* @return Result<Object>
*/
@PostMapping("/del")
public Result<Object> del(@Validated @RequestBody Integer id) {
memberCashOutAccountService.del(id);
return Result.success();
}
}

View File

@ -6,10 +6,7 @@ import com.niu.core.common.domain.PageResult;
import com.niu.core.enums.member.MemberCashOutStatusEnum; import com.niu.core.enums.member.MemberCashOutStatusEnum;
import com.niu.core.enums.pay.TransferTypeEnum; import com.niu.core.enums.pay.TransferTypeEnum;
import com.niu.core.service.admin.member.IMemberCashOutService; import com.niu.core.service.admin.member.IMemberCashOutService;
import com.niu.core.service.admin.member.param.CashOutTransferParam; import com.niu.core.service.admin.member.param.*;
import com.niu.core.service.admin.member.param.MemberCashOutAuditParam;
import com.niu.core.service.admin.member.param.MemberCashOutParam;
import com.niu.core.service.admin.member.param.MemberCashOutSearchParam;
import com.niu.core.service.admin.member.vo.CashOutStatVo; import com.niu.core.service.admin.member.vo.CashOutStatVo;
import com.niu.core.service.admin.member.vo.MemberCashOutInfoVo; import com.niu.core.service.admin.member.vo.MemberCashOutInfoVo;
import com.niu.core.service.admin.member.vo.MemberCashOutListVo; import com.niu.core.service.admin.member.vo.MemberCashOutListVo;
@ -75,6 +72,28 @@ public class MemberCashOutController {
return Result.success(); return Result.success();
} }
/**
* 会员提现取消
* @param id
* @return
*/
@PutMapping("/cancel/{id}")
public Result cancel(@PathVariable(name = "id") Integer id) {
memberCashOutService.cancel(id);
return Result.success();
}
/**
* 备注
* @param id
* @return
*/
@PutMapping("/remark/{id}")
public Result remark(@PathVariable(name = "id") Integer id, @RequestBody MemberCashOutRemarkParam param) {
memberCashOutService.remark(id, param);
return Result.success();
}
/** /**
* 转账方式 * 转账方式
*/ */
@ -103,4 +122,15 @@ public class MemberCashOutController {
CashOutStatVo data = memberCashOutService.stat(); CashOutStatVo data = memberCashOutService.stat();
return Result.success(data); return Result.success(data);
} }
/**
* 检测转账状态
* @param id
* @return
*/
@PutMapping("/check/{id}")
public Result checkTransferStatus(@PathVariable("id") Integer id) {
memberCashOutService.checkTransferStatus(id);
return Result.success();
}
} }

View File

@ -6,9 +6,11 @@ import com.niu.core.common.domain.PageResult;
import com.niu.core.service.admin.pay.IPayTransferService; import com.niu.core.service.admin.pay.IPayTransferService;
import com.niu.core.service.admin.pay.param.PayTransferParam; import com.niu.core.service.admin.pay.param.PayTransferParam;
import com.niu.core.service.admin.pay.param.PayTransferSearchParam; import com.niu.core.service.admin.pay.param.PayTransferSearchParam;
import com.niu.core.service.admin.pay.param.SetSceneIdParam;
import com.niu.core.service.admin.pay.vo.PayTransferInfoVo; import com.niu.core.service.admin.pay.vo.PayTransferInfoVo;
import com.niu.core.service.admin.pay.vo.PayTransferListVo; import com.niu.core.service.admin.pay.vo.PayTransferListVo;
import com.niu.core.common.domain.PageParam; import com.niu.core.common.domain.PageParam;
import com.niu.core.service.core.pay.param.SetTradeSceneParam;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@ -18,7 +20,7 @@ import jakarta.annotation.Resource;
*/ */
@RestController @RestController
@RequestMapping("adminapi/transfer") @RequestMapping("adminapi/pay")
@SaCheckLogin @SaCheckLogin
public class PayTransferController { public class PayTransferController {
@ -26,60 +28,32 @@ public class PayTransferController {
IPayTransferService payTransferService; IPayTransferService payTransferService;
/** /**
* 转账列表 * 获取转账场景
* @param pageParam 分页 * @return
* @param searchParam 搜索条件
* @return Result<PageResult<PayTransferListVo>>
*/ */
@GetMapping("/list") @GetMapping("/transfer_scene")
public Result<PageResult<PayTransferListVo>> list(@Validated PageParam pageParam, public Result<?> transferScene() {
@Validated PayTransferSearchParam searchParam) { return Result.success(payTransferService.getWechatTransferScene());
PageResult<PayTransferListVo> list = payTransferService.list(pageParam, searchParam);
return Result.success(list);
} }
/** /**
* 转账详情 * 设置场景id
* @param id 主键ID * @return
* @return Result<PayTransferInfoVo>
*/ */
@GetMapping("/info") @PostMapping("/transfer_scene/set_scene_id/{scene}")
public Result<PayTransferInfoVo> info(@Validated @RequestParam("id") Integer id) { public Result<?> setSceneId(@PathVariable("scene") String scene, @Validated @RequestBody SetSceneIdParam param) {
PayTransferInfoVo info = payTransferService.info(id); param.setScene(scene);
return Result.success(info); payTransferService.setSceneId(param);
}
/**
* 转账添加
* @param addParam 添加参数
* @return Result<Object>
*/
@PostMapping("/add")
public Result<Object> add(@Validated @RequestBody PayTransferParam addParam) {
payTransferService.add(addParam);
return Result.success(); return Result.success();
} }
/** /**
* 转账编辑 * 设置业务场景配置
* @param editParam 编辑参数 * @return
* @return Result<Object>
*/ */
@PostMapping("/edit") @PostMapping("/transfer_scene/set_trade_scene/{type}")
public Result<Object> edit(Integer id, @Validated @RequestBody PayTransferParam editParam) { public Result<?> setTradeScene(@PathVariable("type") String type, @RequestBody SetTradeSceneParam param) {
payTransferService.edit(id, editParam); payTransferService.setTradeScene(param);
return Result.success(); return Result.success();
} }
/**
* 转账删除
* @param id 参数
* @return Result<Object>
*/
@PostMapping("/del")
public Result<Object> del(@Validated @RequestBody Integer id) {
payTransferService.del(id);
return Result.success();
}
} }

View File

@ -0,0 +1,35 @@
package com.niu.core.controller.adminapi.sys;
import cn.dev33.satoken.annotation.SaCheckLogin;
import com.niu.core.common.domain.Result;
import com.niu.core.service.admin.sys.ISystemService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 系统控制器
*/
@RestController
@RequestMapping("adminapi/sys")
@SaCheckLogin
public class SystemController {
@Resource
ISystemService systemService;
/**
* 清理缓存
* @return
*/
@PostMapping("/cache/clear")
public Result<?> clearCache() {
systemService.clearCache();
return Result.success();
}
}

View File

@ -9,6 +9,7 @@ import com.niu.core.common.domain.Result;
import com.niu.core.service.admin.wxoplatform.IOplatformConfigService; import com.niu.core.service.admin.wxoplatform.IOplatformConfigService;
import com.niu.core.service.admin.wxoplatform.IWeappVersionService; import com.niu.core.service.admin.wxoplatform.IWeappVersionService;
import com.niu.core.service.admin.wxoplatform.param.OplatformConfigParam; import com.niu.core.service.admin.wxoplatform.param.OplatformConfigParam;
import com.niu.core.service.admin.wxoplatform.vo.SiteGroupWeappVersionVo;
import com.niu.core.service.admin.wxoplatform.vo.WxOplatfromWeappVersionVo; import com.niu.core.service.admin.wxoplatform.vo.WxOplatfromWeappVersionVo;
import com.niu.core.service.core.wxoplatform.vo.CoreOplatformStaticConfigVo; import com.niu.core.service.core.wxoplatform.vo.CoreOplatformStaticConfigVo;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -17,6 +18,7 @@ import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.Map;
@RestController @RestController
@RequestMapping("adminapi/wxoplatform") @RequestMapping("adminapi/wxoplatform")
@ -54,8 +56,9 @@ public class WeappVersionController {
* @return * @return
*/ */
@PostMapping("/weapp/version/commit") @PostMapping("/weapp/version/commit")
public Result weappCommit(){ public Result weappCommit(@RequestBody Map<String, Object> params){
weappVersionService.add(null); Integer siteGroupId = ObjectUtil.isEmpty(params.get("site_group_id")) ? 0 : (Integer) params.get("site_group_id");
weappVersionService.add(siteGroupId, siteGroupId == 0);
return Result.success(); return Result.success();
} }
@ -69,4 +72,16 @@ public class WeappVersionController {
weappVersionService.siteWeappCommit(); weappVersionService.siteWeappCommit();
return Result.success(); return Result.success();
} }
/**
* 按站点套餐获取提交记录
*
* @param pageParam
* @return
*/
@GetMapping("/sitegroup/commit")
public Result<PageResult<SiteGroupWeappVersionVo>> getSiteGroupCommitRecord(@Validated PageParam pageParam){
return Result.success(weappVersionService.getSiteGroupCommitRecord(pageParam));
}
} }

View File

@ -4,6 +4,7 @@ import cn.dev33.satoken.annotation.SaCheckLogin;
import com.niu.core.common.domain.PageParam; import com.niu.core.common.domain.PageParam;
import com.niu.core.common.domain.Result; import com.niu.core.common.domain.Result;
import com.niu.core.common.utils.object.ObjectUtils; import com.niu.core.common.utils.object.ObjectUtils;
import com.niu.core.service.admin.member.param.CashOutTransferParam;
import com.niu.core.service.api.member.IMemberCashOutService; import com.niu.core.service.api.member.IMemberCashOutService;
import com.niu.core.service.api.member.param.*; import com.niu.core.service.api.member.param.*;
import com.niu.core.service.core.member.param.MemberCashOutApplyParam; import com.niu.core.service.core.member.param.MemberCashOutApplyParam;
@ -75,8 +76,7 @@ public class MemberCashOutController {
*/ */
@PostMapping("/cash_out/apply") @PostMapping("/cash_out/apply")
public Result<?> apply(@Validated @RequestBody MemberCashOutApplyParam param) { public Result<?> apply(@Validated @RequestBody MemberCashOutApplyParam param) {
memberCashOutService.cashOutApply(param); return Result.success("", memberCashOutService.cashOutApply(param));
return Result.success();
} }
/** /**
@ -92,6 +92,18 @@ public class MemberCashOutController {
return Result.success(); return Result.success();
} }
/**
* 提现转账
* @param id
* @param param
* @return
*/
@PostMapping("/cash_out/transfer/{id}")
public Result<?> transfer(@PathVariable("id") Integer id, @RequestBody CashOutTransferParam param) {
param.setId(id);
return Result.success(memberCashOutService.transfer(param));
}
/** /**
* 提现账号列表 * 提现账号列表
* *

View File

@ -47,6 +47,12 @@ public class MemberCashOut implements Serializable {
/** 收款账号 */ /** 收款账号 */
private String transferAccount; private String transferAccount;
/** 转账收款方(json),主要用于对接在线的打款方式 */
private String transferPayee;
/** 收款码图片 */
private String transferPaymentCode;
/** 失败原因 */ /** 失败原因 */
private String transferFailReason; private String transferFailReason;

View File

@ -38,4 +38,6 @@ public class MemberCashOutAccount implements Serializable {
/** 提现账户 */ /** 提现账户 */
private String accountNo; private String accountNo;
/** 收款码 */
private String transferPaymentCode;
} }

View File

@ -49,6 +49,12 @@ public class PayTransfer implements Serializable {
/** 收款账号 */ /** 收款账号 */
private String transferAccount; private String transferAccount;
/** 转账收款方(json),主要用于对接在线的打款方式 */
private String transferPayee;
/** 收款码图片 */
private String transferPaymentCode;
/** 凭证 */ /** 凭证 */
private String transferVoucher; private String transferVoucher;
@ -81,4 +87,12 @@ public class PayTransfer implements Serializable {
/** 转账批次id */ /** 转账批次id */
private String batchId; private String batchId;
/** 扩展数据,主要用于记录接收到线上打款的业务数据编号 */
private String outBatchNo;
/** 跳转领取页面的package信息 */
private String packageInfo;
/** 扩展信息 */
private String extra;
} }

View File

@ -0,0 +1,38 @@
package com.niu.core.entity.pay;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import lombok.Data;
/**
* 支付转账场景表实体
*/
@Data
public class PayTransferScene implements Serializable {
private static final long serialVersionUID = 1L;
/** 创建时间 */
private Long createTime;
/** 主键 */
@TableId(value="id", type= IdType.AUTO)
private Integer id;
/** 转账报备背景 */
private String infos;
/** 转账收款感知 */
private String perception;
/** 场景 */
private String scene;
/** 站点id */
private Integer siteId;
/** 业务类型 */
private String type;
}

View File

@ -11,6 +11,7 @@ import java.util.Map;
public enum MemberCashOutStatusEnum { public enum MemberCashOutStatusEnum {
WAIT_AUDIT("待审核", 1), WAIT_AUDIT("待审核", 1),
WAIT_TRANSFER("待转账", 2), WAIT_TRANSFER("待转账", 2),
TRANSFER_ING("转账中", 4),
TRANSFERED("已转账", 3), TRANSFERED("已转账", 3),
REFUSE("已拒绝", -1), REFUSE("已拒绝", -1),
CANCEL("已取消", -2); CANCEL("已取消", -2);

View File

@ -0,0 +1,55 @@
package com.niu.core.enums.pay;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 微信转账场景
*/
@Getter
@AllArgsConstructor
public enum TransferSceneEnum {
YJBC("yjbc", "佣金报酬", Arrays.asList("劳务报酬", "报销款", "企业补贴", "开工利是"), Arrays.asList("岗位类型", "报酬说明")),
XJYX("xjyx", "现金营销", Arrays.asList("活动奖励", "现金奖励"), Arrays.asList("活动名称", "奖励说明")),
QYPF("qypf", "企业赔付", Arrays.asList("退款", "商家赔付"), Arrays.asList("赔付原因")),
CGHK("cghk", "采购货款", Arrays.asList("货款"), Arrays.asList("采购商品名称")),
ESHS("eshs", "二手回收", Arrays.asList("二手回收货款"), Arrays.asList("回收商品名称")),
GYBZ("gybz", "公益补助", Arrays.asList("公益补助金"), Arrays.asList("公益活动名称", "公益活动备案编号")),
XZBT("xzbt", "行政补贴", Arrays.asList("行政补贴", "行政奖励"), Arrays.asList("补贴类型")),
BXLP("bxlp", "保险理赔", Arrays.asList("保险理赔款"), Arrays.asList("保险产品备案编号", "保险名称", "保险操作单号"));
private final String scene;
private final String name;
private final List<String> userRecvPerception;
private final List<String> transferSceneReportInfos;
public String getScene() {
return scene;
}
public String getName() {
return name;
}
public List<String> getUserRecvPerception() {
return userRecvPerception;
}
public List<String> getTransferSceneReportInfos() {
return transferSceneReportInfos;
}
public static java.util.Map<String, TransferSceneEnum> getWechatTransferSceneMap() {
java.util.Map<String, TransferSceneEnum> sceneMap = new java.util.HashMap<>();
for (TransferSceneEnum scene : values()) {
sceneMap.put(scene.getScene(), scene);
}
return sceneMap;
}
}

View File

@ -15,6 +15,9 @@ public enum TransferStatusEnum {
WAIT("待转账", "wait"), WAIT("待转账", "wait"),
DEALING("处理中", "dealing"), DEALING("处理中", "dealing"),
SUCCESS("转账成功", "success"), SUCCESS("转账成功", "success"),
WAIT_USER("等待用户确认", "wait_user"),
WAIT_USER_ING("用户确认转账中", "wait_user_ing"),
FAIL_ING("转账撤销中", "fail_ing"),
FAIL("转账失败", "fail"); FAIL("转账失败", "fail");
private final String name; private final String name;

View File

@ -14,10 +14,10 @@ import java.util.Map;
@AllArgsConstructor @AllArgsConstructor
public enum TransferTypeEnum { public enum TransferTypeEnum {
WECHATPAY("微信", "wechatpay", true), WECHATPAY("微信零钱", "wechatpay", true),
WECHAT_CODE("微信", "wechat_code", false),
ALIPAY("支付宝", "alipay", false), ALIPAY("支付宝", "alipay", false),
BALANCEPAY("银行卡", "bank", false), BALANCEPAY("银行卡", "bank", false);
OFFLINE("线下转账", "offline", false);
//转账方式名称 //转账方式名称
String name; String name;

View File

@ -20,7 +20,8 @@ public enum ConfigKeyEnum {
H5("h5"),//h5 H5("h5"),//h5
WXOPLATFORM("WXOPLATFORM"), // 微信开放平台 WXOPLATFORM("WXOPLATFORM"), // 微信开放平台
WEAPP_AUTHORIZATION_INFO("weapp_authorization_info"), WEAPP_AUTHORIZATION_INFO("weapp_authorization_info"),
WECHAT_AUTHORIZATION_INFO("wechat_authorization_info"); WECHAT_AUTHORIZATION_INFO("wechat_authorization_info"),
WECHAT_TRANSFER_SCENE_CONFIG("WECHAT_TRANSFER_SCENE_CONFIG");
private final String name; private final String name;
} }

View File

@ -0,0 +1,12 @@
package com.niu.core.mapper.pay;
import com.github.yulichang.base.MPJBaseMapper;
import com.niu.core.entity.pay.PayTransferScene;
import org.apache.ibatis.annotations.Mapper;
/**
* 支付转账场景表 Mapper
*/
@Mapper
public interface PayTransferSceneMapper extends MPJBaseMapper<PayTransferScene> {
}

View File

@ -1,50 +0,0 @@
package com.niu.core.service.admin.member;
import com.niu.core.common.domain.PageResult;
import com.niu.core.service.admin.member.param.MemberCashOutAccountParam;
import com.niu.core.service.admin.member.param.MemberCashOutAccountSearchParam;
import com.niu.core.common.domain.PageParam;
import com.niu.core.service.admin.member.vo.MemberCashOutAccountInfoVo;
import com.niu.core.service.admin.member.vo.MemberCashOutAccountListVo;
/**
* 会员提现账户服务接口
*/
public interface IMemberCashOutAccountService {
/**
* 会员提现账户列表
* @param pageParam 分页参数
* @param searchParam 搜索参数
* @return PageResult<MemberCashOutAccountListVo>
*/
PageResult<MemberCashOutAccountListVo> list(PageParam pageParam, MemberCashOutAccountSearchParam searchParam);
/**
* 会员提现账户详情
* @param id 主键ID
* @return MemberCashOutAccountInfoVo
*/
MemberCashOutAccountInfoVo info(Integer id);
/**
* 会员提现账户添加
* @param addParam 添加参数
*/
void add(MemberCashOutAccountParam addParam);
/**
* 会员提现账户编辑
* @param id 主键
* @param editParam 编辑参数
*/
void edit(Integer id, MemberCashOutAccountParam editParam);
/**
* 会员提现账户删除
* @param id 主键ID
*/
void del(Integer id);
}

View File

@ -1,10 +1,7 @@
package com.niu.core.service.admin.member; package com.niu.core.service.admin.member;
import com.niu.core.common.domain.PageResult; import com.niu.core.common.domain.PageResult;
import com.niu.core.service.admin.member.param.CashOutTransferParam; import com.niu.core.service.admin.member.param.*;
import com.niu.core.service.admin.member.param.MemberCashOutAuditParam;
import com.niu.core.service.admin.member.param.MemberCashOutParam;
import com.niu.core.service.admin.member.param.MemberCashOutSearchParam;
import com.niu.core.common.domain.PageParam; import com.niu.core.common.domain.PageParam;
import com.niu.core.service.admin.member.vo.CashOutStatVo; import com.niu.core.service.admin.member.vo.CashOutStatVo;
import com.niu.core.service.admin.member.vo.MemberCashOutInfoVo; import com.niu.core.service.admin.member.vo.MemberCashOutInfoVo;
@ -45,4 +42,23 @@ public interface IMemberCashOutService {
* 转账 * 转账
*/ */
void transfer(CashOutTransferParam param); void transfer(CashOutTransferParam param);
/**
* 撤销提现
* @param id
*/
void cancel(Integer id);
/**
* 备注
* @param id
* @param param
*/
void remark(Integer id, MemberCashOutRemarkParam param);
/**
* 检测转账状态
* @param
*/
void checkTransferStatus(Integer id);
} }

View File

@ -1,134 +0,0 @@
package com.niu.core.service.admin.member.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.niu.core.common.domain.PageResult;
import com.niu.core.common.domain.PageParam;
import com.niu.core.entity.member.MemberCashOutAccount;
import com.niu.core.mapper.member.MemberCashOutAccountMapper;
import com.niu.core.service.admin.member.param.MemberCashOutAccountParam;
import com.niu.core.service.admin.member.param.MemberCashOutAccountSearchParam;
import com.niu.core.service.admin.member.IMemberCashOutAccountService;
import com.niu.core.service.admin.member.vo.MemberCashOutAccountInfoVo;
import com.niu.core.service.admin.member.vo.MemberCashOutAccountListVo;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import jakarta.annotation.Resource;
import java.util.LinkedList;
import java.util.List;
/**
* 会员提现账户实现
*/
@Service
public class MemberCashOutAccountServiceImpl implements IMemberCashOutAccountService {
@Resource
MemberCashOutAccountMapper memberCashOutAccountMapper;
/**
* 会员提现账户列表
* @param pageParam 分页参数
* @param searchParam 搜索参数
* @return PageResult<MemberCashOutAccountListVo>
*/
@Override
public PageResult<MemberCashOutAccountListVo> list(PageParam pageParam, MemberCashOutAccountSearchParam searchParam) {
Integer page = pageParam.getPage();
Integer limit =pageParam.getLimit();
QueryWrapper<MemberCashOutAccount> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("account_id");
IPage<MemberCashOutAccount> iPage = memberCashOutAccountMapper.selectPage(new Page<>(page, limit), queryWrapper);
List<MemberCashOutAccountListVo> list = new LinkedList<>();
for (MemberCashOutAccount item : iPage.getRecords()) {
MemberCashOutAccountListVo vo = new MemberCashOutAccountListVo();
BeanUtils.copyProperties(item, vo);
list.add(vo);
}
return PageResult.build(page, limit, iPage.getTotal()).setData(list);
}
/**
* 会员提现账户详情
* @param id 主键
* @return MemberCashOutAccountInfoVo
*/
@Override
public MemberCashOutAccountInfoVo info(Integer id) {
MemberCashOutAccount model = memberCashOutAccountMapper.selectOne(
new QueryWrapper<MemberCashOutAccount>()
.eq("account_id", id)
.last("limit 1"));
Assert.notNull(model, "数据不存在");
MemberCashOutAccountInfoVo vo = new MemberCashOutAccountInfoVo();
BeanUtils.copyProperties(model, vo);
return vo;
}
/**
* 会员提现账户添加
* @param addParam 参数
*/
@Override
public void add(MemberCashOutAccountParam addParam) {
MemberCashOutAccount model = new MemberCashOutAccount();
model.setSiteId(addParam.getSiteId());
model.setMemberId(addParam.getMemberId());
model.setAccountType(addParam.getAccountType());
model.setBankName(addParam.getBankName());
model.setRealname(addParam.getRealname());
model.setCreateTime(System.currentTimeMillis() / 1000);
model.setUpdateTime(System.currentTimeMillis() / 1000);
model.setAccountNo(addParam.getAccountNo());
memberCashOutAccountMapper.insert(model);
}
/**
* 会员提现账户编辑
*
* @param editParam 参数
*/
@Override
public void edit(Integer id, MemberCashOutAccountParam editParam) {
MemberCashOutAccount model = memberCashOutAccountMapper.selectOne(
new QueryWrapper<MemberCashOutAccount>()
.eq("account_id", id)
.last("limit 1"));
Assert.notNull(model, "数据不存在!");
model.setAccountId(id);
model.setAccountId(editParam.getAccountId());
model.setSiteId(editParam.getSiteId());
model.setMemberId(editParam.getMemberId());
model.setAccountType(editParam.getAccountType());
model.setBankName(editParam.getBankName());
model.setRealname(editParam.getRealname());
model.setUpdateTime(System.currentTimeMillis() / 1000);
model.setAccountNo(editParam.getAccountNo());
memberCashOutAccountMapper.updateById(model);
}
/**
* 会员提现账户删除
* @param id 主键ID
*/
@Override
public void del(Integer id) {
MemberCashOutAccount model = memberCashOutAccountMapper.selectOne(
new QueryWrapper<MemberCashOutAccount>()
.eq("account_id", id)
.last("limit 1"));
Assert.notNull(model, "数据不存在!");
memberCashOutAccountMapper.delete(new QueryWrapper<MemberCashOutAccount>().eq("account_id", id));
}
}

View File

@ -17,6 +17,7 @@ import com.niu.core.mapper.member.MemberCashOutMapper;
import com.niu.core.mapper.member.MemberMapper; import com.niu.core.mapper.member.MemberMapper;
import com.niu.core.service.admin.member.param.CashOutTransferParam; import com.niu.core.service.admin.member.param.CashOutTransferParam;
import com.niu.core.service.admin.member.param.MemberCashOutAuditParam; import com.niu.core.service.admin.member.param.MemberCashOutAuditParam;
import com.niu.core.service.admin.member.param.MemberCashOutRemarkParam;
import com.niu.core.service.admin.member.param.MemberCashOutSearchParam; import com.niu.core.service.admin.member.param.MemberCashOutSearchParam;
import com.niu.core.service.admin.member.IMemberCashOutService; import com.niu.core.service.admin.member.IMemberCashOutService;
import com.niu.core.service.admin.member.vo.*; import com.niu.core.service.admin.member.vo.*;
@ -78,19 +79,13 @@ public class MemberCashOutServiceImpl implements IMemberCashOutService {
if (ObjectUtil.isNotEmpty(searchParam.getCreateTime())) QueryMapperUtils.buildByTime(queryWrapper, "mco.create_time", searchParam.getCreateTime()); if (ObjectUtil.isNotEmpty(searchParam.getCreateTime())) QueryMapperUtils.buildByTime(queryWrapper, "mco.create_time", searchParam.getCreateTime());
if (ObjectUtil.isNotEmpty(searchParam.getTransferTime())) QueryMapperUtils.buildByTime(queryWrapper, "mco.transfer_time", searchParam.getTransferTime()); if (ObjectUtil.isNotEmpty(searchParam.getTransferTime())) QueryMapperUtils.buildByTime(queryWrapper, "mco.transfer_time", searchParam.getTransferTime());
IPage<MemberCashOutVo> iPage = memberCashOutMapper.selectJoinPage(new Page<>(page, limit), MemberCashOutVo.class, queryWrapper); IPage<MemberCashOutListVo> iPage = memberCashOutMapper.selectJoinPage(new Page<>(page, limit), MemberCashOutListVo.class, queryWrapper);
List<MemberCashOutListVo> list = new LinkedList<>(); for (MemberCashOutListVo item : iPage.getRecords()) {
for (MemberCashOutVo item : iPage.getRecords()) {
MemberCashOutListVo vo = new MemberCashOutListVo();
BeanUtils.copyProperties(item, vo);
MemberBriefInfoVo memberInfoVo = new MemberBriefInfoVo(); MemberBriefInfoVo memberInfoVo = new MemberBriefInfoVo();
BeanUtils.copyProperties(item, memberInfoVo); BeanUtils.copyProperties(item, memberInfoVo);
vo.setMember(memberInfoVo); item.setMember(memberInfoVo);
list.add(vo);
} }
return PageResult.build(page, limit, iPage.getTotal()).setData(list); return PageResult.build(page, limit, iPage.getTotal()).setData(iPage.getRecords());
} }
/** /**
@ -102,24 +97,24 @@ public class MemberCashOutServiceImpl implements IMemberCashOutService {
public MemberCashOutInfoVo info(Integer id) { public MemberCashOutInfoVo info(Integer id) {
Integer siteId = RequestUtils.siteId(); Integer siteId = RequestUtils.siteId();
MemberCashOut model = memberCashOutMapper.selectOne( MemberCashOutInfoVo vo = memberCashOutMapper.selectJoinOne(
new QueryWrapper<MemberCashOut>() MemberCashOutInfoVo.class,
.eq("id", id) new MPJQueryWrapper<MemberCashOut>()
.eq("site_id", siteId) .select("mco.*,m.member_no,m.username,m.nickname,m.mobile,m.headimg,pt.transfer_voucher,pt.transfer_remark")
.last("limit 1")); .eq("mco.id", id)
.eq("mco.site_id", siteId)
.setAlias("mco")
.leftJoin("?_member m ON mco.member_id = m.member_id".replace("?_", GlobalConfig.tablePrefix))
.leftJoin("?_pay_transfer pt ON mco.transfer_no = pt.transfer_no".replace("?_", GlobalConfig.tablePrefix))
);
Assert.notNull(model, "数据不存在"); if (vo != null) {
MemberCashOutInfoVo.Transfer transfer = new MemberCashOutInfoVo.Transfer();
MemberCashOutInfoVo vo = new MemberCashOutInfoVo(); transfer.setTransferNo(vo.getTransferNo());
BeanUtils.copyProperties(model, vo); transfer.setTransferRemark(vo.getTransferRemark());
transfer.setTransferVoucher(vo.getTransferVoucher());
Member member = memberMapper.selectOne(new QueryWrapper<Member>() vo.setTransfer(transfer);
.eq("member_id", model.getMemberId()) }
.eq("site_id", siteId));
MemberBriefInfoVo memberVo = new MemberBriefInfoVo();
BeanUtils.copyProperties(member, memberVo);
vo.setMemberInfo(memberVo);
return vo; return vo;
} }
@ -182,4 +177,40 @@ public class MemberCashOutServiceImpl implements IMemberCashOutService {
iCoreMemberCashOutService.transfer(model, param); iCoreMemberCashOutService.transfer(model, param);
} }
/**
* 撤销提现
* @param id
*/
@Override
public void cancel(Integer id) {
iCoreMemberCashOutService.cancel(RequestUtils.siteId(), id);
}
/**
* 备注
* @param id
* @param param
*/
@Override
public void remark(Integer id, MemberCashOutRemarkParam param) {
MemberCashOut model = memberCashOutMapper.selectOne(
new QueryWrapper<MemberCashOut>()
.eq("id", id)
.eq("site_id", RequestUtils.siteId())
);
Assert.notNull(model, "数据不存在");
model.setRemark(param.getRemark());
memberCashOutMapper.updateById(model);
}
/**
* 检测转账状态
* @param id
*/
@Override
public void checkTransferStatus(Integer id) {
iCoreMemberCashOutService.checkTransferStatus(RequestUtils.siteId(), id);
}
} }

View File

@ -16,7 +16,7 @@ public class CashOutConfigParam implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@NotNull(message = "is_open参数缺失") @NotNull(message = "is_open参数缺失")
private Integer isOpen = 0; // 是否启用提现 private String isOpen = "0"; // 是否启用提现
@NotNull(message = "transfer_type参数缺失") @NotNull(message = "transfer_type参数缺失")
private LinkedList<String> transferType = new LinkedList<String>(); // 提现方式 private LinkedList<String> transferType = new LinkedList<String>(); // 提现方式

View File

@ -24,4 +24,7 @@ public class CashOutTransferParam implements Serializable {
@NotNull(message = "transfer_type参数缺失") @NotNull(message = "transfer_type参数缺失")
private String transferType; private String transferType;
private String openId = "";
private String channel = "";
} }

View File

@ -0,0 +1,19 @@
package com.niu.core.service.admin.member.param;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 会员提现参数
*/
@Data
public class MemberCashOutRemarkParam implements Serializable {
private static final long serialVersionUID = 1L;
private String remark;
}

View File

@ -13,7 +13,7 @@ public class CashOutConfigVo implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private Integer isOpen = 0; // 是否启用提现 private String isOpen = "0"; // 是否启用提现
private LinkedList<String> transferType = new LinkedList<String>(); // 提现方式 private LinkedList<String> transferType = new LinkedList<String>(); // 提现方式
private BigDecimal min = BigDecimal.ZERO; // 最低提现金额 private BigDecimal min = BigDecimal.ZERO; // 最低提现金额
private BigDecimal rate = BigDecimal.ZERO; // 手续费比率 private BigDecimal rate = BigDecimal.ZERO; // 手续费比率

View File

@ -1,4 +1,6 @@
package com.niu.core.service.admin.member.vo; package com.niu.core.service.admin.member.vo;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.niu.core.common.domain.BeanJsonSerializer;
import com.niu.core.enums.member.AccountTypeEnum; import com.niu.core.enums.member.AccountTypeEnum;
import com.niu.core.enums.member.MemberCashOutStatusEnum; import com.niu.core.enums.member.MemberCashOutStatusEnum;
import com.niu.core.enums.pay.TransferStatusEnum; import com.niu.core.enums.pay.TransferStatusEnum;
@ -31,23 +33,36 @@ public class MemberCashOutInfoVo implements Serializable {
private String transferAccount; // 收款账号 private String transferAccount; // 收款账号
private String transferFailReason; // 失败原因 private String transferFailReason; // 失败原因
private String transferStatus; // 转账状态 private String transferStatus; // 转账状态
private Integer transferTime; // 转账时间 private String transferPaymentCode; // 转账支付码
@JsonSerialize(using = BeanJsonSerializer.LongDateToStringSerializer.class)
private Long transferTime; // 转账时间
private BigDecimal applyMoney; // 提现申请金额 private BigDecimal applyMoney; // 提现申请金额
private BigDecimal rate; // 提现手续费比率 private BigDecimal rate; // 提现手续费比率
private BigDecimal serviceMoney; // 提现手续费 private BigDecimal serviceMoney; // 提现手续费
private BigDecimal money; // 提现到账金额 private BigDecimal money; // 提现到账金额
private Integer auditTime; // 审核时间 @JsonSerialize(using = BeanJsonSerializer.LongDateToStringSerializer.class)
private Long auditTime; // 审核时间
private Integer status; // 状态1待审核2.待转账3已转账 -1拒绝 -2 已取消 private Integer status; // 状态1待审核2.待转账3已转账 -1拒绝 -2 已取消
private String remark; // 备注 private String remark; // 备注
private String refuseReason; // 拒绝理由 private String refuseReason; // 拒绝理由
private String transferNo; // 转账单号 private String transferNo; // 转账单号
private Integer cancelTime; // 取消时间 @JsonSerialize(using = BeanJsonSerializer.LongDateToStringSerializer.class)
private Long cancelTime; // 取消时间
private String finalTransferType; // 转账方式 private String finalTransferType; // 转账方式
private String statusName; private String statusName;
private String transferTypeName; private String transferTypeName;
private String transferStatusName; private String transferStatusName;
private String accountTypeName; private String accountTypeName;
private MemberBriefInfoVo memberInfo; private String memberNo; // 会员编码
private String username; // 会员用户名
private String mobile; // 手机号
private String nickname; // 会员昵称
private String headimg;
@JsonSerialize(using = BeanJsonSerializer.LongDateToStringSerializer.class)
private Long createTime;
private Transfer transfer;
private String transferVoucher;
private String transferRemark;
public String getStatusName() { public String getStatusName() {
return MemberCashOutStatusEnum.getNameByStatus(this.status); return MemberCashOutStatusEnum.getNameByStatus(this.status);
@ -67,4 +82,13 @@ public class MemberCashOutInfoVo implements Serializable {
if (this.accountType.isEmpty()) return ""; if (this.accountType.isEmpty()) return "";
return AccountTypeEnum.getNameByType(this.accountType); return AccountTypeEnum.getNameByType(this.accountType);
} }
@Data
public static class Transfer {
private String transferNo; // 转账单号
private String transferVoucher;
private String transferRemark;
}
} }

View File

@ -58,6 +58,12 @@ public class MemberCashOutListVo implements Serializable {
private String transferTypeName; private String transferTypeName;
private String transferStatusName; private String transferStatusName;
private String accountTypeName; private String accountTypeName;
private String transferPaymentCode;
private String memberNo; // 会员编码
private String username; // 会员用户名
private String mobile; // 手机号
private String nickname; // 会员昵称
private String headimg; // 会员头像
public String getStatusName() { public String getStatusName() {
return MemberCashOutStatusEnum.getNameByStatus(this.status); return MemberCashOutStatusEnum.getNameByStatus(this.status);

View File

@ -4,47 +4,30 @@ import com.niu.core.common.domain.PageResult;
import com.niu.core.service.admin.pay.param.PayTransferParam; import com.niu.core.service.admin.pay.param.PayTransferParam;
import com.niu.core.service.admin.pay.param.PayTransferSearchParam; import com.niu.core.service.admin.pay.param.PayTransferSearchParam;
import com.niu.core.common.domain.PageParam; import com.niu.core.common.domain.PageParam;
import com.niu.core.service.admin.pay.param.SetSceneIdParam;
import com.niu.core.service.admin.pay.vo.PayTransferInfoVo; import com.niu.core.service.admin.pay.vo.PayTransferInfoVo;
import com.niu.core.service.admin.pay.vo.PayTransferListVo; import com.niu.core.service.admin.pay.vo.PayTransferListVo;
import com.niu.core.service.core.pay.param.SetTradeSceneParam;
import com.niu.core.service.core.pay.vo.WechatTransferSceneListVo;
import java.util.Map;
/** /**
* 转账服务接口 * 转账服务接口
*/ */
public interface IPayTransferService { public interface IPayTransferService {
Map<String, WechatTransferSceneListVo> getWechatTransferScene();
/** /**
* 转账列表 * 设置场景id
* @param pageParam 分页参数 * @param param
* @param searchParam 搜索参数
* @return PageResult<PayTransferListVo>
*/ */
PageResult<PayTransferListVo> list(PageParam pageParam, PayTransferSearchParam searchParam); void setSceneId(SetSceneIdParam param);
/** /**
* 转账详情 * 设置业务场景配置
* @param id 主键ID * @param param
* @return PayTransferInfoVo
*/ */
PayTransferInfoVo info(Integer id); void setTradeScene(SetTradeSceneParam param);
/**
* 转账添加
* @param addParam 添加参数
*/
void add(PayTransferParam addParam);
/**
* 转账编辑
* @param id 主键
* @param editParam 编辑参数
*/
void edit(Integer id, PayTransferParam editParam);
/**
* 转账删除
* @param id 主键ID
*/
void del(Integer id);
} }

View File

@ -1,23 +1,18 @@
package com.niu.core.service.admin.pay.impl; package com.niu.core.service.admin.pay.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.niu.core.common.exception.CommonException;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.niu.core.common.utils.RequestUtils;
import com.niu.core.common.domain.PageResult; import com.niu.core.enums.pay.TransferSceneEnum;
import com.niu.core.common.domain.PageParam;
import com.niu.core.entity.pay.PayTransfer;
import com.niu.core.mapper.pay.PayTransferMapper;
import com.niu.core.service.admin.pay.param.PayTransferParam;
import com.niu.core.service.admin.pay.param.PayTransferSearchParam;
import com.niu.core.service.admin.pay.IPayTransferService; import com.niu.core.service.admin.pay.IPayTransferService;
import com.niu.core.service.admin.pay.vo.PayTransferInfoVo; import com.niu.core.service.admin.pay.param.SetSceneIdParam;
import com.niu.core.service.admin.pay.vo.PayTransferListVo; import com.niu.core.service.core.pay.ICoreTransferSceneService;
import org.springframework.beans.BeanUtils; import com.niu.core.service.core.pay.param.SetTradeSceneParam;
import org.springframework.stereotype.Service; import com.niu.core.service.core.pay.vo.WechatTransferSceneListVo;
import org.springframework.util.Assert;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import java.util.LinkedList; import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/** /**
@ -25,135 +20,38 @@ import java.util.List;
*/ */
@Service @Service
public class PayTransferServiceImpl implements IPayTransferService { public class PayTransferServiceImpl implements IPayTransferService {
@Resource @Resource
PayTransferMapper payTransferMapper; ICoreTransferSceneService coreTransferSceneService;
/** public Map<String, WechatTransferSceneListVo> getWechatTransferScene() {
* 转账列表 return coreTransferSceneService.getWechatTransferScene(RequestUtils.siteId());
* @param pageParam 分页参数
* @param searchParam 搜索参数
* @return PageResult<PayTransferListVo>
*/
@Override
public PageResult<PayTransferListVo> list(PageParam pageParam, PayTransferSearchParam searchParam) {
Integer page = pageParam.getPage();
Integer limit =pageParam.getLimit();
QueryWrapper<PayTransfer> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("id");
IPage<PayTransfer> iPage = payTransferMapper.selectPage(new Page<>(page, limit), queryWrapper);
List<PayTransferListVo> list = new LinkedList<>();
for (PayTransfer item : iPage.getRecords()) {
PayTransferListVo vo = new PayTransferListVo();
BeanUtils.copyProperties(item, vo);
list.add(vo);
}
return PageResult.build(page, limit, iPage.getTotal()).setData(list);
} }
/** /**
* 转账详情 * 设置场景id
* @param id 主键
* @return PayTransferInfoVo
*/
@Override
public PayTransferInfoVo info(Integer id) {
PayTransfer model = payTransferMapper.selectOne(
new QueryWrapper<PayTransfer>()
.eq("id", id)
.last("limit 1"));
Assert.notNull(model, "数据不存在");
PayTransferInfoVo vo = new PayTransferInfoVo();
BeanUtils.copyProperties(model, vo);
return vo;
}
/**
* 转账添加
* @param addParam 参数
*/
@Override
public void add(PayTransferParam addParam) {
PayTransfer model = new PayTransfer();
model.setSiteId(addParam.getSiteId());
model.setTradeType(addParam.getTradeType());
model.setTransferNo(addParam.getTransferNo());
model.setMainId(addParam.getMainId());
model.setMainType(addParam.getMainType());
model.setTransferType(addParam.getTransferType());
model.setTransferRealname(addParam.getTransferRealname());
model.setTransferMobile(addParam.getTransferMobile());
model.setTransferBank(addParam.getTransferBank());
model.setTransferAccount(addParam.getTransferAccount());
model.setTransferVoucher(addParam.getTransferVoucher());
model.setTransferRemark(addParam.getTransferRemark());
model.setTransferFailReason(addParam.getTransferFailReason());
model.setTransferStatus(addParam.getTransferStatus());
model.setMoney(addParam.getMoney());
model.setCreateTime(System.currentTimeMillis() / 1000);
model.setTransferTime(addParam.getTransferTime());
model.setUpdateTime(System.currentTimeMillis() / 1000);
model.setOpenid(addParam.getOpenid());
model.setRemark(addParam.getRemark());
model.setBatchId(addParam.getBatchId());
payTransferMapper.insert(model);
}
/**
* 转账编辑
* *
* @param editParam 参数 * @param param
*/ */
@Override @Override
public void edit(Integer id, PayTransferParam editParam) { public void setSceneId(SetSceneIdParam param) {
PayTransfer model = payTransferMapper.selectOne( JSONObject config = coreTransferSceneService.getWechatTransferSceneConfig(RequestUtils.siteId());
new QueryWrapper<PayTransfer>()
.eq("id", id)
.last("limit 1"));
Assert.notNull(model, "数据不存在!"); Map<String, TransferSceneEnum> tradeScenelist = TransferSceneEnum.getWechatTransferSceneMap();
model.setId(id); if (!tradeScenelist.containsKey(param.getScene())) {
model.setSiteId(editParam.getSiteId()); throw new CommonException("不存在的商户转账场景");
model.setTradeType(editParam.getTradeType()); }
model.setTransferNo(editParam.getTransferNo());
model.setMainId(editParam.getMainId()); config.put(param.getScene(), param.getSceneId());
model.setMainType(editParam.getMainType()); coreTransferSceneService.setWechatTransferSceneConfig(RequestUtils.siteId(), config);
model.setTransferType(editParam.getTransferType());
model.setTransferRealname(editParam.getTransferRealname());
model.setTransferMobile(editParam.getTransferMobile());
model.setTransferBank(editParam.getTransferBank());
model.setTransferAccount(editParam.getTransferAccount());
model.setTransferVoucher(editParam.getTransferVoucher());
model.setTransferRemark(editParam.getTransferRemark());
model.setTransferFailReason(editParam.getTransferFailReason());
model.setTransferStatus(editParam.getTransferStatus());
model.setMoney(editParam.getMoney());
model.setTransferTime(editParam.getTransferTime());
model.setUpdateTime(System.currentTimeMillis() / 1000);
model.setOpenid(editParam.getOpenid());
model.setRemark(editParam.getRemark());
model.setBatchId(editParam.getBatchId());
payTransferMapper.updateById(model);
} }
/** /**
* 转账删除 * 设置业务场景配置
* @param id 主键ID * @param param
*/ */
@Override @Override
public void del(Integer id) { public void setTradeScene(SetTradeSceneParam param) {
PayTransfer model = payTransferMapper.selectOne( coreTransferSceneService.setTradeScene(RequestUtils.siteId(), param.getType(), param);
new QueryWrapper<PayTransfer>()
.eq("id", id)
.last("limit 1"));
Assert.notNull(model, "数据不存在!");
payTransferMapper.delete(new QueryWrapper<PayTransfer>().eq("id", id));
} }
} }

View File

@ -0,0 +1,16 @@
package com.niu.core.service.admin.pay.param;
import lombok.Data;
import org.jetbrains.annotations.NotNull;
import java.io.Serializable;
@Data
public class SetSceneIdParam implements Serializable {
private static final long serialVersionUID = 1L;
private String scene;
private String sceneId;
}

View File

@ -8,4 +8,6 @@ public interface ISystemService {
* @return * @return
*/ */
StatSystemVo getSystemInfo(); StatSystemVo getSystemInfo();
void clearCache();
} }

View File

@ -124,19 +124,10 @@ public class SysExportServiceImpl implements ISysExportService {
*/ */
@Override @Override
public Boolean checkExportData(String type, Map<String, Object> whereMap) { public Boolean checkExportData(String type, Map<String, Object> whereMap) {
JSONObject whereJson = new JSONObject();
whereJson.set("keyword", whereMap.getOrDefault("keyword", ""));
whereJson.set("register_type", whereMap.getOrDefault("register_type", ""));
whereJson.set("create_time", whereMap.getOrDefault("create_time", ""));
whereJson.set("is_del", whereMap.getOrDefault("is_del", ""));
whereJson.set("member_label", whereMap.getOrDefault("member_label", ""));
whereJson.set("register_channel", whereMap.getOrDefault("register_channel", ""));
whereJson.set("member_level", whereMap.getOrDefault("member_level", ""));
PageParam pageParam = new PageParam(); PageParam pageParam = new PageParam();
pageParam.setPage(Integer.parseInt(whereMap.getOrDefault("page", 0).toString())); pageParam.setPage(Integer.parseInt(whereMap.getOrDefault("page", 0).toString()));
pageParam.setLimit(Integer.parseInt(whereMap.getOrDefault("limit", 0).toString())); pageParam.setLimit(Integer.parseInt(whereMap.getOrDefault("limit", 0).toString()));
JSONArray jsonArray = coreExportService.getExportData(RequestUtils.siteId(), type, whereJson, pageParam); JSONArray jsonArray = coreExportService.getExportData(RequestUtils.siteId(), type, JSONUtil.parseObj(whereMap), pageParam);
return !jsonArray.isEmpty(); return !jsonArray.isEmpty();
} }
@ -146,21 +137,12 @@ public class SysExportServiceImpl implements ISysExportService {
@Override @Override
public void exportData(String type, Map<String, Object> whereMap) { public void exportData(String type, Map<String, Object> whereMap) {
Integer siteId = RequestUtils.siteId(); Integer siteId = RequestUtils.siteId();
JSONObject whereJson = new JSONObject();
whereJson.set("keyword", whereMap.getOrDefault("keyword", ""));
whereJson.set("register_type", whereMap.getOrDefault("register_type", ""));
whereJson.set("create_time", whereMap.getOrDefault("create_time", ""));
whereJson.set("is_del", whereMap.getOrDefault("is_del", ""));
whereJson.set("member_label", whereMap.getOrDefault("member_label", ""));
whereJson.set("register_channel", whereMap.getOrDefault("register_channel", ""));
whereJson.set("member_level", whereMap.getOrDefault("member_level", ""));
PageParam pageParam = new PageParam(); PageParam pageParam = new PageParam();
pageParam.setPage((Integer) whereMap.getOrDefault("page", 0)); pageParam.setPage((Integer) whereMap.getOrDefault("page", 0));
pageParam.setLimit((Integer) whereMap.getOrDefault("limit", 0)); pageParam.setLimit((Integer) whereMap.getOrDefault("limit", 0));
JSONArray dataColumn = coreExportService.getExportDataColumn(type); JSONArray dataColumn = coreExportService.getExportDataColumn(type);
JSONArray dataArray = coreExportService.getExportData(siteId, type, whereJson, pageParam); JSONArray dataArray = coreExportService.getExportData(siteId, type, JSONUtil.parseObj(whereMap), pageParam);
SysExport export = new SysExport(); SysExport export = new SysExport();
export.setSiteId(RequestUtils.siteId()); export.setSiteId(RequestUtils.siteId());

View File

@ -1,13 +1,18 @@
package com.niu.core.service.admin.sys.impl; package com.niu.core.service.admin.sys.impl;
import com.niu.core.common.component.context.cache.Cached;
import com.niu.core.service.admin.stat.vo.StatSystemVo; import com.niu.core.service.admin.stat.vo.StatSystemVo;
import com.niu.core.service.admin.stat.vo.StatVersionVo; import com.niu.core.service.admin.stat.vo.StatVersionVo;
import com.niu.core.service.admin.sys.ISystemService; import com.niu.core.service.admin.sys.ISystemService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@Service @Service
public class SystemServiceImpl implements ISystemService { public class SystemServiceImpl implements ISystemService {
@Resource
private Cached cached;
/** /**
* 获取版权信息 * 获取版权信息
* *
@ -27,4 +32,9 @@ public class SystemServiceImpl implements ISystemService {
statSystemVo.setVersion(statVersionVo); statSystemVo.setVersion(statVersionVo);
return statSystemVo; return statSystemVo;
} }
@Override
public void clearCache() {
cached.getAllKeys().stream().forEach(key -> cached.remove(key));;
}
} }

View File

@ -24,7 +24,6 @@ import com.niu.core.service.core.notice.vo.AddonNoticeListVo;
import com.niu.core.service.core.notice.vo.NoticeInfoVo; import com.niu.core.service.core.notice.vo.NoticeInfoVo;
import com.niu.core.service.core.site.ICoreSiteService; import com.niu.core.service.core.site.ICoreSiteService;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.security.web.util.UrlUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;

View File

@ -7,6 +7,7 @@ import com.niu.core.entity.oplatform.WxOplatfromWeappVersion;
import com.niu.core.service.admin.wechat.param.WechatFansSearchParam; import com.niu.core.service.admin.wechat.param.WechatFansSearchParam;
import com.niu.core.service.admin.wechat.vo.WechatFansListVo; import com.niu.core.service.admin.wechat.vo.WechatFansListVo;
import com.niu.core.service.admin.wxoplatform.param.OplatformConfigParam; import com.niu.core.service.admin.wxoplatform.param.OplatformConfigParam;
import com.niu.core.service.admin.wxoplatform.vo.SiteGroupWeappVersionVo;
import com.niu.core.service.admin.wxoplatform.vo.WxOplatfromWeappVersionVo; import com.niu.core.service.admin.wxoplatform.vo.WxOplatfromWeappVersionVo;
import com.niu.core.service.core.wxoplatform.vo.CoreOplatformStaticConfigVo; import com.niu.core.service.core.wxoplatform.vo.CoreOplatformStaticConfigVo;
@ -33,19 +34,19 @@ public interface IWeappVersionService {
/** /**
* 添加小程序版本 * 添加小程序版本
*/ */
void add(Integer siteGroupId); void add(Integer siteGroupId, boolean isAll);
/** /**
* 获取小程序版本提交结果 * 获取小程序版本提交结果
* @param taskKey * @param taskKey
*/ */
void getVersionUploadResult(String taskKey); void getVersionUploadResult(String taskKey, boolean isAll);
/** /**
* 上传成功 * 上传成功
* @param taskKey * @param taskKey
*/ */
void uploadSuccess(String taskKey); void uploadSuccess(String taskKey, boolean isAll);
/** /**
* 站点小程序提交 * 站点小程序提交
@ -62,4 +63,11 @@ public interface IWeappVersionService {
void submitAudit(Integer siteId, Integer versionId); void submitAudit(Integer siteId, Integer versionId);
void siteWeappCommit(); void siteWeappCommit();
/**
* 按站点套餐获取提交记录
* @param pageParam
* @return
*/
PageResult<SiteGroupWeappVersionVo> getSiteGroupCommitRecord(PageParam pageParam);
} }

View File

@ -16,6 +16,7 @@ import com.niu.core.common.exception.CommonException;
import com.niu.core.common.utils.RequestUtils; import com.niu.core.common.utils.RequestUtils;
import com.niu.core.common.utils.WechatUtils; import com.niu.core.common.utils.WechatUtils;
import com.niu.core.entity.oplatform.WxOplatfromWeappVersion; import com.niu.core.entity.oplatform.WxOplatfromWeappVersion;
import com.niu.core.entity.pay.Pay;
import com.niu.core.entity.site.Site; import com.niu.core.entity.site.Site;
import com.niu.core.entity.site.SiteGroup; import com.niu.core.entity.site.SiteGroup;
import com.niu.core.entity.sys.SysConfig; import com.niu.core.entity.sys.SysConfig;
@ -27,9 +28,11 @@ import com.niu.core.mapper.site.SiteGroupMapper;
import com.niu.core.mapper.site.SiteMapper; import com.niu.core.mapper.site.SiteMapper;
import com.niu.core.mapper.sys.SysConfigMapper; import com.niu.core.mapper.sys.SysConfigMapper;
import com.niu.core.mapper.weapp.WeappVersionMapper; import com.niu.core.mapper.weapp.WeappVersionMapper;
import com.niu.core.service.admin.pay.vo.PayListVo;
import com.niu.core.service.admin.site.vo.SiteInfoVo; import com.niu.core.service.admin.site.vo.SiteInfoVo;
import com.niu.core.service.admin.wxoplatform.IWeappVersionService; import com.niu.core.service.admin.wxoplatform.IWeappVersionService;
import com.niu.core.service.admin.wxoplatform.vo.OplatformConfigVo; import com.niu.core.service.admin.wxoplatform.vo.OplatformConfigVo;
import com.niu.core.service.admin.wxoplatform.vo.SiteGroupWeappVersionVo;
import com.niu.core.service.admin.wxoplatform.vo.WxOplatfromWeappVersionVo; import com.niu.core.service.admin.wxoplatform.vo.WxOplatfromWeappVersionVo;
import com.niu.core.service.core.site.ICoreSiteService; import com.niu.core.service.core.site.ICoreSiteService;
import com.niu.core.service.core.weapp.ICoreWeappCloudService; import com.niu.core.service.core.weapp.ICoreWeappCloudService;
@ -55,6 +58,7 @@ import org.springframework.stereotype.Service;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
@ -127,11 +131,11 @@ public class WeappVersionServiceImpl implements IWeappVersionService {
* 添加小程序版本 * 添加小程序版本
*/ */
@Override @Override
public void add(Integer siteGroupId) { public void add(Integer siteGroupId, boolean isAll) {
List<SiteGroup> siteGroupList = siteGroupMapper.selectList(new QueryWrapper<SiteGroup>().gt("group_id", 0).orderByAsc("create_time")); List<SiteGroup> siteGroupList = siteGroupMapper.selectList(new QueryWrapper<SiteGroup>().gt("group_id", 0).orderByAsc("create_time"));
if (ObjectUtil.isEmpty(siteGroupList)) throw new CommonException("请先添加站点套餐"); if (ObjectUtil.isEmpty(siteGroupList)) throw new CommonException("请先添加站点套餐");
SiteGroup siteGroup = siteGroupId == null ? siteGroupList.get(0) : siteGroupMapper.selectById(siteGroupId); SiteGroup siteGroup = siteGroupId == null || siteGroupId == 0 ? siteGroupList.get(0) : siteGroupMapper.selectById(siteGroupId);
WxOplatfromWeappVersion uploading = wxOplatfromWeappVersionMapper.selectOne(new QueryWrapper<WxOplatfromWeappVersion>() WxOplatfromWeappVersion uploading = wxOplatfromWeappVersionMapper.selectOne(new QueryWrapper<WxOplatfromWeappVersion>()
.eq("site_group_id", siteGroup.getGroupId()) .eq("site_group_id", siteGroup.getGroupId())
@ -170,7 +174,7 @@ public class WeappVersionServiceImpl implements IWeappVersionService {
model.setTaskKey(taskKey); model.setTaskKey(taskKey);
wxOplatfromWeappVersionMapper.insert(model); wxOplatfromWeappVersionMapper.insert(model);
weappVersionService.getVersionUploadResult(taskKey); weappVersionService.getVersionUploadResult(taskKey, isAll);
} }
/** /**
@ -178,14 +182,14 @@ public class WeappVersionServiceImpl implements IWeappVersionService {
* @param taskKey * @param taskKey
*/ */
@Async @Async
public void getVersionUploadResult(String taskKey) { public void getVersionUploadResult(String taskKey, boolean isAll) {
if (scheduler == null || scheduler.isShutdown() || scheduler.isTerminated()) { if (scheduler == null || scheduler.isShutdown() || scheduler.isTerminated()) {
scheduler = Executors.newScheduledThreadPool(1); scheduler = Executors.newScheduledThreadPool(1);
} }
scheduler.schedule(() -> checkVersionUploadResult(taskKey), 10, TimeUnit.SECONDS); scheduler.schedule(() -> checkVersionUploadResult(taskKey, isAll), 10, TimeUnit.SECONDS);
} }
private void checkVersionUploadResult(String taskKey) { private void checkVersionUploadResult(String taskKey, boolean isAll) {
JSONObject log = coreWeappCloudService.getWeappCompileLog(taskKey); JSONObject log = coreWeappCloudService.getWeappCompileLog(taskKey);
System.out.println("checkVersionUploadResult ++++++++++ " + log.toString()); System.out.println("checkVersionUploadResult ++++++++++ " + log.toString());
@ -200,6 +204,7 @@ public class WeappVersionServiceImpl implements IWeappVersionService {
model.setUpdateTime(System.currentTimeMillis() / 1000); model.setUpdateTime(System.currentTimeMillis() / 1000);
wxOplatfromWeappVersionMapper.update(model, new QueryWrapper<WxOplatfromWeappVersion>().eq("task_key", taskKey)); wxOplatfromWeappVersionMapper.update(model, new QueryWrapper<WxOplatfromWeappVersion>().eq("task_key", taskKey));
scheduler.shutdown(); scheduler.shutdown();
weappVersionService.uploadSuccess(taskKey, isAll);
return; return;
} }
if (last.getInt("percent", 0).equals(100)) { if (last.getInt("percent", 0).equals(100)) {
@ -208,10 +213,10 @@ public class WeappVersionServiceImpl implements IWeappVersionService {
model.setUpdateTime(System.currentTimeMillis() / 1000); model.setUpdateTime(System.currentTimeMillis() / 1000);
wxOplatfromWeappVersionMapper.update(model, new QueryWrapper<WxOplatfromWeappVersion>().eq("task_key", taskKey)); wxOplatfromWeappVersionMapper.update(model, new QueryWrapper<WxOplatfromWeappVersion>().eq("task_key", taskKey));
scheduler.shutdown(); scheduler.shutdown();
weappVersionService.uploadSuccess(taskKey); weappVersionService.uploadSuccess(taskKey, isAll);
return; return;
} }
scheduler.schedule(() -> checkVersionUploadResult(taskKey), 10, TimeUnit.SECONDS); scheduler.schedule(() -> checkVersionUploadResult(taskKey, isAll), 10, TimeUnit.SECONDS);
} }
} else { } else {
scheduler.shutdown(); scheduler.shutdown();
@ -223,7 +228,7 @@ public class WeappVersionServiceImpl implements IWeappVersionService {
* @param taskKey * @param taskKey
*/ */
@Async @Async
public void uploadSuccess(String taskKey) { public void uploadSuccess(String taskKey, boolean isAll) {
WxOplatfromWeappVersion version = wxOplatfromWeappVersionMapper.selectOne(new QueryWrapper<WxOplatfromWeappVersion>().eq("task_key", taskKey)); WxOplatfromWeappVersion version = wxOplatfromWeappVersionMapper.selectOne(new QueryWrapper<WxOplatfromWeappVersion>().eq("task_key", taskKey));
WxOpenComponentService wxOpenService = WechatUtils.WxOpen().getWxOpenComponentService(); WxOpenComponentService wxOpenService = WechatUtils.WxOpen().getWxOpenComponentService();
@ -261,7 +266,12 @@ public class WeappVersionServiceImpl implements IWeappVersionService {
} }
} }
} }
} catch (Exception e) {
System.out.println("小程序模板上传成功获取模板id异常");
e.printStackTrace();
}
if (isAll) {
SiteGroup siteGroup = siteGroupMapper.selectOne(new QueryWrapper<SiteGroup>() SiteGroup siteGroup = siteGroupMapper.selectOne(new QueryWrapper<SiteGroup>()
.select("group_id") .select("group_id")
.gt("group_id", version.getSiteGroupId()) .gt("group_id", version.getSiteGroupId())
@ -269,11 +279,8 @@ public class WeappVersionServiceImpl implements IWeappVersionService {
.last("limit 1") .last("limit 1")
); );
if (siteGroup != null) { if (siteGroup != null) {
weappVersionService.add(siteGroup.getGroupId()); weappVersionService.add(siteGroup.getGroupId(), true);
} }
} catch (Exception e) {
System.out.println("小程序模板上传成功获取模板id异常");
e.printStackTrace();
} }
} }
@ -405,4 +412,33 @@ public class WeappVersionServiceImpl implements IWeappVersionService {
SiteInfoVo site = coreSiteService.getSiteCache(RequestUtils.siteId()); SiteInfoVo site = coreSiteService.getSiteCache(RequestUtils.siteId());
this.weappCommit(site.getSiteId(), site.getGroupId(), null); this.weappCommit(site.getSiteId(), site.getGroupId(), null);
} }
/**
* 按站点套餐获取提交记录
* @param pageParam
* @return
*/
@Override
public PageResult<SiteGroupWeappVersionVo> getSiteGroupCommitRecord(PageParam pageParam) {
Integer page = pageParam.getPage();
Integer limit = pageParam.getLimit();
IPage<SiteGroup> iPage = siteGroupMapper.selectPage(new Page<>(page, limit), new QueryWrapper<SiteGroup>().select("group_id,group_name"));
List<SiteGroupWeappVersionVo> list = new LinkedList<>();
for (SiteGroup item : iPage.getRecords()) {
SiteGroupWeappVersionVo vo = new SiteGroupWeappVersionVo();
BeanUtils.copyProperties(item, vo);
WxOplatfromWeappVersion lastVersion = wxOplatfromWeappVersionMapper.selectOne(new QueryWrapper<WxOplatfromWeappVersion>().eq("site_group_id", item.getGroupId()).orderByDesc("id").last("limit 1"));
if (lastVersion != null) {
WxOplatfromWeappVersionVo versionVo = new WxOplatfromWeappVersionVo();
BeanUtils.copyProperties(lastVersion, versionVo);
vo.setCommitRecord(versionVo);
}
list.add(vo);
}
return PageResult.build(page, limit, iPage.getTotal()).setData(list);
}
} }

View File

@ -0,0 +1,30 @@
package com.niu.core.service.admin.wxoplatform.vo;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.niu.core.enums.channel.WeappVersionStatusEnum;
import lombok.Data;
import java.io.Serializable;
import java.util.HashMap;
/**
* 微信提交记录 视图
*/
@Data
public class SiteGroupWeappVersionVo implements Serializable {
private static final long serialVersionUID = 1L;
private Integer groupId;
/** 分组名称 */
private String groupName;
private WxOplatfromWeappVersionVo commitRecord;
public Object getCommitRecord() {
if (this.commitRecord == null) {
return new HashMap<>();
}
return this.commitRecord;
}
}

View File

@ -2,6 +2,7 @@ package com.niu.core.service.api.member;
import com.niu.core.common.domain.PageParam; import com.niu.core.common.domain.PageParam;
import com.niu.core.common.domain.PageResult; import com.niu.core.common.domain.PageResult;
import com.niu.core.service.admin.member.param.CashOutTransferParam;
import com.niu.core.service.admin.member.vo.CashOutConfigVo; import com.niu.core.service.admin.member.vo.CashOutConfigVo;
import com.niu.core.service.api.member.param.*; import com.niu.core.service.api.member.param.*;
import com.niu.core.service.api.member.vo.*; import com.niu.core.service.api.member.vo.*;
@ -47,7 +48,7 @@ public interface IMemberCashOutService {
* @param param * @param param
* @return * @return
*/ */
boolean cashOutApply(MemberCashOutApplyParam param); Integer cashOutApply(MemberCashOutApplyParam param);
/** /**
* 撤销提现申请 * 撤销提现申请
@ -57,6 +58,12 @@ public interface IMemberCashOutService {
*/ */
boolean cashOutCancel(MemberCashOutCancelParam param); boolean cashOutCancel(MemberCashOutCancelParam param);
/**
* 转账
* @param param
*/
Object transfer(CashOutTransferParam param);
/** /**
* 提现账号列表 * 提现账号列表
* *

View File

@ -4,6 +4,8 @@ import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.query.MPJQueryWrapper;
import com.niu.core.common.config.GlobalConfig;
import com.niu.core.common.domain.PageParam; import com.niu.core.common.domain.PageParam;
import com.niu.core.common.domain.PageResult; import com.niu.core.common.domain.PageResult;
import com.niu.core.common.exception.CommonException; import com.niu.core.common.exception.CommonException;
@ -16,6 +18,7 @@ import com.niu.core.enums.member.MemberCashOutStatusEnum;
import com.niu.core.enums.pay.TransferTypeEnum; import com.niu.core.enums.pay.TransferTypeEnum;
import com.niu.core.mapper.member.MemberCashOutAccountMapper; import com.niu.core.mapper.member.MemberCashOutAccountMapper;
import com.niu.core.mapper.member.MemberCashOutMapper; import com.niu.core.mapper.member.MemberCashOutMapper;
import com.niu.core.service.admin.member.param.CashOutTransferParam;
import com.niu.core.service.admin.member.vo.CashOutConfigVo; import com.niu.core.service.admin.member.vo.CashOutConfigVo;
import com.niu.core.service.api.member.IMemberCashOutService; import com.niu.core.service.api.member.IMemberCashOutService;
import com.niu.core.service.api.member.param.*; import com.niu.core.service.api.member.param.*;
@ -53,7 +56,7 @@ public class MemberCashOutServiceImpl implements IMemberCashOutService {
Integer limit = pageParam.getLimit(); Integer limit = pageParam.getLimit();
QueryWrapper<MemberCashOut> queryWrapper = new QueryWrapper(); QueryWrapper<MemberCashOut> queryWrapper = new QueryWrapper();
queryWrapper.select("id,site_id,cash_out_no,member_id,account_type,transfer_type,transfer_realname,transfer_mobile,transfer_bank,transfer_account,transfer_status,transfer_time,apply_money,rate,service_money,money,audit_time,status,remark,create_time,refuse_reason"); queryWrapper.select("id,site_id,cash_out_no,member_id,account_type,transfer_type,transfer_realname,transfer_payment_code,transfer_mobile,transfer_bank,transfer_account,transfer_status,transfer_time,apply_money,rate,service_money,money,audit_time,status,remark,create_time,refuse_reason");
queryWrapper.eq("site_id", param.siteId()); queryWrapper.eq("site_id", param.siteId());
queryWrapper.eq("member_id", param.memberId()); queryWrapper.eq("member_id", param.memberId());
if (ObjectUtil.isNotEmpty(param.getStatus())) queryWrapper.like("status", param.getStatus()); if (ObjectUtil.isNotEmpty(param.getStatus())) queryWrapper.like("status", param.getStatus());
@ -63,24 +66,35 @@ public class MemberCashOutServiceImpl implements IMemberCashOutService {
IPage<MemberCashOut> iPage = this.memberCashOutMapper.selectPage(new Page<>(page, limit), queryWrapper); IPage<MemberCashOut> iPage = this.memberCashOutMapper.selectPage(new Page<>(page, limit), queryWrapper);
List<MemberCashOutListVo> memberCashOutListVoList = CollectUtils.convert(iPage.getRecords(), MemberCashOutListVo.class); List<MemberCashOutListVo> memberCashOutListVoList = CollectUtils.convert(iPage.getRecords(), MemberCashOutListVo.class);
if (memberCashOutListVoList != null) { if (memberCashOutListVoList != null) {
// for (MemberCashOutListVo memberCashOutListVo : memberCashOutListVoList) {
//
// }
} }
return PageResult.build(page, limit, iPage.getTotal()).setData(memberCashOutListVoList); return PageResult.build(page, limit, iPage.getTotal()).setData(memberCashOutListVoList);
} }
@Override @Override
public MemberCashOutInfoVo cashOutInfo(MemberCashOutInfoParam param) { public MemberCashOutInfoVo cashOutInfo(MemberCashOutInfoParam param) {
QueryWrapper<MemberCashOut> queryWrapper = new QueryWrapper(); MemberCashOutInfoVo vo = memberCashOutMapper.selectJoinOne(
queryWrapper.select("id,site_id,cash_out_no,member_id,transfer_type,transfer_realname,transfer_mobile,transfer_bank,transfer_account,transfer_fail_reason,transfer_time,apply_money,rate,service_money,money,audit_time,status,remark,create_time,refuse_reason"); MemberCashOutInfoVo.class,
queryWrapper.eq("id", param.getId()); new MPJQueryWrapper<MemberCashOut>()
queryWrapper.eq("site_id", param.siteId()); .select("mco.*,m.member_no,m.username,m.nickname,m.mobile,m.headimg,pt.transfer_voucher,pt.transfer_remark,pt.extra,pt.package_info")
queryWrapper.eq("member_id", param.memberId()); .eq("mco.id", param.getId())
MemberCashOut memberCashOut = memberCashOutMapper.selectOne(queryWrapper); .eq("mco.member_id", param.memberId())
MemberCashOutInfoVo memberCashOutInfoVo = new MemberCashOutInfoVo(); .eq("mco.site_id", param.siteId())
BeanUtils.copyProperties(memberCashOut, memberCashOutInfoVo); .setAlias("mco")
return memberCashOutInfoVo; .leftJoin("?_member m ON mco.member_id = m.member_id".replace("?_", GlobalConfig.tablePrefix))
.leftJoin("?_pay_transfer pt ON mco.transfer_no = pt.transfer_no".replace("?_", GlobalConfig.tablePrefix))
);
if (vo != null) {
MemberCashOutInfoVo.Transfer transfer = new MemberCashOutInfoVo.Transfer();
transfer.setTransferNo(vo.getTransferNo());
transfer.setTransferRemark(vo.getTransferRemark());
transfer.setTransferVoucher(vo.getTransferVoucher());
transfer.setExtra(vo.getExtra());
transfer.setPackageInfo(vo.getPackageInfo());
vo.setTransfer(transfer);
}
return vo;
} }
@Override @Override
@ -106,11 +120,10 @@ public class MemberCashOutServiceImpl implements IMemberCashOutService {
* @return * @return
*/ */
@Override @Override
public boolean cashOutApply(MemberCashOutApplyParam param) { public Integer cashOutApply(MemberCashOutApplyParam param) {
param.setMemberId(RequestUtils.memberId()); param.setMemberId(RequestUtils.memberId());
param.setSiteId(RequestUtils.siteId()); param.setSiteId(RequestUtils.siteId());
coreMemberCashOutService.apply(param); return coreMemberCashOutService.apply(param);
return true;
} }
/** /**
@ -126,22 +139,33 @@ public class MemberCashOutServiceImpl implements IMemberCashOutService {
.eq("site_id", param.siteId()) .eq("site_id", param.siteId())
.eq("id", param.getId())); .eq("id", param.getId()));
if (ObjectUtil.isEmpty(cashOut)) throw new CommonException("提现申请不存在"); if (ObjectUtil.isEmpty(cashOut)) throw new CommonException("提现申请不存在");
if (!cashOut.getStatus().equals(MemberCashOutStatusEnum.WAIT_AUDIT.getStatus())) throw new CommonException("当前提现申请未处于待审核状态");
cashOut.setStatus(MemberCashOutStatusEnum.CANCEL.getStatus()); coreMemberCashOutService.cancel(cashOut.getSiteId(), cashOut.getId());
cashOut.setCancelTime(System.currentTimeMillis() / 1000);
memberCashOutMapper.updateById(cashOut);
coreMemberCashOutService.giveback(cashOut);
return true; return true;
} }
/**
* 开始转账
* @param param
*/
@Override
public Object transfer(CashOutTransferParam param) {
MemberCashOut cashOut = memberCashOutMapper.selectOne(new QueryWrapper<MemberCashOut>()
.eq("member_id", RequestUtils.memberId())
.eq("site_id", RequestUtils.siteId())
.eq("id", param.getId()));
if (ObjectUtil.isEmpty(cashOut)) throw new CommonException("提现申请不存在");
if (!cashOut.getStatus().equals(MemberCashOutStatusEnum.WAIT_TRANSFER.getStatus())) throw new CommonException("当前提现申请未处于待转账状态");
return coreMemberCashOutService.transfer(cashOut, param);
}
@Override @Override
public PageResult accountList(PageParam pageParam, MemberCashOutAccountListParam param) { public PageResult accountList(PageParam pageParam, MemberCashOutAccountListParam param) {
Integer page = pageParam.getPage(); Integer page = pageParam.getPage();
Integer limit = pageParam.getLimit(); Integer limit = pageParam.getLimit();
QueryWrapper<MemberCashOutAccount> queryWrapper = new QueryWrapper(); QueryWrapper<MemberCashOutAccount> queryWrapper = new QueryWrapper();
queryWrapper.select("account_id,site_id,member_id,account_type,bank_name,realname,account_no"); queryWrapper.select("account_id,site_id,member_id,account_type,bank_name,realname,account_no,transfer_payment_code");
queryWrapper.eq("site_id", param.siteId()); queryWrapper.eq("site_id", param.siteId());
queryWrapper.eq("member_id", param.memberId()); queryWrapper.eq("member_id", param.memberId());
if (ObjectUtil.isNotEmpty(param.getAccountType())) queryWrapper.eq("account_type", param.getAccountType()); if (ObjectUtil.isNotEmpty(param.getAccountType())) queryWrapper.eq("account_type", param.getAccountType());
@ -154,7 +178,7 @@ public class MemberCashOutServiceImpl implements IMemberCashOutService {
@Override @Override
public MemberCashOutAccountDetailsVo accountDetails(MemberCashOutAccountDetailsParam param) { public MemberCashOutAccountDetailsVo accountDetails(MemberCashOutAccountDetailsParam param) {
QueryWrapper<MemberCashOutAccount> queryWrapper = new QueryWrapper(); QueryWrapper<MemberCashOutAccount> queryWrapper = new QueryWrapper();
queryWrapper.select("account_id,site_id,member_id,account_type,bank_name,realname,account_no"); queryWrapper.select("account_id,site_id,member_id,account_type,bank_name,realname,account_no,transfer_payment_code");
queryWrapper.eq("account_id", param.getAccountId()); queryWrapper.eq("account_id", param.getAccountId());
queryWrapper.eq("site_id", param.siteId()); queryWrapper.eq("site_id", param.siteId());
queryWrapper.eq("member_id", param.memberId()); queryWrapper.eq("member_id", param.memberId());
@ -167,7 +191,7 @@ public class MemberCashOutServiceImpl implements IMemberCashOutService {
@Override @Override
public MemberCashOutFirstAccountDetailsVo accountDetailsOfFirst(MemberCashOutFirstAccountDetailsParam param) { public MemberCashOutFirstAccountDetailsVo accountDetailsOfFirst(MemberCashOutFirstAccountDetailsParam param) {
QueryWrapper<MemberCashOutAccount> queryWrapper = new QueryWrapper(); QueryWrapper<MemberCashOutAccount> queryWrapper = new QueryWrapper();
queryWrapper.select("account_id,site_id,member_id,account_type,bank_name,realname,account_no"); queryWrapper.select("account_id,site_id,member_id,account_type,bank_name,realname,account_no,transfer_payment_code");
queryWrapper.eq("site_id", param.siteId()); queryWrapper.eq("site_id", param.siteId());
queryWrapper.eq("member_id", param.memberId()); queryWrapper.eq("member_id", param.memberId());
if (ObjectUtil.isNotEmpty(param.getAccountType())) queryWrapper.eq("account_type", param.getAccountType()); if (ObjectUtil.isNotEmpty(param.getAccountType())) queryWrapper.eq("account_type", param.getAccountType());

View File

@ -1,6 +1,8 @@
package com.niu.core.service.api.member.impl; package com.niu.core.service.api.member.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONArray; import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
@ -88,7 +90,8 @@ public class MemberSignServiceImpl implements IMemberSignService {
@Override @Override
@Transactional @Transactional
public MemberSignOperateVo signOperate(MemberSignOperateParam param) { public MemberSignOperateVo signOperate(MemberSignOperateParam param) {
MemberSignConfigVo config = getSystemSignConfig(param.siteId()); JSONObject signConfig = coreConfigService.getConfigValue(RequestUtils.siteId(), "SIGN_CONFIG");
MemberSignConfigVo config = JSONUtil.toBean(signConfig, MemberSignConfigVo.class);
if (!config.getIsUse()) throw new RuntimeException("签到未开启"); if (!config.getIsUse()) throw new RuntimeException("签到未开启");
@ -105,8 +108,19 @@ public class MemberSignServiceImpl implements IMemberSignService {
Integer days = 1; Integer days = 1;
if (yesterdayMemberSign != null) { if (yesterdayMemberSign != null) {
if (yesterdayMemberSign.getDays() + 1 < config.getSignPeriod()) { //连签天数大于签到周期连签天数重置为1
days = yesterdayMemberSign.getDays() + 1; days = yesterdayMemberSign.getDays() + 1;
if (days > config.getSignPeriod()) {
days = 1;
}
if (ObjectUtil.isNotEmpty(config.getContinueAward())) {
JSONArray continueSigns = config.getContinueAward();
CollUtil.sort(continueSigns, Comparator.comparing(o -> ((JSONObject) o).getInt("continue_sign")).reversed());
// 获取最大的连签天数
Integer maxContinueSign = continueSigns.getJSONObject(0).getInt("continue_sign");
if (days > maxContinueSign) {
days = 1;
}
} }
} }
@ -127,7 +141,7 @@ public class MemberSignServiceImpl implements IMemberSignService {
dayAwardVar.put("from_type", "day_sign_award"); dayAwardVar.put("from_type", "day_sign_award");
dayAwardVar.put("memo", "日签奖励"); dayAwardVar.put("memo", "日签奖励");
coreMemberService.memberGiftGrant(param.siteId(), param.memberId(), config.getDayAward(), dayAwardVar); coreMemberService.memberGiftGrant(param.siteId(), param.memberId(), config.getDayAward(), dayAwardVar);
vo.setAwards(config.getDayAward()); vo.setAwards(coreMemberService.getGiftContent(param.siteId(), config.getDayAward(), "member_sign"));
// 发放连签奖励 // 发放连签奖励
if (config.getContinueAward().size() > 0) { if (config.getContinueAward().size() > 0) {
@ -137,10 +151,32 @@ public class MemberSignServiceImpl implements IMemberSignService {
if (item.getInt("continue_sign").equals(days)) { if (item.getInt("continue_sign").equals(days)) {
// 是否限制领取 // 是否限制领取
if (item.getInt("receive_limit").equals(2)) { if (item.getInt("receive_limit").equals(2)) {
// 周期开始时间
Long periodStartTime = memberSignMapper.selectOne(new QueryWrapper<MemberSign>()
.select("start_time")
.eq("member_id", param.memberId())
.eq("site_id", param.siteId())
.eq("days", 1)
.gt("start_time", 0)
.orderByDesc("sign_id")
.last("limit 1")
).getStartTime();
// 周期结束时间
Long periodEndTime = periodStartTime + (config.getSignPeriod() * 86400);
// 领取次数
Long receiveNum = memberSignMapper.selectCount(new QueryWrapper<MemberSign>()
.eq("member_id", param.memberId())
.eq("site_id", param.siteId())
.between("create_time", periodStartTime, periodEndTime)
.eq("continue_tag", item.getStr("continue_tag"))
);
if (receiveNum < item.getInt("receive_num")) {
continueAward = item;
}
} else { } else {
continueAward = item; continueAward = item;
} }
break;
} }
} }
@ -155,12 +191,12 @@ public class MemberSignServiceImpl implements IMemberSignService {
dayAwardVar.put("from_type", "continue_sign_award"); dayAwardVar.put("from_type", "continue_sign_award");
dayAwardVar.put("memo", "连签奖励"); dayAwardVar.put("memo", "连签奖励");
coreMemberService.memberGiftGrant(param.siteId(), param.memberId(), continueAward, continueAwardVar); coreMemberService.memberGiftGrant(param.siteId(), param.memberId(), continueAward, continueAwardVar);
model.setContinueAward(continueAward.toString()); model.setContinueAward(continueAward.toString());
memberSignMapper.updateById(model);
vo.setInfo("连签" + days.toString() + "天恭喜您获得以下奖励"); vo.setInfo("连签" + days.toString() + "天恭喜您获得以下奖励");
vo.setAwards(continueAward); vo.setAwards(coreMemberService.getGiftContent(param.siteId(), continueAward, "member_sign"));
memberSignMapper.updateById(model);
} }
} }

View File

@ -25,4 +25,6 @@ public class MemberCashOutAccountAddParam implements ApiBaseParam {
/** 提现账户 */ /** 提现账户 */
private String accountNo; private String accountNo;
/** 收款码 */
private String transferPaymentCode;
} }

View File

@ -25,4 +25,6 @@ public class MemberCashOutAccountEditParam implements ApiBaseParam {
/** 提现账户 */ /** 提现账户 */
private String accountNo; private String accountNo;
/** 收款码 */
private String transferPaymentCode;
} }

View File

@ -23,4 +23,5 @@ public class MemberCashOutAccountDetailsVo {
// 提现账户 // 提现账户
private String accountNo; private String accountNo;
private String transferPaymentCode;
} }

View File

@ -23,4 +23,5 @@ public class MemberCashOutFirstAccountDetailsVo {
// 提现账户 // 提现账户
private String accountNo; private String accountNo;
private String transferPaymentCode;
} }

View File

@ -3,6 +3,7 @@ package com.niu.core.service.api.member.vo;
import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.niu.core.common.domain.BeanJsonSerializer; import com.niu.core.common.domain.BeanJsonSerializer;
import com.niu.core.enums.member.AccountTypeEnum; import com.niu.core.enums.member.AccountTypeEnum;
import com.niu.core.enums.member.MemberCashOutStatusEnum;
import com.niu.core.enums.pay.TransferTypeEnum; import com.niu.core.enums.pay.TransferTypeEnum;
import lombok.Data; import lombok.Data;
@ -43,6 +44,8 @@ public class MemberCashOutInfoVo {
// 转账状态 // 转账状态
private String transferStatus; private String transferStatus;
private String transferPaymentCode;
// 申请时间 // 申请时间
@JsonSerialize(using = BeanJsonSerializer.LongDateToStringSerializer.class) @JsonSerialize(using = BeanJsonSerializer.LongDateToStringSerializer.class)
private Long createTime; private Long createTime;
@ -78,6 +81,22 @@ public class MemberCashOutInfoVo {
private String accountType; private String accountType;
private String transferNo; // 转账单号
private String transferVoucher;
private String transferRemark;
private String extra;
private Transfer transfer;
private String nickname;
private String headimg;
private String packageInfo;
/** /**
* 取消时间 * 取消时间
*/ */
@ -99,20 +118,7 @@ public class MemberCashOutInfoVo {
} }
public String getStatusName() { public String getStatusName() {
// 状态1待审核2.待转账3已转账 -1拒绝 -2 已取消 return MemberCashOutStatusEnum.getNameByStatus(this.status);
switch (this.getStatus()) {
case 1:
return "待审核";
case 2:
return "待转账";
case 3:
return "已转账";
case -1:
return "拒绝";
case -2:
return "已取消";
}
return "";
} }
/** /**
@ -122,4 +128,17 @@ public class MemberCashOutInfoVo {
return ""; return "";
} }
@Data
public static class Transfer {
private String transferNo; // 转账单号
private String transferVoucher;
private String transferRemark;
@JsonSerialize(using = BeanJsonSerializer.StringToJsonSerializer.class)
private String extra;
private String packageInfo;
}
} }

View File

@ -43,6 +43,8 @@ public class MemberCashOutListVo {
// 转账状态 // 转账状态
private String transferStatus; private String transferStatus;
private String transferPaymentCode;
// 申请时间 // 申请时间
@JsonSerialize(using = BeanJsonSerializer.LongDateToStringSerializer.class) @JsonSerialize(using = BeanJsonSerializer.LongDateToStringSerializer.class)
private Long createTime; private Long createTime;

View File

@ -12,6 +12,7 @@ import com.niu.core.common.component.context.WebAppEnvs;
import com.niu.core.common.config.GlobalConfig; import com.niu.core.common.config.GlobalConfig;
import com.niu.core.entity.addon.Addon; import com.niu.core.entity.addon.Addon;
import com.niu.core.mapper.addon.AddonMapper; import com.niu.core.mapper.addon.AddonMapper;
import com.niu.core.service.admin.addon.IAddonDevelopBuildService;
import com.niu.core.service.admin.niucloud.ICloudBuildService; import com.niu.core.service.admin.niucloud.ICloudBuildService;
import com.niu.core.service.core.addon.*; import com.niu.core.service.core.addon.*;
import com.niu.core.service.core.app.tools.SQLScriptRunnerTools; import com.niu.core.service.core.app.tools.SQLScriptRunnerTools;
@ -49,6 +50,9 @@ public class CoreAddonInstallServiceImpl extends CoreAddonBaseService implements
@Resource @Resource
ICoreScheduleService coreScheduleService; ICoreScheduleService coreScheduleService;
@Resource
IAddonDevelopBuildService addonDevelopBuildService;
private Boolean installCheck = false; private Boolean installCheck = false;
private ArrayList<String> installStep = new ArrayList<String>(); private ArrayList<String> installStep = new ArrayList<String>();
@ -347,6 +351,12 @@ public class CoreAddonInstallServiceImpl extends CoreAddonBaseService implements
if (!ObjectUtil.isNotEmpty(coreAddonService.getInfoByKey(addon))) { if (!ObjectUtil.isNotEmpty(coreAddonService.getInfoByKey(addon))) {
throw new CommonException("当前插件未安装,不能进行卸载操作"); throw new CommonException("当前插件未安装,不能进行卸载操作");
} }
// 卸载前先打包
if (GlobalConfig.runActive.equalsIgnoreCase("dev")) {
addonDevelopBuildService.build(addon);
}
try { try {
// 卸载菜单 // 卸载菜单
coreMenuService.deleteMenu(addon, true); coreMenuService.deleteMenu(addon, true);

View File

@ -38,7 +38,7 @@ public class CoreDiyConfigService implements ICoreDiyConfigService {
private static JSONArray bottomJson; private static JSONArray bottomJson;
private static JSONArray getBottomJson() { private static JSONArray getBottomJson() {
if (bottomJson == null) { if (bottomJson == null || bottomJson.isEmpty()) {
JsonModuleLoader jsonModuleLoader = new JsonModuleLoader(); JsonModuleLoader jsonModuleLoader = new JsonModuleLoader();
bottomJson = jsonModuleLoader.mergeContentToArray("diy/bottom.json"); bottomJson = jsonModuleLoader.mergeContentToArray("diy/bottom.json");
} }

View File

@ -14,7 +14,7 @@ public interface ICoreMemberCashOutService {
* 申请提现 * 申请提现
* @param param * @param param
*/ */
void apply(MemberCashOutApplyParam param); Integer apply(MemberCashOutApplyParam param);
/** /**
* 提现审核 * 提现审核
@ -45,7 +45,7 @@ public interface ICoreMemberCashOutService {
* 转账成功 * 转账成功
* @param cashOut * @param cashOut
*/ */
void transfer(MemberCashOut cashOut, CashOutTransferParam param); Object transfer(MemberCashOut cashOut, CashOutTransferParam param);
/** /**
* 转账完成 * 转账完成
@ -66,4 +66,18 @@ public interface ICoreMemberCashOutService {
* @param cashOut * @param cashOut
*/ */
void giveback(MemberCashOut cashOut); void giveback(MemberCashOut cashOut);
/**
* 撤销提现
* @param siteId
* @param id
*/
void cancel(Integer siteId, Integer id);
/**
* 检测转账状态
* @param siteId
* @param id
*/
void checkTransferStatus(Integer siteId, Integer id);
} }

View File

@ -38,12 +38,12 @@ public class GiftBalanceDriver {
JSONObject signContent = new JSONObject(); JSONObject signContent = new JSONObject();
signContent.set("text", config.getStr("money") + ""); signContent.set("text", config.getStr("money") + "");
signContent.set("icon", "static/resource/images/member/sign/packet.png"); signContent.set("icon", "static/resource/images/member/sign/packet.png");
return signContent; return (new JSONArray()).put(signContent);
case "member_sign_continue": case "member_sign_continue":
JSONObject signContinueContent = new JSONObject(); JSONObject signContinueContent = new JSONObject();
signContinueContent.set("text", config.getStr("money") + ""); signContinueContent.set("text", config.getStr("money") + "");
signContinueContent.set("icon", "static/resource/images/member/sign/packet01.png"); signContinueContent.set("icon", "static/resource/images/member/sign/packet01.png");
return signContinueContent; return (new JSONArray()).put(signContinueContent);
default: default:
return ""; return "";
} }
@ -58,7 +58,7 @@ public class GiftBalanceDriver {
siteId, siteId,
memberId, memberId,
AccountTypeEnum.BALANCE.getType(), AccountTypeEnum.BALANCE.getType(),
new Double(config.getStr("money")), Double.valueOf(config.getStr("money")),
vars.getOrDefault("from_type", "").toString(), vars.getOrDefault("from_type", "").toString(),
vars.getOrDefault("momo", "").toString(), vars.getOrDefault("momo", "").toString(),
vars.getOrDefault("related_id", "").toString()); vars.getOrDefault("related_id", "").toString());

View File

@ -38,12 +38,12 @@ public class GiftPointDriver {
JSONObject signContent = new JSONObject(); JSONObject signContent = new JSONObject();
signContent.set("text", config.getStr("num") + "积分"); signContent.set("text", config.getStr("num") + "积分");
signContent.set("icon", "static/resource/images/member/sign/point.png"); signContent.set("icon", "static/resource/images/member/sign/point.png");
return signContent; return (new JSONArray()).put(signContent);
case "member_sign_continue": case "member_sign_continue":
JSONObject signContinueContent = new JSONObject(); JSONObject signContinueContent = new JSONObject();
signContinueContent.set("text", config.getStr("num") + "积分"); signContinueContent.set("text", config.getStr("num") + "积分");
signContinueContent.set("icon", "static/resource/images/member/sign/point01.png"); signContinueContent.set("icon", "static/resource/images/member/sign/point01.png");
return signContinueContent; return (new JSONArray()).put(signContinueContent);
default: default:
return null; return null;
} }

View File

@ -1,6 +1,7 @@
package com.niu.core.service.core.member.impl; package com.niu.core.service.core.member.impl;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.niu.core.common.exception.CommonException; import com.niu.core.common.exception.CommonException;
@ -59,23 +60,23 @@ public class CoreMemberCashOutServiceImpl implements ICoreMemberCashOutService {
* @param param * @param param
*/ */
@Override @Override
public void apply(MemberCashOutApplyParam param) { public Integer apply(MemberCashOutApplyParam param) {
Member member = memberMapper.selectOne(new QueryWrapper<Member>() Member member = memberMapper.selectOne(new QueryWrapper<Member>()
.eq("member_id", param.getMemberId()) .eq("member_id", param.getMemberId())
.eq("site_id", param.getSiteId())); .eq("site_id", param.getSiteId()));
if (ObjectUtil.isEmpty(member)) throw new CommonException("会员不存在"); if (ObjectUtil.isEmpty(member)) throw new CommonException("会员不存在");
CashOutConfigVo config = coreMemberConfigService.getCashOutConfig(param.getSiteId()); CashOutConfigVo config = coreMemberConfigService.getCashOutConfig(param.getSiteId());
if (config.getIsOpen().equals(0)) throw new CommonException("会员提现业务未开启"); if (config.getIsOpen().equals("0")) throw new CommonException("会员提现业务未开启");
BigDecimal applyMoney = param.getApplyMoney(); BigDecimal applyMoney = param.getApplyMoney();
if (applyMoney.compareTo(BigDecimal.ZERO) <= 0) throw new CommonException("提现金额必须大于0"); if (applyMoney.compareTo(BigDecimal.ZERO) <= 0) throw new CommonException("提现金额必须大于0");
if (param.getAccountType() == AccountTypeEnum.MONEY.getType() && applyMoney.compareTo(member.getMoney()) > 0) throw new CommonException("提现金额不能大于账户余额"); if (param.getAccountType() == AccountTypeEnum.MONEY.getType() && applyMoney.compareTo(member.getMoney()) > 0) throw new CommonException("提现金额不能大于账户余额");
if (param.getAccountType() == AccountTypeEnum.COMMISSION.getType() && applyMoney.compareTo(member.getCommission()) > 0) throw new CommonException("提现金额不能大于账户可提现金额"); if (param.getAccountType() == AccountTypeEnum.COMMISSION.getType() && applyMoney.compareTo(member.getCommission()) > 0) throw new CommonException("提现金额不能大于账户可提现金额");
if (applyMoney.compareTo(config.getMin()) <= 0) throw new CommonException("提现金额不能小于最低提现金额"); if (applyMoney.compareTo(config.getMin()) < 0) throw new CommonException("提现金额不能小于最低提现金额");
if (!config.getTransferType().contains(param.getTransferType())) throw new CommonException("当前会员提现方式未启用"); if (!config.getTransferType().contains(param.getTransferType())) throw new CommonException("当前会员提现方式未启用");
MemberCashOutAccount cashoutAccount = null; MemberCashOutAccount cashoutAccount = new MemberCashOutAccount();
if (!param.getTransferType().equals(TransferTypeEnum.WECHATPAY.getKey())) { if (!param.getTransferType().equals(TransferTypeEnum.WECHATPAY.getKey())) {
cashoutAccount = memberCashOutAccountMapper.selectOne(new QueryWrapper<MemberCashOutAccount>() cashoutAccount = memberCashOutAccountMapper.selectOne(new QueryWrapper<MemberCashOutAccount>()
.eq("member_id", param.getMemberId()) .eq("member_id", param.getMemberId())
@ -95,13 +96,16 @@ public class CoreMemberCashOutServiceImpl implements ICoreMemberCashOutService {
model.setServiceMoney(serviceMoney); model.setServiceMoney(serviceMoney);
model.setMoney(applyMoney.subtract(serviceMoney)); model.setMoney(applyMoney.subtract(serviceMoney));
model.setTransferType(param.getTransferType()); model.setTransferType(param.getTransferType());
model.setTransferRealname(cashoutAccount == null ? "" : cashoutAccount.getRealname()); model.setTransferRealname(ObjectUtil.defaultIfNull(cashoutAccount.getRealname(), ""));
model.setTransferMobile(member.getMobile()); model.setTransferMobile(member.getMobile());
model.setTransferBank(cashoutAccount == null ? "" : cashoutAccount.getBankName()); model.setTransferBank(ObjectUtil.defaultIfNull(cashoutAccount.getBankName(), ""));
model.setTransferAccount(cashoutAccount == null ? "" : cashoutAccount.getAccountNo()); model.setTransferAccount(ObjectUtil.defaultIfNull(cashoutAccount.getAccountNo(), ""));
model.setRate(config.getRate()); model.setRate(config.getRate());
model.setTransferPaymentCode(ObjectUtil.defaultIfNull(cashoutAccount.getTransferPaymentCode(), ""));
model.setTransferPayee(ObjectUtil.isNull(param.getTransferPayee()) ? "" : JSONUtil.parseObj(param.getTransferPayee()).toString());
this.addCashOutRecord(model, member, config); this.addCashOutRecord(model, member, config);
return model.getId();
} }
@Transactional @Transactional
@ -170,11 +174,6 @@ public class CoreMemberCashOutServiceImpl implements ICoreMemberCashOutService {
cashOut.setAuditTime(System.currentTimeMillis() / 1000); cashOut.setAuditTime(System.currentTimeMillis() / 1000);
cashOut.setStatus(MemberCashOutStatusEnum.WAIT_TRANSFER.getStatus()); cashOut.setStatus(MemberCashOutStatusEnum.WAIT_TRANSFER.getStatus());
memberCashOutMapper.updateById(cashOut); memberCashOutMapper.updateById(cashOut);
CashOutConfigVo config = coreMemberConfigService.getCashOutConfig(cashOut.getSiteId());
if (config.getIsAutoTransfer().equals("1")) {
this.transfer(cashOut, new CashOutTransferParam());
}
} }
/** /**
@ -182,9 +181,10 @@ public class CoreMemberCashOutServiceImpl implements ICoreMemberCashOutService {
* *
* @param cashOut * @param cashOut
*/ */
public void transfer(MemberCashOut cashOut, CashOutTransferParam param) { @Transactional
public Object transfer(MemberCashOut cashOut, CashOutTransferParam param) {
Assert.notNull(cashOut, "提现记录不存在"); Assert.notNull(cashOut, "提现记录不存在");
if (!cashOut.getStatus().equals(MemberCashOutStatusEnum.WAIT_TRANSFER.getStatus())) throw new CommonException("当前提现申请未处于待转账状态"); if (!cashOut.getStatus().equals(MemberCashOutStatusEnum.WAIT_TRANSFER.getStatus()) && !cashOut.getStatus().equals(MemberCashOutStatusEnum.TRANSFER_ING.getStatus())) throw new CommonException("当前提现申请未处于待转账状态");
if (ObjectUtil.isEmpty(cashOut.getTransferNo())) { if (ObjectUtil.isEmpty(cashOut.getTransferNo())) {
PayTransfer transfer = new PayTransfer(); PayTransfer transfer = new PayTransfer();
@ -194,7 +194,9 @@ public class CoreMemberCashOutServiceImpl implements ICoreMemberCashOutService {
transfer.setMoney(cashOut.getMoney()); transfer.setMoney(cashOut.getMoney());
transfer.setTradeType("member_cash_out"); transfer.setTradeType("member_cash_out");
transfer.setRemark(""); transfer.setRemark("");
transfer.setExtra("");
cashOut.setTransferNo(coreTransferService.create(transfer)); cashOut.setTransferNo(coreTransferService.create(transfer));
cashOut.setStatus(MemberCashOutStatusEnum.TRANSFER_ING.getStatus());
memberCashOutMapper.updateById(cashOut); memberCashOutMapper.updateById(cashOut);
} }
@ -204,20 +206,25 @@ public class CoreMemberCashOutServiceImpl implements ICoreMemberCashOutService {
String transferType = ObjectUtil.defaultIfNull(param.getTransferType(), cashOut.getTransferType()); String transferType = ObjectUtil.defaultIfNull(param.getTransferType(), cashOut.getTransferType());
if (!transferType.equals(TransferTypeEnum.OFFLINE.getKey())) { if (!transferType.equals("offline")) {
data.put("transfer_type", cashOut.getTransferType()); data.put("transfer_type", cashOut.getTransferType());
data.put("transfer_realname", cashOut.getTransferRealname()); data.put("transfer_realname", cashOut.getTransferRealname());
data.put("transfer_mobile", cashOut.getTransferMobile()); data.put("transfer_mobile", cashOut.getTransferMobile());
data.put("transfer_bank", cashOut.getTransferBank()); data.put("transfer_bank", cashOut.getTransferBank());
data.put("transfer_account", cashOut.getTransferAccount()); data.put("transfer_account", cashOut.getTransferAccount());
data.put("transfer_payment_code", cashOut.getTransferPaymentCode());
if (cashOut.getTransferType().equals(TransferTypeEnum.WECHATPAY.getKey())) { if (cashOut.getTransferType().equals(TransferTypeEnum.WECHATPAY.getKey())) {
Member member = memberMapper.selectOne(new QueryWrapper<Member>().select("wx_openid, weapp_openid").eq("member_id", cashOut.getMemberId())); JSONObject transferPayee = new JSONObject();
data.put("openid", ObjectUtil.defaultIfEmpty(member.getWxOpenid(), member.getWeappOpenid())); transferPayee.put("open_id", param.getOpenId());
transferPayee.put("channel", param.getChannel());
data.put("transfer_payee", transferPayee.toString());
} }
} else {
transferType = cashOut.getTransferType();
} }
coreTransferService.transfer(cashOut.getSiteId(), cashOut.getTransferNo(), transferType, data); return coreTransferService.transfer(cashOut.getSiteId(), cashOut.getTransferNo(), transferType, data);
} }
/** /**
@ -228,7 +235,7 @@ public class CoreMemberCashOutServiceImpl implements ICoreMemberCashOutService {
public void transferFinish(String transferNo) { public void transferFinish(String transferNo) {
MemberCashOut cashOut = memberCashOutMapper.selectOne(new QueryWrapper<MemberCashOut>().eq("transfer_no", transferNo)); MemberCashOut cashOut = memberCashOutMapper.selectOne(new QueryWrapper<MemberCashOut>().eq("transfer_no", transferNo));
Assert.notNull(cashOut, "提现记录不存在"); Assert.notNull(cashOut, "提现记录不存在");
if (!cashOut.getStatus().equals(MemberCashOutStatusEnum.WAIT_TRANSFER.getStatus())) throw new CommonException("当前提现申请未处于待转账状态"); if (!cashOut.getStatus().equals(MemberCashOutStatusEnum.WAIT_TRANSFER.getStatus()) && !cashOut.getStatus().equals(MemberCashOutStatusEnum.TRANSFER_ING.getStatus())) throw new CommonException("当前提现申请未处于待转账状态");
cashOut.setTransferTime(System.currentTimeMillis() / 1000); cashOut.setTransferTime(System.currentTimeMillis() / 1000);
cashOut.setStatus(MemberCashOutStatusEnum.TRANSFERED.getStatus()); cashOut.setStatus(MemberCashOutStatusEnum.TRANSFERED.getStatus());
@ -290,4 +297,47 @@ public class CoreMemberCashOutServiceImpl implements ICoreMemberCashOutService {
} }
memberMapper.updateById(updateMember); memberMapper.updateById(updateMember);
} }
/**
* 撤销提现
* @param siteId
* @param id
*/
@Override
public void cancel(Integer siteId, Integer id) {
MemberCashOut cashOut = memberCashOutMapper.selectOne(new QueryWrapper<MemberCashOut>().eq("id", id).eq("site_id", siteId));
Assert.notNull(cashOut, "提现记录不存在");
Integer[] status = new Integer[]{
MemberCashOutStatusEnum.WAIT_AUDIT.getStatus(),
MemberCashOutStatusEnum.WAIT_TRANSFER.getStatus(),
MemberCashOutStatusEnum.TRANSFER_ING.getStatus()
};
if (!ObjectUtil.contains(status, cashOut.getStatus())) {
throw new CommonException("当前提现申请不支持撤销");
}
if (cashOut.getTransferType().equals(TransferTypeEnum.WECHATPAY.getKey()) && cashOut.getStatus().equals(MemberCashOutStatusEnum.TRANSFER_ING.getStatus())) {
// 微信提现撤销
coreTransferService.cancel(cashOut.getSiteId(), cashOut.getTransferNo());
}
cashOut.setStatus(MemberCashOutStatusEnum.CANCEL.getStatus());
memberCashOutMapper.updateById(cashOut);
giveback(cashOut);
}
/**
* 检测转账状态
* @param siteId
* @param id
*/
@Override
public void checkTransferStatus(Integer siteId, Integer id) {
MemberCashOut cashOut = memberCashOutMapper.selectOne(new QueryWrapper<MemberCashOut>().eq("id", id).eq("site_id", siteId));
Assert.notNull(cashOut, "提现记录不存在");
coreTransferService.check(cashOut.getSiteId(), cashOut.getTransferNo());
}
} }

View File

@ -24,4 +24,13 @@ public class MemberCashOutApplyParam {
private Integer accountId = 0; private Integer accountId = 0;
private TransferPayee transferPayee;
@Data
public static class TransferPayee {
private String openId;
private String channel;
}
} }

View File

@ -0,0 +1,41 @@
package com.niu.core.service.core.pay;
import cn.hutool.json.JSONObject;
import com.niu.core.service.core.pay.param.SetTradeSceneParam;
import com.niu.core.service.core.pay.vo.TransferSceneInfo;
import com.niu.core.service.core.pay.vo.WechatTransferSceneListVo;
import java.util.List;
import java.util.Map;
public interface ICoreTransferSceneService {
/**
* 获取微信转账场景配置
* @param siteId
*/
JSONObject getWechatTransferSceneConfig(Integer siteId);
/**
* 设置微信转账场景配置
* @param siteId
*/
void setWechatTransferSceneConfig(Integer siteId, JSONObject data);
/**
* 获取转账场景
* @param siteId
*/
Map<String, WechatTransferSceneListVo> getWechatTransferScene(Integer siteId);
/**
* 通过业务设置转账场景的配置信息
* @param siteId
*/
void setTradeScene(Integer siteId, String type, SetTradeSceneParam param);
/**
* 通过业务获取转账场景的配置信息
*/
TransferSceneInfo getSceneInfoByType(Integer siteId, String type);
}

View File

@ -18,9 +18,13 @@ public interface ICoreTransferService {
String create(PayTransfer model); String create(PayTransfer model);
void transfer(Integer siteId, String transferNo, String transferType, Map<String, Object> data); Object transfer(Integer siteId, String transferNo, String transferType, Map<String, Object> data);
PayTransfer findTransferByTransferNo(Integer siteId, String transferNo); PayTransfer findTransferByTransferNo(Integer siteId, String transferNo);
void transferNotify(TransferNotifyParam param); void transferNotify(TransferNotifyParam param);
void cancel(Integer siteId, String transferNo);
void check(Integer siteId, String transferNo);
} }

View File

@ -26,6 +26,7 @@ import com.niu.core.service.core.pay.ICorePayService;
import com.niu.core.service.core.pay.ICoreRefundService; import com.niu.core.service.core.pay.ICoreRefundService;
import com.niu.core.service.core.pay.ICoreTransferService; import com.niu.core.service.core.pay.ICoreTransferService;
import com.niu.core.service.core.pay.vo.PayTypeVo; import com.niu.core.service.core.pay.vo.PayTypeVo;
import com.niu.core.service.core.pay.vo.TransferQueryVo;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -214,7 +215,7 @@ public class Alipay extends BasePay {
/** /**
* 转账 * 转账
*/ */
public void transfer(TransferParam param) { public Object transfer(TransferParam param) {
try { try {
PayTransfer transfer = param.getTransfer(); PayTransfer transfer = param.getTransfer();
@ -246,6 +247,18 @@ public class Alipay extends BasePay {
} catch (Exception e) { } catch (Exception e) {
throw new CommonException(e.getMessage()); throw new CommonException(e.getMessage());
} }
return null;
}
@Override
public Object transferCancel(String transferNo) {
return null;
}
@Override
public TransferQueryVo transferQuery(String transferNo) {
return null;
} }
private TransferStatusEnum handleTransferStatus(String state) { private TransferStatusEnum handleTransferStatus(String state) {

View File

@ -16,6 +16,7 @@ import com.niu.core.service.core.member.ICoreMemberAccountService;
import com.niu.core.service.core.pay.ICorePayService; import com.niu.core.service.core.pay.ICorePayService;
import com.niu.core.service.core.pay.ICoreRefundService; import com.niu.core.service.core.pay.ICoreRefundService;
import com.niu.core.service.core.pay.vo.PayTypeVo; import com.niu.core.service.core.pay.vo.PayTypeVo;
import com.niu.core.service.core.pay.vo.TransferQueryVo;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
@ -86,7 +87,21 @@ public class Balancepay extends BasePay {
/** /**
* 转账 * 转账
*/ */
public void transfer(TransferParam param) { public Object transfer(TransferParam param) {
return null;
}
/**
* 转账撤销
*/
@Override
public Object transferCancel(String transferNo) {
return null;
}
@Override
public TransferQueryVo transferQuery(String transferNo) {
return null;
} }
/** /**

View File

@ -10,6 +10,7 @@ import com.niu.core.common.loader.pay.param.TransferParam;
import com.niu.core.entity.pay.Pay; import com.niu.core.entity.pay.Pay;
import com.niu.core.enums.pay.PayTypeEnum; import com.niu.core.enums.pay.PayTypeEnum;
import com.niu.core.service.core.pay.vo.PayTypeVo; import com.niu.core.service.core.pay.vo.PayTypeVo;
import com.niu.core.service.core.pay.vo.TransferQueryVo;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
@ -44,8 +45,18 @@ public class FriendPay extends BasePay {
} }
@Override @Override
public void transfer(TransferParam param) { public Object transfer(TransferParam param) {
return null;
}
@Override
public Object transferCancel(String transferNo) {
return null;
}
@Override
public TransferQueryVo transferQuery(String transferNo) {
return null;
} }
@Override @Override

View File

@ -4,14 +4,14 @@ import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.binarywang.wxpay.bean.notify.*; import com.github.binarywang.wxpay.bean.notify.*;
import com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request; import com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request; import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result; import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result; import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum; import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.bean.transfer.TransferBatchesRequest; import com.github.binarywang.wxpay.bean.transfer.*;
import com.github.binarywang.wxpay.bean.transfer.TransferBatchesResult;
import com.github.binarywang.wxpay.config.WxPayConfig; import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.service.WxPayService; import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl; import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
@ -28,10 +28,14 @@ import com.niu.core.enums.pay.OnliepayStatusEnum;
import com.niu.core.enums.pay.PayTypeEnum; import com.niu.core.enums.pay.PayTypeEnum;
import com.niu.core.enums.pay.RefundTransferStatusEnum; import com.niu.core.enums.pay.RefundTransferStatusEnum;
import com.niu.core.enums.pay.TransferStatusEnum; import com.niu.core.enums.pay.TransferStatusEnum;
import com.niu.core.mapper.pay.PayTransferMapper;
import com.niu.core.service.core.pay.ICorePayService; import com.niu.core.service.core.pay.ICorePayService;
import com.niu.core.service.core.pay.ICoreRefundService; import com.niu.core.service.core.pay.ICoreRefundService;
import com.niu.core.service.core.pay.ICoreTransferSceneService;
import com.niu.core.service.core.pay.ICoreTransferService; import com.niu.core.service.core.pay.ICoreTransferService;
import com.niu.core.service.core.pay.vo.PayTypeVo; import com.niu.core.service.core.pay.vo.PayTypeVo;
import com.niu.core.service.core.pay.vo.TransferQueryVo;
import com.niu.core.service.core.pay.vo.TransferSceneInfo;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -66,6 +70,14 @@ public class Wechatpay extends BasePay {
return SpringContext.bean(ICoreTransferService.class); return SpringContext.bean(ICoreTransferService.class);
} }
public PayTransferMapper payTransferMapper() {
return SpringContext.bean(PayTransferMapper.class);
}
public ICoreTransferSceneService coreTransferSceneService() {
return SpringContext.bean(ICoreTransferSceneService.class);
}
public BasePay init(JSONObject config) { public BasePay init(JSONObject config) {
this.config = config; this.config = config;
payConfig = new WxPayConfig(); payConfig = new WxPayConfig();
@ -306,27 +318,25 @@ public class Wechatpay extends BasePay {
} }
private Object transferNotify(PayAsyncNotifyParam param, HttpServletRequest request, HttpServletResponse response) { private Object transferNotify(PayAsyncNotifyParam param, HttpServletRequest request, HttpServletResponse response) {
// try { try {
// WxPayTransferBatchesNotifyV3Result result = app().parseTransferBatchesNotifyV3Result(getRequestBody(request), getRequestHeader(request)); TransferBillsNotifyResult result = app().parseTransferBillsNotifyV3Result(getRequestBody(request), getRequestHeader(request));
// WxPayTransferBatchesNotifyV3Result.DecryptNotifyResult notifyResult = result.getResult(); TransferBillsNotifyResult.DecryptNotifyResult notifyResult = result.getResult();
//
// if (result.getRawData().getEventType().equals("MCHTRANSFER.BATCH.FINISHED")) { if (result.getRawData().getEventType().equals("MCHTRANSFER.BILL.FINISHED")) {
// TransferNotifyParam notifyParam = new TransferNotifyParam(); TransferNotifyParam notifyParam = new TransferNotifyParam();
// notifyParam.setSiteId(param.getSiteId()); notifyParam.setSiteId(param.getSiteId());
// notifyParam.setTransferNo(notifyResult.getOutBatchNo()); notifyParam.setTransferNo(notifyResult.getOutBillNo());
// notifyParam.setTransferStatus(handleTransferStatus(notifyResult.getBatchStatus())); notifyParam.setTransferStatus(handleTransferStatus(notifyResult.getState()));
// coreTransferService.transferNotify(notifyParam); coreTransferService().transferNotify(notifyParam);
// return WxPayNotifyV3Response.success("SUCCESS");
// return WxPayNotifyV3Response.success("SUCCESS"); } else {
// } else { log.error("微信转账回调通知失败:{}", result);
// log.error("微信转账回调通知失败:{}", result); return WxPayNotifyV3Response.fail("微信转账回调通知失败");
// return WxPayNotifyV3Response.fail("微信转账回调通知失败"); }
// } } catch (Exception e) {
// } catch (Exception e) { log.error("微信转账回调结果异常,异常原因{}", e.getMessage());
// log.error("微信转账回调结果异常,异常原因{}", e.getMessage()); return WxPayNotifyV3Response.fail(e.getMessage());
// return WxPayNotifyV3Response.fail(e.getMessage()); }
// }
return null;
} }
private String getRequestBody(HttpServletRequest request) throws IOException { private String getRequestBody(HttpServletRequest request) throws IOException {
@ -364,36 +374,106 @@ public class Wechatpay extends BasePay {
/** /**
* 转账 * 转账
*/ */
public void transfer(TransferParam param) { public Object transfer(TransferParam param) {
try { try {
PayTransfer transfer = param.getTransfer(); PayTransfer transfer = param.getTransfer();
JSONObject transferPayee = JSONUtil.parseObj(transfer.getTransferPayee());
List<TransferBatchesRequest.TransferDetail> transferDetailList = new LinkedList<>(); TransferSceneInfo transferSceneInfo = coreTransferSceneService().getSceneInfoByType(transfer.getSiteId(), transfer.getTradeType());
TransferBatchesRequest.TransferDetail transferDetail = new TransferBatchesRequest.TransferDetail();
transferDetail.setOutDetailNo(transfer.getTransferNo()); TransferBillsRequest request = new TransferBillsRequest();
transferDetail.setTransferAmount(transfer.getMoney().multiply(new BigDecimal(100)).intValue()); if (transferPayee.getStr("channel", "").equals(ChannelEnum.WECHAT.getCode())) {
transferDetail.setOpenid(transfer.getOpenid()); request.setAppid(config.getStr("mp_app_id", ""));
transferDetail.setTransferRemark(transfer.getRemark()); } else {
if (transfer.getMoney().multiply(new BigDecimal(100)).intValue() > 200000) { request.setAppid(config.getStr("mini_app_id", ""));
transferDetail.setUserName(transfer.getTransferRealname());
} }
request.setOutBillNo(transfer.getTransferNo());
request.setTransferSceneId(transferSceneInfo.getSceneId());
request.setOpenid(transferPayee.getStr("open_id", ""));
if (transfer.getMoney().multiply(new BigDecimal(100)).intValue() > 200000) {
request.setUserName(transfer.getTransferRealname());
}
request.setTransferAmount(transfer.getMoney().multiply(new BigDecimal(100)).intValue());
request.setTransferRemark(ObjectUtil.defaultIfEmpty(transfer.getRemark(), "提现转账"));
request.setNotifyUrl(param.getNotifyUrl());
request.setUserRecvPerception(transferSceneInfo.getPerception());
TransferBatchesRequest request = new TransferBatchesRequest(); List<TransferBillsRequest.TransferSceneReportInfo> transferSceneReportInfos = new LinkedList<>();
request.setAppid(config.getStr("mp_app_id", "")); JSONObject infos = JSONUtil.parseObj(transferSceneInfo.getInfos());
request.setOutBatchNo(transfer.getTransferNo()); for (String type: infos.keySet()) {
request.setBatchName(""); TransferBillsRequest.TransferSceneReportInfo info = new TransferBillsRequest.TransferSceneReportInfo();
request.setBatchRemark(transfer.getRemark()); info.setInfoType(type);
request.setTotalAmount(transfer.getMoney().multiply(new BigDecimal(100)).intValue()); info.setInfoContent(infos.getStr(type, ""));
request.setTotalNum(1); transferSceneReportInfos.add(info);
request.setTransferDetailList(transferDetailList); }
app().getConfig().setNotifyUrl(param.getNotifyUrl()); request.setTransferSceneReportInfos(transferSceneReportInfos);
TransferBatchesResult result = app().getTransferService().transferBatches(request); TransferBillsResult transferResult = app().getTransferService().transferBills(request);
TransferNotifyParam notifyParam = new TransferNotifyParam(); TransferNotifyParam notifyParam = new TransferNotifyParam();
notifyParam.setSiteId(transfer.getSiteId()); notifyParam.setSiteId(transfer.getSiteId());
notifyParam.setTransferNo(transfer.getTransferNo()); notifyParam.setTransferNo(transfer.getTransferNo());
notifyParam.setTransferStatus(handleTransferStatus(result.getBatchStatus())); notifyParam.setTransferStatus(handleTransferStatus(transferResult.getState()));
coreTransferService().transferNotify(notifyParam); coreTransferService().transferNotify(notifyParam);
Map<String, Object> result = new HashMap<>();
result.put("mch_id", config.getStr("mch_id", ""));
result.put("appid", request.getAppid());
result.put("out_bill_no", transferResult.getOutBillNo());
result.put("transfer_bill_no", transferResult.getTransferBillNo());
result.put("status", transferResult.getState());
result.put("reason", transferResult.getFailReason());
result.put("package_info", transferResult.getPackageInfo());
result.put("extra", JSONUtil.parseObj(result));
transfer.setOutBatchNo((String) result.get("out_bill_no"));
transfer.setPackageInfo((String) result.get("package_info"));
transfer.setExtra(((JSONObject) result.get("extra")).toString());
payTransferMapper().updateById(transfer);
return result;
} catch (Exception e) {
throw new CommonException(e.getMessage());
}
}
/**
* 撤销转账
* @param transferNo
* @return
*/
@Override
public Object transferCancel(String transferNo) {
try {
PayTransfer transfer = payTransferMapper().selectOne(new QueryWrapper<PayTransfer>().eq("transfer_no", transferNo));
TransferBillsCancelResult result = app().getTransferService().transformBillsCancel(transferNo);
TransferNotifyParam notifyParam = new TransferNotifyParam();
notifyParam.setSiteId(transfer.getSiteId());
notifyParam.setTransferNo(transfer.getTransferNo());
notifyParam.setTransferStatus(handleTransferStatus(result.getState()));
coreTransferService().transferNotify(notifyParam);
return null;
} catch (Exception e) {
throw new CommonException(e.getMessage());
}
}
/**
* 查询转账单
* @param transferNo
* @return
*/
@Override
public TransferQueryVo transferQuery(String transferNo) {
try {
TransferBillsGetResult result = app().getTransferService().getBillsByOutBillNo(transferNo);
TransferQueryVo vo = new TransferQueryVo();
vo.setTransferNo(transferNo);
vo.setTransferSatus(handleTransferStatus(result.getState()));
vo.setFailReason(result.getFailReason());
vo.setOriginal(result);
return vo;
} catch (Exception e) { } catch (Exception e) {
throw new CommonException(e.getMessage()); throw new CommonException(e.getMessage());
} }
@ -401,9 +481,14 @@ public class Wechatpay extends BasePay {
private TransferStatusEnum handleTransferStatus(String state) { private TransferStatusEnum handleTransferStatus(String state) {
Map<String, TransferStatusEnum> map = new HashMap<>(); Map<String, TransferStatusEnum> map = new HashMap<>();
map.put("FINISHED", TransferStatusEnum.SUCCESS); map.put("ACCEPTED", TransferStatusEnum.DEALING);
map.put("PROCESSING", TransferStatusEnum.DEALING); map.put("PROCESSING", TransferStatusEnum.DEALING);
map.put("CLOSED", TransferStatusEnum.FAIL); map.put("WAIT_USER_CONFIRM", TransferStatusEnum.WAIT_USER);
map.put("TRANSFERING", TransferStatusEnum.DEALING);
map.put("SUCCESS", TransferStatusEnum.SUCCESS);
map.put("FAIL", TransferStatusEnum.FAIL);
map.put("CANCELING", TransferStatusEnum.FAIL_ING);
map.put("CANCELLED", TransferStatusEnum.FAIL);
return map.get(state); return map.get(state);
} }

View File

@ -0,0 +1,141 @@
package com.niu.core.service.core.pay.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.niu.core.common.utils.RequestUtils;
import com.niu.core.common.utils.json.JsonModuleLoader;
import com.niu.core.entity.pay.PayTransferScene;
import com.niu.core.enums.pay.TransferSceneEnum;
import com.niu.core.enums.sys.ConfigKeyEnum;
import com.niu.core.mapper.pay.PayTransferSceneMapper;
import com.niu.core.service.core.pay.ICoreTransferSceneService;
import com.niu.core.service.core.pay.param.SetTradeSceneParam;
import com.niu.core.service.core.pay.vo.TransferSceneInfo;
import com.niu.core.service.core.pay.vo.WechatTransferSceneListVo;
import com.niu.core.service.core.sys.ICoreConfigService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class CoreTransferSceneServiceImpl implements ICoreTransferSceneService {
private final ICoreConfigService coreConfigService;
private final PayTransferSceneMapper payTransferSceneMapper;
/**
* 获取微信转账场景配置
* @param siteId
*/
@Override
public JSONObject getWechatTransferSceneConfig(Integer siteId) {
JSONObject config = coreConfigService.getConfigValue(siteId, ConfigKeyEnum.WECHAT_TRANSFER_SCENE_CONFIG.getName());
if (ObjectUtil.isNull(config)) return new JSONObject();
return config;
}
/**
* 设置微信转账场景配置
* @param siteId
*/
@Override
public void setWechatTransferSceneConfig(Integer siteId, JSONObject data) {
coreConfigService.setConfig(siteId, ConfigKeyEnum.WECHAT_TRANSFER_SCENE_CONFIG.getName(), data);
}
/**
* 获取转账场景
* @param siteId
*/
@Override
public Map<String, WechatTransferSceneListVo> getWechatTransferScene(Integer siteId) {
Map<String, TransferSceneEnum> tradeScenelist = TransferSceneEnum.getWechatTransferSceneMap();
JSONObject config = getWechatTransferSceneConfig(siteId);
JSONObject tradeSceneEventArray = JsonModuleLoader.build().mergeResultElement(RequestUtils.siteId(), "pay/wechat_transfer_scene.json");
Map<String, PayTransferScene> tradeSceneColumn = payTransferSceneMapper.selectList(new QueryWrapper<PayTransferScene>().eq("site_id", siteId)).stream().collect(Collectors.toMap(PayTransferScene::getType, i -> i));
JSONObject tradeSceneList = new JSONObject();
for(String key: tradeSceneEventArray.keySet()) {
JSONObject tradeSceneItem = tradeSceneEventArray.getJSONObject(key);
PayTransferScene tradeSceneSelectData = tradeSceneColumn.get(key);
if (tradeSceneSelectData == null) {
tradeSceneList.putByPath(tradeSceneItem.getStr("scene") + "." + key, tradeSceneItem);
} else {
tradeSceneList.putByPath(tradeSceneItem.getStr("scene") + "." + key, tradeSceneSelectData);
tradeSceneList.putByPath(tradeSceneItem.getStr("scene") + "." + key + ".infos", JSONUtil.parseObj(tradeSceneSelectData.getInfos()));
tradeSceneList.putByPath(tradeSceneItem.getStr("scene") + "." + key + ".name", tradeSceneItem.getStr("name"));
}
}
Map<String, WechatTransferSceneListVo> list = new HashMap<>();
for (Map.Entry<String, TransferSceneEnum> item : tradeScenelist.entrySet()) {
WechatTransferSceneListVo vo = new WechatTransferSceneListVo();
vo.setName(item.getValue().getName());
vo.setTransferSceneReportInfos(item.getValue().getTransferSceneReportInfos());
vo.setUserRecvPerception(item.getValue().getUserRecvPerception());
vo.setSceneId(config.getStr(item.getValue().getScene(), ""));
if (tradeSceneList.get(item.getValue().getScene()) != null) {
vo.setTradeSceneData(tradeSceneList.getJSONObject(item.getValue().getScene()));
}
list.put(item.getValue().getScene(), vo);
}
return list;
}
/**
* 通过业务设置转账场景的配置信息
* @param siteId
*/
@Override
public void setTradeScene(Integer siteId, String type, SetTradeSceneParam param) {
PayTransferScene tradeScene = payTransferSceneMapper.selectOne(new QueryWrapper<PayTransferScene>().eq("site_id", siteId).eq("type", type));
PayTransferScene model = new PayTransferScene();
model.setSiteId(siteId);
model.setType(type);
model.setPerception(param.getPerception());
model.setScene(param.getScene());
model.setInfos(param.getInfos().toString());
if (tradeScene == null) {
model.setCreateTime(System.currentTimeMillis() / 1000);
payTransferSceneMapper.insert(model);
} else {
model.setId(tradeScene.getId());
payTransferSceneMapper.updateById(model);
}
}
/**
* 通过业务获取转账场景的配置信息
*/
@Override
public TransferSceneInfo getSceneInfoByType(Integer siteId, String type) {
PayTransferScene tradeScene = payTransferSceneMapper.selectOne(new QueryWrapper<PayTransferScene>().eq("site_id", siteId).eq("type", type));
TransferSceneInfo vo = new TransferSceneInfo();
if (tradeScene == null) {
JSONObject transferScene = JsonModuleLoader.build().mergeResultElement(RequestUtils.siteId(), "pay/wechat_transfer_scene.json");
vo = JSONUtil.toBean(transferScene.getJSONObject(type), TransferSceneInfo.class);
} else {
BeanUtil.copyProperties(tradeScene, vo);
}
JSONObject config = getWechatTransferSceneConfig(siteId);
vo.setSceneId(config.getStr(vo.getScene(), ""));
return vo;
}
}

View File

@ -3,15 +3,18 @@ package com.niu.core.service.core.pay.impl;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Snowflake; import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.binarywang.wxpay.bean.transfer.TransferBillsResult;
import com.niu.core.common.domain.PageParam; import com.niu.core.common.domain.PageParam;
import com.niu.core.common.domain.PageResult; import com.niu.core.common.domain.PageResult;
import com.niu.core.common.exception.CommonException; import com.niu.core.common.exception.CommonException;
import com.niu.core.common.loader.pay.param.TransferNotifyParam; import com.niu.core.common.loader.pay.param.TransferNotifyParam;
import com.niu.core.common.loader.pay.param.TransferParam; import com.niu.core.common.loader.pay.param.TransferParam;
import com.niu.core.entity.pay.PayTransfer; import com.niu.core.entity.pay.PayTransfer;
import com.niu.core.enums.member.MemberCashOutStatusEnum;
import com.niu.core.enums.pay.TransferStatusEnum; import com.niu.core.enums.pay.TransferStatusEnum;
import com.niu.core.enums.pay.TransferTypeEnum; import com.niu.core.enums.pay.TransferTypeEnum;
import com.niu.core.event.pay.PayCloseEvent; import com.niu.core.event.pay.PayCloseEvent;
@ -24,6 +27,7 @@ import com.niu.core.service.core.pay.param.PayTransferParam;
import com.niu.core.service.core.pay.param.PayTransferSearchParam; import com.niu.core.service.core.pay.param.PayTransferSearchParam;
import com.niu.core.service.core.pay.vo.PayTransferInfoVo; import com.niu.core.service.core.pay.vo.PayTransferInfoVo;
import com.niu.core.service.core.pay.vo.PayTransferListVo; import com.niu.core.service.core.pay.vo.PayTransferListVo;
import com.niu.core.service.core.pay.vo.TransferQueryVo;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -90,7 +94,7 @@ public class CoreTransferServiceImpl implements ICoreTransferService {
* @param data * @param data
*/ */
@Transactional @Transactional
public void transfer(Integer siteId, String transferNo, String transferType, Map<String, Object> data) { public Object transfer(Integer siteId, String transferNo, String transferType, Map<String, Object> data) {
PayTransfer transfer = findTransferByTransferNo(siteId, transferNo); PayTransfer transfer = findTransferByTransferNo(siteId, transferNo);
if (transfer == null) throw new CommonException("无效的转账单据"); if (transfer == null) throw new CommonException("无效的转账单据");
if (!transfer.getTransferStatus().equals(TransferStatusEnum.WAIT.getStatus()) && !transfer.getTransferStatus().equals(TransferStatusEnum.FAIL.getStatus())) { if (!transfer.getTransferStatus().equals(TransferStatusEnum.WAIT.getStatus()) && !transfer.getTransferStatus().equals(TransferStatusEnum.FAIL.getStatus())) {
@ -105,6 +109,8 @@ public class CoreTransferServiceImpl implements ICoreTransferService {
transfer.setTransferMobile((String) data.getOrDefault("transfer_mobile", "")); transfer.setTransferMobile((String) data.getOrDefault("transfer_mobile", ""));
transfer.setTransferAccount((String) data.getOrDefault("transfer_account", "")); transfer.setTransferAccount((String) data.getOrDefault("transfer_account", ""));
transfer.setOpenid((String) data.getOrDefault("openid", "")); transfer.setOpenid((String) data.getOrDefault("openid", ""));
transfer.setTransferPayee((String) data.getOrDefault("transfer_payee", ""));
transfer.setTransferPaymentCode((String) data.getOrDefault("transfer_payment_code", ""));
payTransferMapper.updateById(transfer); payTransferMapper.updateById(transfer);
Map transferTypeEnum = TransferTypeEnum.getMap().get(transferType); Map transferTypeEnum = TransferTypeEnum.getMap().get(transferType);
@ -114,10 +120,10 @@ public class CoreTransferServiceImpl implements ICoreTransferService {
TransferParam param = new TransferParam(); TransferParam param = new TransferParam();
param.setTransfer(transfer); param.setTransfer(transfer);
param.setNotifyUrl(corePayService.buildNotifyUrl(siteId, "transfer", transferType, "transfer")); param.setNotifyUrl(corePayService.buildNotifyUrl(siteId, "transfer", transferType, "transfer"));
corePayService.driver(siteId, "transfer", transferType).transfer(param); return corePayService.driver(siteId, "transfer", transferType).transfer(param);
return;
} }
this.success(transfer); this.success(transfer);
return null;
} }
@Transactional @Transactional
@ -130,14 +136,72 @@ public class CoreTransferServiceImpl implements ICoreTransferService {
if (param.getTransferStatus().getStatus().equals(TransferStatusEnum.SUCCESS.getStatus())) { if (param.getTransferStatus().getStatus().equals(TransferStatusEnum.SUCCESS.getStatus())) {
this.success(transfer); this.success(transfer);
} } else if (param.getTransferStatus().getStatus().equals(TransferStatusEnum.FAIL.getStatus())) {
if (param.getTransferStatus().getStatus().equals(TransferStatusEnum.FAIL.getStatus())) {
transfer.setTransferFailReason(param.getFailReason()); transfer.setTransferFailReason(param.getFailReason());
this.fail(transfer); this.fail(transfer);
} else {
transfer.setTransferStatus(param.getTransferStatus().getStatus());
this.dealing(transfer);
} }
} }
/**
* 撤销转账
* @param transferNo
*/
@Override
public void cancel(Integer siteId, String transferNo) {
PayTransfer transfer = findTransferByTransferNo(siteId, transferNo);
if (transfer == null) throw new CommonException("无效的转账单据");
String[] status = new String[]{
TransferStatusEnum.WAIT.getStatus(),
TransferStatusEnum.DEALING.getStatus(),
TransferStatusEnum.FAIL.getStatus(),
TransferStatusEnum.WAIT_USER.getStatus(),
TransferStatusEnum.WAIT_USER_ING.getStatus(),
TransferStatusEnum.FAIL_ING.getStatus()
};
if (!ObjectUtil.contains(status, transfer.getTransferStatus())) {
throw new CommonException("转账状态已发生变化");
}
corePayService.driver(siteId, "transfer", transfer.getTransferType()).transferCancel(transferNo);
}
/**
*
* @param transferNo
*/
@Override
public void check(Integer siteId, String transferNo) {
PayTransfer transfer = findTransferByTransferNo(siteId, transferNo);
if (transfer == null) throw new CommonException("无效的转账单据");
String[] status = new String[]{
TransferStatusEnum.WAIT.getStatus(),
TransferStatusEnum.DEALING.getStatus(),
TransferStatusEnum.FAIL.getStatus(),
TransferStatusEnum.WAIT_USER.getStatus(),
TransferStatusEnum.WAIT_USER_ING.getStatus(),
TransferStatusEnum.FAIL_ING.getStatus()
};
if (!ObjectUtil.contains(status, transfer.getTransferStatus())) {
throw new CommonException("只有待转账和转账中的订单可以校验");
}
TransferQueryVo transferResult = corePayService.driver(siteId, "transfer", transfer.getTransferType()).transferQuery(transferNo);
if (transferResult == null) throw new CommonException("查询不到转账信息");
TransferNotifyParam param = new TransferNotifyParam();
param.setSiteId(siteId);
param.setTransferNo(transferNo);
param.setTransferStatus(transferResult.getTransferSatus());
param.setFailReason(ObjectUtil.defaultIfNull(transferResult.getFailReason(), ""));
transferNotify(param);
}
/** /**
* 转账成功 * 转账成功
* *
@ -163,6 +227,16 @@ public class CoreTransferServiceImpl implements ICoreTransferService {
*/ */
private void fail(PayTransfer transfer) { private void fail(PayTransfer transfer) {
transfer.setTransferStatus(TransferStatusEnum.FAIL.getStatus()); transfer.setTransferStatus(TransferStatusEnum.FAIL.getStatus());
transfer.setTransferTime(System.currentTimeMillis() / 1000);
payTransferMapper.updateById(transfer);
}
/**
* 转账处理中
*
* @param transfer
*/
private void dealing(PayTransfer transfer) {
payTransferMapper.updateById(transfer); payTransferMapper.updateById(transfer);
} }
} }

Some files were not shown because too many files have changed in this diff Show More