修复已知问题
新增好友代付功能
优化wap端分包方案
This commit is contained in:
wangchen147 2025-01-16 09:32:47 +08:00
parent 81d3c3bce0
commit 71d3055aeb
2895 changed files with 13817 additions and 6509 deletions

View File

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

14
admin/components.d.ts vendored
View File

@ -11,9 +11,15 @@ declare module '@vue/runtime-core' {
DiyLink: typeof import('./src/components/diy-link/index.vue')['default']
Editor: typeof import('./src/components/editor/index.vue')['default']
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']
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']
ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
ElCol: typeof import('element-plus/es')['ElCol']
@ -28,6 +34,8 @@ declare module '@vue/runtime-core' {
ElDialog: typeof import('element-plus/es')['ElDialog']
ElDrawer: typeof import('element-plus/es')['ElDrawer']
ElDropdown: typeof import('element-plus/es')['ElDropdown']
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
ElEmpty: typeof import('element-plus/es')['ElEmpty']
ElForm: typeof import('element-plus/es')['ElForm']
ElFormItem: typeof import('element-plus/es')['ElFormItem']
@ -38,14 +46,19 @@ declare module '@vue/runtime-core' {
ElInput: typeof import('element-plus/es')['ElInput']
ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
ElLink: typeof import('element-plus/es')['ElLink']
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']
ElOptionGroup: typeof import('element-plus/es')['ElOptionGroup']
ElPageHeader: typeof import('element-plus/es')['ElPageHeader']
ElPagination: typeof import('element-plus/es')['ElPagination']
ElPopover: typeof import('element-plus/es')['ElPopover']
ElProgress: typeof import('element-plus/es')['ElProgress']
ElRadio: typeof import('element-plus/es')['ElRadio']
ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
ElRate: typeof import('element-plus/es')['ElRate']
ElResult: typeof import('element-plus/es')['ElResult']
ElRow: typeof import('element-plus/es')['ElRow']
ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
@ -54,6 +67,7 @@ declare module '@vue/runtime-core' {
ElStatistic: typeof import('element-plus/es')['ElStatistic']
ElStep: typeof import('element-plus/es')['ElStep']
ElSteps: typeof import('element-plus/es')['ElSteps']
ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
ElSwitch: typeof import('element-plus/es')['ElSwitch']
ElTable: typeof import('element-plus/es')['ElTable']
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']

View File

@ -9,7 +9,7 @@ import request from '@/utils/request'
* @returns
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
export function getCashOutList(params: Record<string, any>) {
return request.get(`member/cash_out`, { params })
return request.get(`member/cash_out`, {params})
}
/**
@ -357,7 +357,7 @@ export function getCashOutDetail(id: number) {
* @param params
*/
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})
}
/**
@ -365,7 +365,7 @@ export function memberAudit(params: Record<string, any>) {
* @param params
*/
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})
}
/**
@ -373,7 +373,7 @@ export function memberTransfer(params: Record<string, any>) {
* @param params
*/
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,6 +422,7 @@ export function getGrowthRuleDict() {
export function getPointRuleDict() {
return request.get(`member/dict/point_rule`)
}
/***************************************************** 会员等级 ****************************************************/
/**
@ -430,7 +431,7 @@ export function getPointRuleDict() {
* @returns
*/
export function getMemberLevelPageList(params: Record<string, any>) {
return request.get(`member/level`, { params })
return request.get(`member/level`, {params})
}
/**
@ -448,7 +449,7 @@ export function getMemberLevelInfo(level_id: number) {
* @returns
*/
export function addMemberLevel(params: Record<string, any>) {
return request.post('member/level', params, { showSuccessMessage: true })
return request.post('member/level', params, {showSuccessMessage: true})
}
/**
@ -456,7 +457,7 @@ export function addMemberLevel(params: Record<string, any>) {
* @param params
*/
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})
}
/**
@ -465,7 +466,7 @@ export function updateMemberLevel(params: Record<string, any>) {
* @returns
*/
export function deleteMemberLevel(level_id: number) {
return request.delete(`member/level/${level_id}`, { showSuccessMessage: true })
return request.delete(`member/level/${level_id}`, {showSuccessMessage: true})
}
/**
@ -480,8 +481,8 @@ export function getMemberLevelAll() {
/**
*
*/
export function getMemberBenefitsContent(params: Record<string, any>) {
return request.post(`member/benefits/content`, params);
export function getMemberBenefitsContent() {
return request.get(`member/benefits/content`);
}
/**
@ -504,12 +505,35 @@ export function getSignConfig() {
* @returns
*/
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>) {
return request.get(`member/sign`, { params });
return request.get(`member/sign`, {params});
}
/***************************************************** 地址管理 ****************************************************/
/**
*
*/
export function getMemberAddress(params: Record<string, any>) {
return request.get(`member/address`, {params});
}
/**
*
*/
export function addMemberAddress(params: Record<string, any>) {
return request.post(`member/address`, params);
}
/**
*
*/
export function editMemberAddress(params: Record<string, any>) {
return request.put(`member/address`, params);
}

View File

@ -3,21 +3,21 @@ import request from '@/utils/request'
/**
*
*/
export function getAuthinfo() {
export function getAuthInfo() {
return request.get('niucloud/authinfo', { showErrorMessage: false })
}
/**
*
*/
export function setAuthinfo(params: Record<string, any>) {
export function setAuthInfo(params: Record<string, any>) {
return request.post('niucloud/authinfo', params, {showSuccessMessage: true})
}
/**
*
*/
export function getAdminAuthinfo() {
export function getAdminAuthInfo() {
return request.get('niucloud/admin/authinfo')
}

View File

@ -75,3 +75,26 @@ export function getRefundTransfer(params: Record<string, any>) {
export function getAllPayType() {
return request.get(`pay/type/all`)
}
/**
*
*/
export function getPayList() {
return request.get(`pay/type/list`)
}
/**
*
*/
export function pay(params: Record<string, any>) {
return request.post(`pay`, params)
}
/**
*
* @param params
* @returns
*/
export function getFriendsPay(tradeType: string, tradeId: number, channel: string) {
return request.get(`pay/friendspay/info/${tradeType}/${tradeId}/${channel}`, {showErrorMessage: false})
}

View File

@ -103,4 +103,13 @@ export function initPoster(params: Record<string, any>) {
*/
export function getPreviewPoster(params: Record<string, any>) {
return request.get(`sys/poster/preview`, {params})
}
/**
*
* @param params
* @returns
*/
export function getPosterGenerate(params: Record<string, any>) {
return request.get(`sys/poster/generate`, {params, showErrorMessage: false})
}

View File

@ -65,5 +65,23 @@
"nativeDomain": "Native支付回调链接",
"nativeDomainTips": "需在微信商户号>产品中心>开发配置>支付配置 Native支付回调链接中添加该链接",
"wechatpayPublicCert": "微信支付公钥",
"wechatpayPublicCertId": "微信支付公钥ID"
"wechatpayPublicCertId": "微信支付公钥ID",
"updateFriendsPay":"找朋友帮忙付",
"friendsPaySwitch":"帮付说明",
"friendsPayTitle":"帮付说明标题",
"friendsPayTitlePlaceholder":"请输入帮付说明标题",
"desContent":"说明内容",
"friendsPayGoodsSwitch":"订单信息清单",
"friendsPayGoodsSwitchTips":"开启后,帮付人可以看到订单信息清单",
"friendsPayName":"支付方式名称",
"friendsPayNamePlaceholder":"请输入支付方式名称",
"desContentPlaceholder": "请输入说明内容",
"helpName":"帮付页面名称",
"helpNamePlaceholder":"请输入帮付页面名称",
"helpBtn":"帮付按钮名称",
"helpBtnPlaceholder":"请输入帮付按钮名称",
"remark":"发起帮付留言",
"remarkPlaceholder":"请输入留言备注",
"payWechatImage":"默认分享图片(公众号)",
"payWeappImage":"默认分享图片(小程序)"
}

View File

@ -45,17 +45,14 @@
<el-button class="w-[154px] !h-[48px] mt-[8px]" type="primary" @click="authCodeApproveFn">授权码认证</el-button>
<el-popover ref="getAuthCodeDialog" placement="bottom-start" :width="478" trigger="click" class="mt-[8px]">
<div class="px-[18px] py-[8px]">
<p class="leading-[32px] text-[14px]">您在官方应用市场购买任意一款应用即可获得授权码输入正确授权码认证通过后即可支持在线升级和其它相关服务
</p>
<p class="leading-[32px] text-[14px]">您在官方应用市场购买任意一款应用即可获得授权码输入正确授权码认证通过后即可支持在线升级和其它相关服务</p>
<div class="flex justify-end mt-[36px]">
<el-button class="w-[182px] !h-[48px]" plain @click="market">去应用市场逛逛</el-button>
<el-button class="w-[100px] !h-[48px]" plain @click="getAuthCodeDialog.hide()">关闭</el-button>
</div>
</div>
<template #reference>
<el-button
class="w-[154px] !h-[48px] mt-[8px] !text-[var(--el-color-primary)] hover:!text-[var(--el-color-primary)] !bg-transparent"
plain type="primary">如何获取授权码?</el-button>
<el-button class="w-[154px] !h-[48px] mt-[8px] !text-[var(--el-color-primary)] hover:!text-[var(--el-color-primary)] !bg-transparent" plain type="primary">如何获取授权码?</el-button>
</template>
</el-popover>
</div>
@ -92,7 +89,7 @@
<div class="text-page-title mb-[20px]">历史版本</div>
<el-timeline>
<el-timeline-item :timestamp="item['release_time'] + ' 版本:' + item['version_no']" v-for="(item,index) in frameworkVersionList" type="primary" :hollow="true" placement="top" :key="index">
<div class="mt-[10px] p-[20px] bg-overlay rounded-md timeline-log-wrap whitespace-pre" v-if="item['upgrade_log']">
<div class="mt-[10px] p-[20px] bg-overlay rounded-md timeline-log-wrap whitespace-pre-wrap" v-if="item['upgrade_log']">
<div v-html="item['upgrade_log']"></div>
</div>
</el-timeline-item>
@ -108,10 +105,11 @@
import { reactive, ref, computed } from 'vue'
import { t } from '@/lang'
import { getVersions } from '@/app/api/auth'
import { getAuthinfo, setAuthinfo, getFrameworkVersionList } from '@/app/api/module'
import { ElMessageBox, FormInstance, FormRules,ElMessage } from 'element-plus'
import { getAuthInfo, setAuthInfo, getFrameworkVersionList } from '@/app/api/module'
import { ElMessageBox, FormInstance, FormRules,ElMessage } from 'element-plus'
import Upgrade from '@/app/components/upgrade/index.vue'
import CloudBuild from '@/app/components/cloud-build/index.vue'
import { cloneDeep } from 'lodash-es'
const upgradeRef = ref<any>(null)
const cloudBuildRef = ref<any>(null)
@ -144,7 +142,7 @@ const newVersion:any = computed(() => {
})
const hideAuthCode = (res:any) => {
const authCode = JSON.parse(JSON.stringify(res))
const authCode = cloneDeep(res)
const data = authCode.slice(0, authCode.length / 2) + authCode.slice(authCode.length / 2, authCode.length - 1).replace(/./g, '*')
return data
}
@ -167,7 +165,7 @@ const authinfo = ref<AuthInfo>({
const loading = ref(true)
const saveLoading = ref(false)
const checkAppMange = () => {
getAuthinfo().then((res) => {
getAuthInfo().then((res) => {
loading.value = false
if (res.data.data && res.data.data.length != 0) {
authinfo.value = res.data.data
@ -204,7 +202,7 @@ const save = async (formEl: FormInstance | undefined) => {
if (valid) {
saveLoading.value = true
setAuthinfo(formData).then(() => {
setAuthInfo(formData).then(() => {
saveLoading.value = false
checkAppMange()
}).catch(() => {
@ -231,7 +229,7 @@ getVersionsInfo()
* 升级
*/
const handleUpgrade = () => {
if (!authinfo.value) {
if (!authinfo.value.auth_code) {
authCodeApproveFn()
return
}
@ -239,7 +237,7 @@ const handleUpgrade = () => {
}
const handleCloudBuild = () => {
if (!authinfo.value) {
if (!authinfo.value.auth_code) {
authCodeApproveFn()
return
}

View File

@ -97,7 +97,7 @@ import { reactive, ref } from 'vue'
import { setWeappVersion, getWeappPreview, getWeappVersionList, getWeappUploadLog, getWeappConfig } from '@/app/api/weapp'
import { t } from '@/lang'
import { useRoute, useRouter } from 'vue-router'
import { getAuthinfo } from '@/app/api/module'
import { getAuthInfo } from '@/app/api/module'
import { getAppType } from '@/utils/common'
import { ElMessageBox } from 'element-plus'
import { AnyObject } from '@/types/global'
@ -131,7 +131,7 @@ const form = ref({
const uploadSuccessShowDialog = ref(false)
const authCode = ref('')
getAuthinfo().then(res => {
getAuthInfo().then(res => {
if (res.data.data && res.data.data.auth_code) {
authCode.value = res.data.data.auth_code
getWeappPreviewImage()

View File

@ -377,7 +377,7 @@ import { ref, reactive, watch, h } from 'vue'
import { t } from '@/lang'
import { getAddonLocal, uninstallAddon, installAddon, preInstallCheck, cloudInstallAddon, getAddonInstalltask, getAddonCloudInstallLog, preUninstallCheck, cancelInstall } from '@/app/api/addon'
import { deleteAddonDevelop } from '@/app/api/tools'
import { downloadVersion, getAuthinfo, setAuthinfo } from '@/app/api/module'
import { downloadVersion, getAuthInfo, setAuthInfo } from '@/app/api/module'
import { ElMessage, ElMessageBox, ElNotification, FormInstance, FormRules } from 'element-plus'
import 'vue-web-terminal/lib/theme/dark.css'
import { Terminal, TerminalFlash } from 'vue-web-terminal'
@ -436,7 +436,7 @@ const downEvent = (param: Record<string, any>, isDown = false) => {
}
const authCode = ref('')
getAuthinfo().then(res => {
getAuthInfo().then(res => {
if (res.data.data && res.data.data.auth_code) {
authCode.value = res.data.data.auth_code
}
@ -865,7 +865,7 @@ const saveLoading = ref(false)
const authLoading = ref(true)
const checkAppMange = () => {
authLoading.value = true
getAuthinfo()
getAuthInfo()
.then((res) => {
authLoading.value = false
if (res.data.data && res.data.data.length != 0) {
@ -905,7 +905,7 @@ const save = async (formEl: FormInstance | undefined) => {
if (valid) {
saveLoading.value = true
setAuthinfo(formData)
setAuthInfo(formData)
.then(() => {
saveLoading.value = false
setTimeout(() => {

View File

@ -0,0 +1,191 @@
<template>
<el-dialog v-model="showDialog"
:destroy-on-close="true"
:title="formData.config.pay_type_name ? formData.config.pay_type_name : t('updateFriendsPay')" width="550px">
<el-form ref="formRef" v-loading="loading" :model="formData" :rules="formRules" class="page-form"
label-width="110px">
<el-form-item :label="t('friendsPaySwitch')">
<el-switch v-model="formData.config.pay_explain_switch" :active-value="1" :inactive-value="0"/>
</el-form-item>
<template v-if="formData.config.pay_explain_switch == 1">
<el-form-item :label="t('friendsPayTitle')" prop="config.pay_explain_title">
<el-input v-model.trim="formData.config.pay_explain_title" :placeholder="t('friendsPayTitlePlaceholder')"
class="input-width" clearable maxlength="10" show-word-limit/>
</el-form-item>
<el-form-item :label="t('desContent')" prop="config.pay_explain_content">
<el-input v-model.trim="formData.config.pay_explain_content" :placeholder="t('desContentPlaceholder')"
class="input-width" clearable maxlength="120" rows="4" show-word-limit type="textarea"/>
</el-form-item>
</template>
<el-form-item :label="t('friendsPayGoodsSwitch')">
<div>
<el-switch v-model="formData.config.pay_info_switch" :active-value="1" :inactive-value="0"/>
<div class="text-[12px] text-[#999] leading-[20px]">{{ t('friendsPayGoodsSwitchTips') }}</div>
</div>
</el-form-item>
<el-form-item :label="t('friendsPayName')" prop="config.pay_type_name">
<el-input v-model.trim="formData.config.pay_type_name" :placeholder="t('friendsPayNamePlaceholder')"
class="input-width" clearable maxlength="10" show-word-limit/>
</el-form-item>
<el-form-item :label="t('helpName')" prop="config.pay_page_name">
<el-input v-model.trim="formData.config.pay_page_name" :placeholder="t('helpNamePlaceholder')"
class="input-width" clearable maxlength="10" show-word-limit/>
</el-form-item>
<el-form-item :label="t('helpBtn')" prop="config.pay_button_name">
<el-input v-model.trim="formData.config.pay_button_name" :placeholder="t('helpBtnPlaceholder')"
class="input-width" clearable maxlength="10" show-word-limit/>
</el-form-item>
<el-form-item :label="t('remark')" prop="config.pay_leave_message">
<el-input v-model.trim="formData.config.pay_leave_message" :placeholder="t('remarkPlaceholder')"
class="input-width" clearable maxlength="20" rows="4" show-word-limit type="textarea"/>
</el-form-item>
<el-form-item :label="t('payWechatImage')" prop="config.pay_wechat_share_image">
<upload-image v-model="formData.config.pay_wechat_share_image" :limit="1"/>
</el-form-item>
<el-form-item :label="t('payWeappImage')" prop="config.pay_weapp_share_image">
<upload-image v-model="formData.config.pay_weapp_share_image" :limit="1"/>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="cancel()">{{ t('cancel') }}</el-button>
<el-button :loading="loading" type="primary" @click="confirm(formRef)">{{ t('confirm') }}</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import {computed, reactive, ref} from 'vue'
import {t} from '@/lang'
import type {FormInstance} from 'element-plus'
import Test from '@/utils/test'
import {cloneDeep} from 'lodash-es'
const showDialog = ref(false)
const loading = ref(true)
const initData = ref<any>(null)
/**
* 表单数据
*/
const initialFormData = {
type: 'friendspay',
app_id: '',
config: {
pay_explain_switch: 0,
pay_info_switch: 1,
pay_explain_title: '',
pay_explain_content: '',
pay_type_name: '',
pay_page_name: '',
pay_button_name: '',
pay_leave_message: '',
pay_wechat_share_image: '',
pay_weapp_share_image: ''
},
channel: '',
status: 0,
is_default: 0
}
const formData: Record<string, any> = reactive({...initialFormData})
const formRef = ref<FormInstance>()
//
const formRules = computed(() => {
return {
'config.pay_explain_title': [
{required: true, message: t('friendsPayTitlePlaceholder'), trigger: 'blur'},
{
validator: (rule: any, value: string, callback: any) => {
if (formData.config.pay_explain_switch == 1 && value === '') {
callback(new Error(t('friendsPayTitlePlaceholder')))
}
callback()
},
trigger: 'blur'
}
],
'config.pay_explain_content': [
{required: true, message: t('desContentPlaceholder'), trigger: 'blur'},
{
validator: (rule: any, value: string, callback: any) => {
if (formData.config.pay_explain_switch == 1 && value === '') {
callback(new Error(t('desContentPlaceholder')))
}
callback()
},
trigger: 'blur'
}
],
'config.pay_type_name': [
{required: true, message: t('friendsPayNamePlaceholder'), trigger: 'blur'}
],
'config.pay_page_name': [
{required: true, message: t('helpNamePlaceholder'), trigger: 'blur'}
],
'config.pay_button_name': [
{required: true, message: t('helpBtnPlaceholder'), trigger: 'blur'}
],
'config.pay_leave_message': [
{required: true, message: t('remarkPlaceholder'), trigger: 'blur'}
]
}
})
const emit = defineEmits(['complete'])
/**
* 确认
* @param formEl
*/
const confirm = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
await formEl.validate(async (valid) => {
if (valid) {
emit('complete', formData)
showDialog.value = false
}
})
}
const cancel = () => {
Object.assign(formData, initialFormData)
if (initData.value) {
Object.keys(formData).forEach((key: string) => {
if (initData.value[key] != undefined) formData[key] = initData.value[key]
})
formData.channel = initData.value.redio_key.split('_')[0]
formData.status = Number(formData.status)
}
emit('complete', formData)
showDialog.value = false
}
const setFormData = async (data: any = null) => {
initData.value = cloneDeep(data)
loading.value = true
Object.assign(formData, initialFormData)
if (data) {
Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key]
})
formData.channel = data.redio_key.split('_')[0]
formData.status = Number(formData.status)
}
loading.value = false
}
const enableVerify = () => {
let verify = true
if ((formData.config.pay_explain_switch == 1 && Test.empty(formData.config.pay_explain_title)) || (formData.config.pay_explain_switch == 1 && Test.empty(formData.config.pay_explain_content)) || Test.empty(formData.config.pay_type_name) || Test.empty(formData.config.pay_page_name) || Test.empty(formData.config.pay_button_name) || Test.empty(formData.config.pay_leave_message)) verify = false
return verify
}
defineExpose({
showDialog,
setFormData,
enableVerify
})
</script>
<style lang="scss" scoped></style>

View File

@ -1,74 +1,82 @@
<template>
<!--支付设置-->
<div class="main-container" v-loading="payLoading">
<!--支付设置-->
<div v-loading="payLoading" class="main-container">
<el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center" v-if="!payLoading">
<span class="text-page-title">{{ pageName }}</span>
<el-button type="primary" @click="isEdit = true" ref="setConfigBtn">{{ t('setConfig') }}</el-button>
</div>
</el-card>
<el-card class="box-card !border-none" shadow="never">
<div v-if="!payLoading" class="flex justify-between items-center">
<span class="text-page-title">{{ pageName }}</span>
<el-button ref="setConfigBtn" type="primary" @click="isEdit = true">{{ t('setConfig') }}</el-button>
</div>
</el-card>
<el-card class="box-card mt-[15px] !border-none" shadow="never" v-for="(payItems, payKey) in payConfigData" :key="payKey">
<h3 class="panel-title !text-sm">{{ payItems.name }}</h3>
<el-card v-for="(payItems, payKey) in payConfigData" :key="payKey" class="box-card mt-[15px] !border-none"
shadow="never">
<h3 class="panel-title !text-sm">{{ payItems.name }}</h3>
<div>
<div class="flex items-center justify-between p-[10px] table-item-border bg">
<span class="text-base w-[150px]">{{ t('payType') }}</span>
<span class="text-base w-[110px] text-center">{{ t('onState') }}</span>
<span class="text-base w-[80px] text-center" v-if="isEdit">{{ t('templateName') }}</span>
</div>
<div ref="fieldBoxRefs" :data-key="payKey">
<div class="flex items-center justify-between p-[10px] table-item-border" v-for="(childrenItem, childrenIndex) in payItems.pay_type" :key="childrenItem.redio_key" :id="payKey + '_' + childrenIndex">
<div class="flex w-[150px]">
<span v-if="isEdit" class="iconfont icontuodong mr-2 handle cursor-pointer"></span>
<div class="flex items-center select-none">
<div class="mr-[15px] w-[30px] h-[30px]">
<img class="w-[30px]" :src="img(childrenItem.icon)" />
</div>
<span class="text-base text-[#666]">{{ childrenItem.name }}</span>
</div>
</div>
<div class="flex items-center justify-center w-[110px] select-none">
<el-switch v-if="isEdit" v-model="childrenItem.status" :active-text="t('isEnable')" @change="enablePaymentMode(childrenItem)" />
<div v-else>
<el-tag v-if="childrenItem.status" class="ml-2" type="success">{{ t('open') }}</el-tag>
<el-tag v-else class="ml-2" type="info">{{ t('notOpen') }}</el-tag>
</div>
</div>
<div class="flex items-center justify-center w-[80px] select-none" v-if="isEdit">
<button class="text-base" @click="configPayFn(childrenItem)" v-if="childrenItem.setting_component">{{ t('clickConfigure') }}</button>
<button v-else>--</button>
</div>
</div>
</div>
</div>
</el-card>
<div class="fixed-footer-wrap" v-if="isEdit">
<div class="fixed-footer">
<el-button type="primary" :loading="loading" @click="cancelFn">{{ t('cancel') }}</el-button>
<el-button type="primary" :loading="loading" @click="saveFn(formRef)">{{ t('save') }}</el-button>
</div>
<div>
<div class="flex items-center justify-between p-[10px] table-item-border bg">
<span class="text-base w-[230px]">{{ t('payType') }}</span>
<span class="text-base w-[110px] text-center">{{ t('onState') }}</span>
<span v-if="isEdit" class="text-base w-[80px] text-center">{{ t('templateName') }}</span>
</div>
<template v-for="(item, index) in payTypeList">
<component :is="item.setting_component" :ref="(el) => setPayTypeRefs(el, item.key)" v-if="item.setting_component" @complete="setConfigInfo"/>
</template>
<div ref="fieldBoxRefs" :data-key="payKey">
<div v-for="(childrenItem, childrenIndex) in payItems.pay_type"
:id="payKey + '_' + childrenIndex" :key="childrenItem.redio_key"
class="flex items-center justify-between p-[10px] table-item-border">
<div class="flex w-[230px] flex-shrink-0">
<span v-if="isEdit" class="iconfont icontuodong mr-2 handle cursor-pointer"></span>
<div class="flex items-center select-none">
<div class="mr-[15px] w-[30px] h-[30px] flex-shrink-0">
<img :src="img(childrenItem.icon)" class="w-[30px]"/>
</div>
<span class="text-base text-[#666]">{{ childrenItem.name }}</span>
</div>
</div>
<div class="flex items-center justify-center w-[110px] select-none">
<el-switch v-if="isEdit" v-model="childrenItem.status" :active-text="t('isEnable')" :active-value="1"
:inactive-value="0" @change="enablePaymentMode(childrenItem)"/>
<div v-else>
<el-tag v-if="childrenItem.status" class="ml-2" type="success">{{ t('open') }}</el-tag>
<el-tag v-else class="ml-2" type="info">{{ t('notOpen') }}</el-tag>
</div>
</div>
<div v-if="isEdit" class="flex items-center justify-center w-[80px] select-none">
<button v-if="childrenItem.setting_component" class="text-base" @click="configPayFn(childrenItem)">
{{ t('clickConfigure') }}
</button>
<button v-else>--</button>
</div>
</div>
</div>
</div>
</el-card>
<div v-if="isEdit" class="fixed-footer-wrap">
<div class="fixed-footer">
<el-button :loading="loading" type="primary" @click="cancelFn">{{ t('cancel') }}</el-button>
<el-button :loading="loading" type="primary" @click="saveFn(formRef)">{{ t('save') }}</el-button>
</div>
</div>
<template v-for="(item, index) in payTypeList">
<component :is="item.setting_component" v-if="item.setting_component" :ref="(el) => setPayTypeRefs(el, item.key)"
@complete="setConfigInfo"/>
</template>
</div>
</template>
<script lang="ts" setup>
import { ref, watch, nextTick, defineAsyncComponent } from 'vue'
import { t } from '@/lang'
import { getPayConfigList, setPatConfig } from '@/app/api/sys'
import { getAllPayType } from '@/app/api/pay'
import { img } from '@/utils/common'
import { ElMessage } from 'element-plus'
import Sortable, { SortableEvent } from 'sortablejs'
import { useRoute } from 'vue-router'
import {defineAsyncComponent, nextTick, ref, watch} from 'vue'
import {t} from '@/lang'
import {getPayConfigList, setPatConfig} from '@/app/api/sys'
import {getAllPayType} from '@/app/api/pay'
import {img} from '@/utils/common'
import {ElMessage} from 'element-plus'
import Sortable, {SortableEvent} from 'sortablejs'
import {useRoute} from 'vue-router'
import {cloneDeep} from 'lodash-es'
const route = useRoute()
const pageName = route.meta.title
@ -77,15 +85,15 @@ const payTypeList = ref([])
const payTypeRefs = ref({})
const modules: any = import.meta.glob('@/**/*.vue')
getAllPayType().then(({ data }) => {
Object.keys(data).forEach((key: string) => {
data[key].setting_component && (data[key].setting_component = defineAsyncComponent(modules[data[key].setting_component]))
})
payTypeList.value = data
getAllPayType().then(({data}) => {
Object.keys(data).forEach((key: string) => {
data[key].setting_component && (data[key].setting_component = defineAsyncComponent(modules[data[key].setting_component]))
})
payTypeList.value = data
})
const setPayTypeRefs = (el: any, index: string) => {
payTypeRefs.value[index] = (el)
payTypeRefs.value[index] = (el)
}
const payLoading = ref(true)
@ -96,128 +104,124 @@ const setConfigBtn = ref()
//
const payConfigData = ref([])
const checkPayConfigList = () => {
getPayConfigList().then(res => {
const payData = res.data
for (const i in payData) {
const payType = payData[i].pay_type
const pay_type = []
let default_key = ''
getPayConfigList().then(res => {
const payData = res.data
for (const i in payData) {
const payType = payData[i].pay_type
const pay_type = []
let default_key = ''
payType.forEach((item, index) => {
item.redio_key = payData[i].key + '_' + item.key
item.defauit_key = ''
if (item.is_default == 1) {
default_key = item.redio_key
}
item.status = Boolean(item.status)
pay_type.push(item)
})
payData[payData[i].key].default_pay_type = default_key
payData[payData[i].key].pay_type = pay_type
payType.forEach((item, index) => {
item.redio_key = payData[i].key + '_' + item.key
item.defauit_key = ''
if (item.is_default == 1) {
default_key = item.redio_key
}
payConfigData.value = payData
payLoading.value = false
nextTick(() => {
fieldBoxRefs.value.forEach((item, index) => {
sortableFn(item, index)
})
})
}).catch(() => {
pay_type.push(item)
})
payData[payData[i].key].default_pay_type = default_key
payData[payData[i].key].pay_type = pay_type
}
payConfigData.value = payData
payLoading.value = false
nextTick(() => {
fieldBoxRefs.value.forEach((item, index) => {
sortableFn(item, index)
})
})
})
}
checkPayConfigList()
//
const setConfigInfo = (data:any) => {
payConfigData.value[data.channel].pay_type.forEach(element => {
if (element.key == data.type) {
element.config = data.config
}
})
const setConfigInfo = (data: any) => {
payConfigData.value[data.channel].pay_type.forEach(element => {
if (element.key == data.type) {
element.config = data.config
}
})
console.log(payConfigData.value)
}
//
const configPayFn = (data:any) => {
payTypeRefs.value[data.key].setFormData(data)
payTypeRefs.value[data.key].showDialog = true
const configPayFn = (data: any) => {
payTypeRefs.value[data.key].setFormData(data)
payTypeRefs.value[data.key].showDialog = true
}
//
const enablePaymentMode = async (data: object) => {
if (payTypeRefs.value[data.key] && typeof payTypeRefs.value[data.key].enableVerify == 'function') {
payTypeRefs.value[data.key].setFormData(data)
const enablePaymentMode = async (data: any) => {
if (payTypeRefs.value[data.key] && typeof payTypeRefs.value[data.key].enableVerify == 'function') {
payTypeRefs.value[data.key].setFormData(data)
const verify = payTypeRefs.value[data.key].enableVerify()
if (!verify) {
data.status = false
ElMessage(t('configurePaymentMethod'))
return false
}
const verify = payTypeRefs.value[data.key].enableVerify()
if (!verify) {
data.status = 0
ElMessage(t('configurePaymentMethod'))
return false
}
}
}
interface SortableEvt extends SortableEvent {
originalEvent?: DragEvent
originalEvent?: DragEvent
}
//
const fieldBoxRefs = ref<any>([])
watch(isEdit, (newValue, oldValue) => {
if (newValue) {
nextTick(() => {
fieldBoxRefs.value.forEach((item:any, index:any) => {
sortableFn(item, index)
})
})
}
if (newValue) {
nextTick(() => {
fieldBoxRefs.value.forEach((item: any, index: any) => {
sortableFn(item, index)
})
})
}
})
// item=>index
const sortableFn = (item, index) => {
const sortable = Sortable.create(item, {
group: {
put: false //
},
handle: '.handle',
animation: 200,
disabled: false,
onEnd: (evt) => {
const key = evt.target.getAttribute('data-key')
const data = payConfigData.value[key].pay_type
data.splice(evt.newIndex, 0, ...data.splice(evt.oldIndex, 1))
}
})
const sortable = Sortable.create(item, {
group: {
put: false //
},
handle: '.handle',
animation: 200,
disabled: false,
onEnd: (evt) => {
const key = evt.target.getAttribute('data-key')
const data = payConfigData.value[key].pay_type
data.splice(evt.newIndex, 0, ...data.splice(evt.oldIndex, 1))
}
})
}
//
const saveFn = () => {
payLoading.value = true
const data = JSON.parse(JSON.stringify(payConfigData.value))
Object.values(data).forEach((item, index) => {
item.pay_type.forEach((subItem:any, subIndex:any) => {
subItem.sort = subIndex
subItem.status = Number(subItem.status)
})
payLoading.value = true
const data = cloneDeep(payConfigData.value)
Object.values(data).forEach((item, index) => {
item.pay_type.forEach((subItem: any, subIndex: any) => {
subItem.sort = subIndex
})
})
setPatConfig({ config: data }).then(res => {
checkPayConfigList()
isEdit.value = false
payLoading.value = false
})
setPatConfig({config: data}).then(res => {
checkPayConfigList()
isEdit.value = false
payLoading.value = false
})
}
//
const cancelFn = () => {
location.reload()
location.reload()
}
</script>
<style lang="scss" scoped>
.table-item-border {
@apply border-b border-[var(--el-border-color)];
}
.table-item-border {
@apply border-b border-[var(--el-border-color)];
}
</style>

View File

@ -2,11 +2,10 @@ package com.niu.boot.process;
import cn.hutool.core.io.FileUtil;
import com.niu.boot.config.BootConfig;
import com.niu.boot.utils.BIOUtils;
import com.niu.boot.utils.BootLogUtils;
import com.niu.boot.utils.PipeNameUtils;
import com.niu.boot.utils.ThreadUtils;
import com.niu.boot.utils.*;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.IOFileFilter;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
@ -252,10 +251,18 @@ public class ProcessManager {
// 覆盖变更文件
File codeDir = new File(upgradeDir, "download/" + version);
if (addon.equals("niucloud-admin")) {
IOFileFilter envFile = FileTools.createExclusionFilter(new String[]{
"application-prod.yml",
".env.development",
".env.production",
".env.dev",
".env.product"
});
File[] childFile = codeDir.listFiles();
for (File file : childFile) {
if (file.isDirectory()) {
if (new File(sourceFile, file.getName()).exists()) FileUtils.copyDirectory(file, new File(sourceFile, file.getName()));
if (new File(sourceFile, file.getName()).exists()) FileUtils.copyDirectory(file, new File(sourceFile, file.getName()), envFile);
} else {
FileUtils.copyFile(file, new File(sourceFile, file.getName()));
}

View File

@ -1,6 +1,11 @@
package com.niu.boot.utils;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.io.filefilter.IOFileFilter;
import java.io.*;
import java.util.Arrays;
import java.util.List;
public class FileTools {
@ -117,4 +122,25 @@ public class FileTools {
}
}
/**
* 创建 FileUtils.copyDirectory 需要排除的目录和文件
*
* @param names
* @return
*/
public static IOFileFilter createExclusionFilter(String[] names) {
// 定义要排除的目录
List<String> excluded = Arrays.asList(names);
// 创建一个过滤器来排除特定子目录
IOFileFilter excludeSubDirsFilter = FileFilterUtils.trueFileFilter(); // 初始化为 false表示过滤所有文件或目录
// 循环创建过滤器
for (String name : excluded) {
IOFileFilter tempFilter = FileFilterUtils.nameFileFilter(name);
excludeSubDirsFilter = FileFilterUtils.and(excludeSubDirsFilter, FileFilterUtils.notFileFilter(tempFilter));
}
return excludeSubDirsFilter;
}
}

View File

@ -1,6 +1,7 @@
package com.niu.core.common.component.context.event;
import com.niu.core.common.annotation.EventCallback;
import com.niu.core.common.config.GlobalConfig;
import com.niu.core.event.example.CoreSourceEvent;
import com.niu.core.event.example.DemoEventDefiner;
import com.niu.core.event.example.ExampleEventDefiner;
@ -27,7 +28,7 @@ public class EventMediatorContext {
String basePackage = "com";
List<Class> eventCallbackClassList = scanAnnotationByComponentProvider(basePackage, EventCallback.class);
CallbackMediator.getInstance().init(eventCallbackClassList);
// log.info("eventCallbackClassList = " + eventCallbackClassList);
log.info("eventCallbackClassList = " + eventCallbackClassList);
}
/**
@ -79,7 +80,12 @@ public class EventMediatorContext {
provider.findCandidateComponents(basePackage).forEach(beanDefinition -> {
String beanClassName = beanDefinition.getBeanClassName();
try {
Class<?> beanClass = Class.forName(beanClassName);
Class<?> beanClass = null;
if (GlobalConfig.runActive.equals("dev")) {
beanClass = Class.forName(beanClassName);
} else {
beanClass = Thread.currentThread().getContextClassLoader().loadClass(beanClassName);
}
classList.add(beanClass);
} catch (Exception e) {
e.printStackTrace();

View File

@ -1,14 +1,11 @@
package com.niu.core.common.component.upgrade;
import cn.hutool.json.JSONObject;
import com.niu.core.common.component.upload.model.*;
public interface IUpgradeProvider {
public abstract class IUpgradeProvider {
/**
* 处理
* @param
*/
public void handle();
abstract public void handle();
}

View File

@ -49,7 +49,7 @@ public class GlobalConfig {
/**
* 版本
*/
public static String version = "0.0.2";
public static String version = "0.0.3";
/**
* 应用key
@ -62,6 +62,11 @@ public class GlobalConfig {
**/
public static String defaultAccessPath;
/**
* 是否是演示站点
*/
public static Boolean isDemo = false;
@Value("${mybatis-plus.global-config.db-config.table-prefix}")
public void setTablePrefix(String tablePrefix) {
GlobalConfig.tablePrefix = tablePrefix;
@ -115,4 +120,8 @@ public class GlobalConfig {
GlobalConfig.webDomain = webDomain;
}
@Value("${system.is-demo:false}")
public void setIsDemo(Boolean isDemo) {
GlobalConfig.isDemo = isDemo;
}
}

View File

@ -1,89 +1,126 @@
package com.niu.core.common.config.executable.initialize;
import com.niu.core.common.utils.language.AddonModuleBundleMessageSource;
import cn.hutool.core.util.ClassLoaderUtil;
import com.niu.core.common.annotation.EventCallback;
import com.niu.core.common.annotation.SpringModuleApplication;
import com.niu.core.common.component.context.MapperMap;
import com.niu.core.common.component.context.SpringContext;
import com.niu.core.common.component.context.event.EventMediatorContext;
import com.niu.core.common.component.handler.annotation.HandlerProvider;
import com.niu.core.common.component.handler.factory.HandlerProviderFactory;
import com.niu.core.common.component.initialize.annotation.Initializer;
import com.niu.core.common.component.initialize.manager.InitializeProviderManager;
import com.niu.core.common.component.job.annotation.JobProvider;
import com.niu.core.common.component.job.factory.JobProviderFactory;
import com.niu.core.common.component.loader.factory.LoaderProviderFactory;
import com.niu.core.common.component.pay.annotation.PayProvider;
import com.niu.core.common.component.pay.factory.PayProviderFactory;
import com.niu.core.common.component.sms.annotation.SmsProvider;
import com.niu.core.common.component.sms.factory.SmsProviderFactory;
import com.niu.core.common.component.upgrade.annotation.UpgradeProvider;
import com.niu.core.common.component.upgrade.factory.UpgradeProviderFactory;
import com.niu.core.common.component.upload.annotation.UploadProvider;
import com.niu.core.common.component.upload.factory.UploadProviderFactory;
import com.niu.core.common.config.GlobalConfig;
import com.niu.core.common.config.dataization.AddonModuleContext;
import com.niu.core.common.utils.language.AddonModuleBundleMessageSource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import java.lang.annotation.Annotation;
import javax.annotation.Nonnull;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
/**
* SpringBoot初始化完成后执行
*/
@Component
@Order(1)
@Slf4j
public class CoreApplicationRunner implements CommandLineRunner, ApplicationRunner {
@SuppressWarnings("unused")
class CoreApplicationRunner implements ApplicationListener<ApplicationReadyEvent> {
@Override
public void run(String... args) throws Exception {
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
String basePackage = "com";
int delaySeconds = 30; // 延迟是为了解决mybatis-plus-join的初始化bug
if (GlobalConfig.runActive.equalsIgnoreCase("dev")) {
executorService.schedule(() -> {
try {
log.info("开发环境下装载模块开始.");
// 统一扫描注解
Map<Class<? extends Annotation>, List<Class>> annotationClassListMap = ResourceBeanInitializer.scanning(basePackage);
// 初始化已安装的插件
AddonModuleContext.init(AddonResourceHelper.loadAddonEnvsMapByScan());
// 初始化国际化文件
AddonModuleBundleMessageSource.init();
// 业务资源初始化
ResourceBeanInitializer.initialize(annotationClassListMap);
log.info("开发环境下装载模块完成.");
// 钩子输出
System.out.println("Service started successfully.");
} catch (Exception e) {
e.printStackTrace();
}
}, delaySeconds, TimeUnit.SECONDS);
executorService.shutdown();
public void onApplicationEvent(@Nonnull ApplicationReadyEvent event) {
boolean isDev = GlobalConfig.runActive.equalsIgnoreCase("dev");
String env = isDev ? "开发" : "生产";
log.info("{}环境下装载模块开始.", env);
Map<String, String> addonEnvsMap;
if (isDev) {
// 初始化已安装的插件
addonEnvsMap = AddonResourceHelper.loadAddonEnvsMapByScan();
} else {
executorService.schedule(() -> {
log.info("生产环境下装载模块开始.");
try {
// 初始化已安装的插件
Map<String, String> addonEnvsMap = AddonResourceHelper.loadDynamicAddon();
log.info("addonEnvsMap = " + addonEnvsMap);
AddonModuleContext.init(addonEnvsMap);
// 统一扫描注解
Map<Class<? extends Annotation>, List<Class>> annotationClassListMap = ResourceBeanInitializer.scanning(basePackage);
// 初始化国际化
AddonModuleBundleMessageSource.init();
// 业务资源初始化
ResourceBeanInitializer.initialize(annotationClassListMap);
// 从管道中获取命令
PipeCommandHelper.doPipeCommand();
log.info("生产环境下装载模块完成.");
// 钩子输出
System.out.println("Service started successfully.");
}catch (Exception e) {
log.info("生产环境下装载模块异常");
e.printStackTrace();
}
}, delaySeconds, TimeUnit.SECONDS);
addonEnvsMap = AddonResourceHelper.loadDynamicAddon();
}
executorService.shutdown();
// 初始化已安装的插件
log.info("addonEnvsMap = {}", addonEnvsMap);
AddonModuleContext.init(addonEnvsMap);
// 初始化国际化文件
AddonModuleBundleMessageSource.init();
log.info("{}环境下装载模块完成.", env);
// 业务资源初始化
List<? extends Class<?>> list = scanner()
.findCandidateComponents("com.niu")
.stream()
.map(bd -> {
try {
return ClassLoaderUtil.loadClass(bd.getBeanClassName());
} catch (Exception e) {
throw new RuntimeException(e);
}
})
.toList();
initialize(list);
if (!isDev) {
// 从管道中获取命令
PipeCommandHelper.doPipeCommand();
}
// 钩子输出
System.out.println("Service started successfully.");
}
@Override
public void run(ApplicationArguments args) throws Exception {
log.debug("run() start");
/**
* 业务初始化
*/
private void initialize(List<? extends Class<?>> list) {
// load功能初始化
LoaderProviderFactory.init();
// 业务事件监听及事件回调组件初始化
EventMediatorContext.init();
// 业务调用
HandlerProviderFactory.init(HandlerProvider.class, list.stream().filter(o -> o.isAnnotationPresent(HandlerProvider.class)).map(o -> (Class) o).toList());
// 上传组件初始化
UploadProviderFactory.init(UploadProvider.class, list.stream().filter(o -> o.isAnnotationPresent(UploadProvider.class)).map(o -> (Class) o).toList());
// 短息组件初始化
SmsProviderFactory.init(SmsProvider.class, list.stream().filter(o -> o.isAnnotationPresent(SmsProvider.class)).map(o -> (Class) o).toList());
// 支付组件初始化
PayProviderFactory.init(PayProvider.class, list.stream().filter(o -> o.isAnnotationPresent(PayProvider.class)).map(o -> (Class) o).toList());
// 初始化组件初始化
InitializeProviderManager.exec(Initializer.class, list.stream().filter(o -> o.isAnnotationPresent(Initializer.class)).map(o -> (Class) o).toList(), SpringContext.get());
// 测试测试
// EventMediatorContext.test();
// 任务调度统一实现
JobProviderFactory.init(JobProvider.class, list.stream().filter(o -> o.isAnnotationPresent(JobProvider.class)).map(o -> (Class) o).toList());
// 升级事件初始化
UpgradeProviderFactory.init(UpgradeProvider.class, list.stream().filter(o -> o.isAnnotationPresent(UpgradeProvider.class)).map(o -> (Class) o).toList());
MapperMap.init(Mapper.class, list.stream().filter(o -> o.isAnnotationPresent(Mapper.class)).map(o -> (Class) o).toList());
}
log.debug("run() end");
private ClassPathBeanDefinitionScanner scanner() {
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner((BeanDefinitionRegistry) SpringContext.applicationContext, false);
Stream.of(SpringModuleApplication.class, Initializer.class, HandlerProvider.class,
UploadProvider.class, SmsProvider.class, PayProvider.class, JobProvider.class, EventCallback.class, UpgradeProvider.class, Mapper.class)
.forEach(o -> scanner.addIncludeFilter(new AnnotationTypeFilter(o, true, false)));
return scanner;
}
}

View File

@ -57,7 +57,8 @@ public class SaTokenAdminInterceptor extends SaInterceptor {
/** 校验用户和当前的路由权限 */
authService.checkRole(request);
/*** 检测是否是演示环境 */
authService.checkIsDemo(request);
// Integer userId = (Integer)StpUtil.getLoginId();
//adminapi/xxxx

View File

@ -1,6 +1,7 @@
package com.niu.core.common.loader.notice;
import cn.hutool.json.JSONObject;
import cn.hutool.core.util.ClassLoaderUtil;
import java.lang.reflect.Constructor;
import java.util.Map;
@ -17,7 +18,7 @@ public abstract class BaseNotice {
public static BaseNotice forName(String driver) {
BaseNotice base = null;
try {
Class<?> clazz = Class.forName(driver);
Class<?> clazz = ClassLoaderUtil.loadClass(driver);
base = (BaseNotice) clazz.newInstance();
} catch (Exception e) {
e.printStackTrace();

View File

@ -3,6 +3,7 @@ package com.niu.core.common.loader.pay;
import cn.hutool.json.JSONObject;
import com.niu.core.common.loader.pay.param.RefundParam;
import com.niu.core.common.loader.pay.param.TransferParam;
import cn.hutool.core.util.ClassLoaderUtil;
import com.niu.core.entity.pay.Pay;
import com.niu.core.service.core.pay.vo.PayTypeVo;
import com.niu.core.common.loader.pay.param.PayAsyncNotifyParam;
@ -25,7 +26,7 @@ public abstract class BasePay {
public static BasePay forName(String driver) {
BasePay base = null;
try {
Class<?> clazz = Class.forName(driver);
Class<?> clazz = ClassLoaderUtil.loadClass(driver);
base = (BasePay) clazz.newInstance();
} catch (Exception e) {
e.printStackTrace();

View File

@ -2,6 +2,7 @@ package com.niu.core.common.loader.sms;
import cn.hutool.json.JSONObject;
import com.niu.core.common.loader.notice.NoticeDataVo;
import cn.hutool.core.util.ClassLoaderUtil;
import com.niu.core.service.admin.sys.param.AttachmentUploadParam;
import com.niu.core.service.core.notice.vo.NoticeInfoVo;
@ -26,7 +27,7 @@ public abstract class BaseSms {
public static BaseSms forName(String driver, JSONObject config) {
BaseSms base = null;
try {
Class<?> clazz = Class.forName(driver);
Class<?> clazz = ClassLoaderUtil.loadClass(driver);
Constructor<?> constructor = clazz.getConstructor(JSONObject.class);
base = (BaseSms) constructor.newInstance(config);
} catch (Exception e) {

View File

@ -1,11 +1,17 @@
package com.niu.core.common.utils.Export;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.SimpleColumnWidthStyleStrategy;
import com.niu.core.common.component.context.SpringContext;
import com.niu.core.common.component.context.task.ThreadPoolManager;
import com.niu.core.entity.sys.SysExport;
import com.niu.core.mapper.sys.SysExportMapper;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
@ -17,32 +23,53 @@ import java.util.List;
public class BusinessExcelUtil {
/**
* @Description: 动态导出excel
*
* @param exportDynamic 参数实体类
* @Description: 动态导出excel
* @return: void
*/
public static void exportBusinessExcel(ExportDynamic exportDynamic) {
public static void exportBusinessExcel(Integer exportId, ExportDynamic exportDynamic) {
// 文件名称不能为空
if (!ObjectUtils.isEmpty(exportDynamic.getFileName())) {
List<List<String>> head = new ArrayList<>();
// 设置文件名称和文件路径
String filePath = exportDynamic.getFilePath();
String fileName = filePath + File.separator + exportDynamic.getFileName();
String fileName = filePath + exportDynamic.getFileName();
// 设置动态表头
if (!CollectionUtils.isEmpty(exportDynamic.getHeads())) {
// 处理查询条件以及表格的标题
head = formatHead(head(exportDynamic.getHeads()), exportDynamic.getTableTitle());
head.addAll(formatHead(head(exportDynamic.getHeads()), exportDynamic.getTableTitle()));
}
// 导出excel
EasyExcel.write(fileName)
.head(head)
ThreadPoolManager.runTask(() -> {
SysExportMapper mapper = SpringContext.bean(SysExportMapper.class);
SysExport export = mapper.selectById(exportId);
if (export == null) {
return;
}
export.setExportStatus(2);
export.setFilePath(exportDynamic.getRelativePath() + exportDynamic.getFileName());
try {
EasyExcel.write(fileName)
.head(head)
// .relativeHeadRowIndex(1) 表格离上方多少行
.registerWriteHandler(new SimpleColumnWidthStyleStrategy(ExcelConstant.DEFAULT_COLUMN_WIDTH))
.registerWriteHandler(setterTableHead())
.registerWriteHandler(new CustomCellWriteHandler())
.sheet(ExcelConstant.DEFAULT_SHEET_NAME)
.doWrite(exportDynamic.getDatas());
.registerWriteHandler(new SimpleColumnWidthStyleStrategy(ExcelConstant.DEFAULT_COLUMN_WIDTH))
.registerWriteHandler(setterTableHead())
.registerWriteHandler(new CustomCellWriteHandler())
.sheet(ExcelConstant.DEFAULT_SHEET_NAME)
.doWrite(exportDynamic.getDatas());
} catch (Exception e) {
export.setExportStatus(-1);
export.setFailReason(e.getMessage());
}
if (export.getExportStatus() == 2) {
export.setFileSize(FileUtil.size(new File(fileName)) / 1024 + "");
}
mapper.updateById(export);
});
}
}
@ -72,7 +99,6 @@ public class BusinessExcelUtil {
/**
* @Description: 处理表格标题和查询条件
*
* @Date: 2024/4/28 16:29
* @Param heads: 表头数据
* @Param title: 表头内容
@ -80,6 +106,10 @@ public class BusinessExcelUtil {
* @return: java.util.List<java.util.List < java.lang.String>>
*/
private static List<List<String>> formatHead(List<List<String>> heads, String title) {
if (ObjectUtil.hasEmpty(heads, title)) {
return heads;
}
List<List<String>> datas = new ArrayList<>();
if (!CollectionUtils.isEmpty(heads)) {
for (int i = 0; i < heads.size(); i++) {

View File

@ -15,10 +15,8 @@ import java.util.List;
@Slf4j
public class CustomCellWriteHandler extends HorizontalCellStyleStrategy implements CellWriteHandler, RowWriteHandler {
private static Integer INDEX;
@Override
public void afterRowDispose(RowWriteHandlerContext context) {
WriteSheetHolder writeSheetHolder = context.getWriteSheetHolder();
@ -59,7 +57,7 @@ public class CustomCellWriteHandler extends HorizontalCellStyleStrategy implemen
headCellStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
} else {
font.setFontHeightInPoints(ExcelConstant.MIN_HEIGHT_SIZE); // 设置字体大小
if (headCell.getRowIndex()>0 && headCell.getRowIndex() <= INDEX) {
if (headCell.getRowIndex() > 0 && headCell.getRowIndex() <= INDEX) {
// 只有查询条件列一居左 列二居右
if (headCell.getColumnIndex() == 0) {
headCellStyle.setAlignment(HorizontalAlignment.LEFT); // 居左

View File

@ -5,7 +5,6 @@ import lombok.experimental.Accessors;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 导出Excel的数据实体类
@ -13,6 +12,14 @@ import java.util.Map;
@Data
@Accessors(chain = true)
public class ExportDynamic {
/**
* 表头数据
*/
List<ExportHeads> heads = new ArrayList<>();
/**
* 表数据
*/
List<List<Object>> datas = new ArrayList<>();
/**
* 文件名称
*/
@ -21,16 +28,9 @@ public class ExportDynamic {
* 文件全路径
*/
private String filePath;
private String relativePath;
/**
* 表格标题
*/
private String tableTitle;
/**
* 表头数据
*/
List<ExportHeads> heads =new ArrayList<>();
/**
* 表数据
*/
List<List<Object>> datas =new ArrayList<>();
}

View File

@ -216,19 +216,19 @@ public class FileTools {
/**
* 创建 FileUtils.copyDirectory 需要排除的目录
*
* @param dirs
* @param names
* @return
*/
public static IOFileFilter createExclusionFilter(String[] dirs) {
public static IOFileFilter createExclusionFilter(String[] names) {
// 定义要排除的目录
List<String> excludedDirs = Arrays.asList(dirs);
List<String> excluded = Arrays.asList(names);
// 创建一个过滤器来排除特定子目录
IOFileFilter excludeSubDirsFilter = FileFilterUtils.trueFileFilter(); // 初始化为 false表示过滤所有文件或目录
// 循环创建过滤器
for (String dirName : excludedDirs) {
IOFileFilter tempFilter = FileFilterUtils.nameFileFilter(dirName);
for (String name : excluded) {
IOFileFilter tempFilter = FileFilterUtils.nameFileFilter(name);
excludeSubDirsFilter = FileFilterUtils.and(excludeSubDirsFilter, FileFilterUtils.notFileFilter(tempFilter));
}

View File

@ -1,5 +1,6 @@
package com.niu.core.common.utils.system;
import com.niu.core.common.config.GlobalConfig;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.AnnotationTypeFilter;
@ -37,7 +38,12 @@ public final class ClassPathScanAnnotationManager {
componentProvider.findCandidateComponents(basePackage).forEach(beanDefinition -> {
String beanClassName = beanDefinition.getBeanClassName();
try {
Class<?> beanClass = Class.forName(beanClassName);
Class<?> beanClass = null;
if (GlobalConfig.runActive.equals("dev")) {
beanClass = Class.forName(beanClassName);
} else {
beanClass = Thread.currentThread().getContextClassLoader().loadClass(beanClassName);
}
for (Class scanAnnotationClass : scanAnnotationClassList) {
Annotation annotation = beanClass.getAnnotation(scanAnnotationClass);
if (annotation != null) {

View File

@ -16,6 +16,7 @@ import com.niu.core.common.domain.PageParam;
import com.niu.core.service.core.addon.ICoreAddonService;
import com.niu.core.service.core.addon.vo.InstallAddonListVo;
import com.niu.core.service.core.diy.param.StartUpPageConfigParam;
import lombok.Data;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@ -137,14 +138,19 @@ public class DiyController {
return Result.success(diyPageService.getLink());
}
@Data
public static class Id {
private Integer id;
}
/**
* 设为使用
*
* @return Result<Object>
*/
@PutMapping("/use/{id}")
public Result<Object> setUse(@PathVariable Integer id) {
diyPageService.setUse(id);
@PutMapping("/use")
public Result<Object> setUse(@RequestBody Id id) {
diyPageService.setUse(id.getId());
return Result.success();
}

View File

@ -1,24 +1,25 @@
package com.niu.core.controller.adminapi.member;
import cn.dev33.satoken.annotation.SaCheckLogin;
import com.niu.core.common.domain.PageParam;
import com.niu.core.common.domain.Result;
import com.niu.core.common.domain.PageResult;
import com.niu.core.service.admin.member.IMemberAddressService;
import com.niu.core.service.admin.member.param.MemberAddressParam;
import com.niu.core.service.admin.member.param.MemberAddressSearchParam;
import com.niu.core.service.admin.member.vo.MemberAddressInfoVo;
import com.niu.core.service.admin.member.vo.MemberAddressListVo;
import com.niu.core.common.domain.PageParam;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
/**
* 会员收货地址控制器
*/
@RestController
@RequestMapping("adminapi/member_address")
@RequestMapping("adminapi/member/address")
@SaCheckLogin
public class MemberAddressController {
@ -27,34 +28,34 @@ public class MemberAddressController {
/**
* 会员收货地址列表
* @param pageParam 分页
*
* @param searchParam 搜索条件
* @return Result<PageResult<MemberAddressListVo>>
* @return Result<PageResult < MemberAddressListVo>>
*/
@GetMapping("/list")
public Result<PageResult<MemberAddressListVo>> list(@Validated PageParam pageParam,
@Validated MemberAddressSearchParam searchParam) {
PageResult<MemberAddressListVo> list = memberAddressService.list(pageParam, searchParam);
return Result.success(list);
@GetMapping("")
public Result<List<MemberAddressListVo>> list(MemberAddressSearchParam searchParam) {
return Result.success(memberAddressService.list(searchParam));
}
/**
* 会员收货地址详情
*
* @param id 主键ID
* @return Result<MemberAddressInfoVo>
*/
@GetMapping("/info")
public Result<MemberAddressInfoVo> info(@Validated @RequestParam("id") Integer id) {
@GetMapping("/{id}")
public Result<MemberAddressInfoVo> info(@PathVariable Integer id) {
MemberAddressInfoVo info = memberAddressService.info(id);
return Result.success(info);
}
/**
* 会员收货地址添加
*
* @param addParam 添加参数
* @return Result<Object>
*/
@PostMapping("/add")
@PostMapping("")
public Result<Object> add(@Validated @RequestBody MemberAddressParam addParam) {
memberAddressService.add(addParam);
return Result.success();
@ -62,22 +63,24 @@ public class MemberAddressController {
/**
* 会员收货地址编辑
*
* @param editParam 编辑参数
* @return Result<Object>
*/
@PostMapping("/edit")
public Result<Object> edit(Integer id, @Validated @RequestBody MemberAddressParam editParam) {
@PutMapping("/{id}")
public Result<Object> edit(@PathVariable Integer id, @Validated @RequestBody MemberAddressParam editParam) {
memberAddressService.edit(id, editParam);
return Result.success();
}
/**
* 会员收货地址删除
*
* @param id 参数
* @return Result<Object>
*/
@PostMapping("/del")
public Result<Object> del(@Validated @RequestBody Integer id) {
@DeleteMapping("/{id}")
public Result<Object> del(@PathVariable Integer id) {
memberAddressService.del(id);
return Result.success();
}

View File

@ -1,16 +1,18 @@
package com.niu.core.controller.adminapi.pay;
import cn.dev33.satoken.annotation.SaCheckLogin;
import com.niu.core.common.domain.Result;
import com.niu.core.common.domain.PageParam;
import com.niu.core.common.domain.PageResult;
import com.niu.core.common.domain.Result;
import com.niu.core.service.admin.pay.IPayService;
import com.niu.core.service.admin.pay.param.GetFriendspayInfoByTradeParam;
import com.niu.core.service.admin.pay.param.PayParam;
import com.niu.core.service.admin.pay.param.PaySearchParam;
import com.niu.core.service.admin.pay.vo.PayInfoVo;
import com.niu.core.service.admin.pay.vo.PayListVo;
import com.niu.core.common.domain.PageParam;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
@ -27,19 +29,21 @@ public class PayController {
/**
* 支付记录列表
* @param pageParam 分页
*
* @param pageParam 分页
* @param searchParam 搜索条件
* @return Result<PageResult<PayListVo>>
* @return Result<PageResult < PayListVo>>
*/
@GetMapping("/list")
public Result<PageResult<PayListVo>> list(@Validated PageParam pageParam,
@Validated PaySearchParam searchParam) {
@Validated PaySearchParam searchParam) {
PageResult<PayListVo> list = payService.list(pageParam, searchParam);
return Result.success(list);
}
/**
* 支付记录详情
*
* @param id 主键ID
* @return Result<PayInfoVo>
*/
@ -51,6 +55,7 @@ public class PayController {
/**
* 支付记录添加
*
* @param addParam 添加参数
* @return Result<Object>
*/
@ -62,6 +67,7 @@ public class PayController {
/**
* 支付记录编辑
*
* @param editParam 编辑参数
* @return Result<Object>
*/
@ -73,6 +79,7 @@ public class PayController {
/**
* 支付记录删除
*
* @param id 参数
* @return Result<Object>
*/
@ -82,4 +89,23 @@ public class PayController {
return Result.success();
}
@GetMapping("/friendspay/info/{trade_type}/{trade_id}/{channel}")
public Result<?> getFriendspayInfoByTrade(@PathVariable("trade_type") String tradeType, @PathVariable("trade_id") Integer tradeId, @PathVariable("channel") String channel) {
GetFriendspayInfoByTradeParam param = new GetFriendspayInfoByTradeParam();
param.setTradeType(tradeType);
param.setTradeId(tradeId);
param.setChannel(channel);
return Result.success(payService.getFriendspayInfoByTrade(param));
}
@GetMapping("/type/list")
public Result<?> payTypeList() {
return Result.success(payService.getPayTypeList());
}
@PostMapping
public Result<?> pay(@RequestBody com.niu.core.common.loader.pay.param.PayParam param) {
return Result.success(payService.pay(param));
}
}

View File

@ -1,16 +1,16 @@
package com.niu.core.controller.adminapi.sys;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.hutool.json.JSONObject;
import com.niu.core.common.domain.Result;
import com.niu.core.common.domain.PageParam;
import com.niu.core.common.domain.PageResult;
import com.niu.core.common.domain.Result;
import com.niu.core.enums.sys.ExportEnum;
import com.niu.core.service.admin.sys.ISysExportService;
import com.niu.core.service.admin.sys.param.SysExportSearchParam;
import com.niu.core.service.admin.sys.vo.SysExportListVo;
import com.niu.core.common.domain.PageParam;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Map;
@ -28,62 +28,54 @@ public class SysExportController {
/**
* 导出报列表
* @param pageParam 分页
*
* @param pageParam 分页
* @param searchParam 搜索条件
* @return Result<PageResult<SysExportListVo>>
* @return Result<PageResult < SysExportListVo>>
*/
@GetMapping("/export")
public Result<PageResult<SysExportListVo>> list(@Validated PageParam pageParam,
@Validated SysExportSearchParam searchParam) {
@Validated SysExportSearchParam searchParam) {
PageResult<SysExportListVo> list = sysExportService.list(pageParam, searchParam);
return Result.success(list);
}
/**
* 获取导出状态列表
*
* @return
*/
@GetMapping("/export/status")
public Result<Object> getExportStatus(){
public Result<Object> getExportStatus() {
return Result.success(ExportEnum.getStatus());
}
/**
* 报表导出类型
*
* @return
*/
@GetMapping("/export/type")
public Result<Map<String, String>> getExportDataType(){
public Result<Map<String, String>> getExportDataType() {
return Result.success(sysExportService.getExportDataType());
}
/**
* 报表导出数据检查
*
* @param type
* @return
*/
@GetMapping("/export/check/{type}")
public Result<Object> check(@Validated @PathVariable("type") String type, @RequestParam Map<String, Object> objectMap){
public Result<Object> check(@Validated @PathVariable("type") String type, @RequestParam Map<String, Object> objectMap) {
return Result.success(sysExportService.checkExportData(type, objectMap));
}
/**
* 报表导出
*
* @param type
* @return
*/
@GetMapping("/export/{type}")
public Result<Object> export(@Validated @PathVariable("type") String type, @RequestParam Map<String, Object> jsonObject){
public Result<Object> export(@Validated @PathVariable("type") String type, @RequestParam Map<String, Object> jsonObject) {
sysExportService.exportData(type, jsonObject);
return Result.success();
}
/**
* 导出报删除
*
* @param id 参数
* @return Result<Object>
*/

View File

@ -1,8 +1,10 @@
package com.niu.core.controller.adminapi.sys;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.hutool.core.util.ObjectUtil;
import com.niu.core.common.domain.Result;
import com.niu.core.common.domain.PageResult;
import com.niu.core.common.utils.RequestUtils;
import com.niu.core.enums.poster.PosterTypeEnum;
import com.niu.core.service.admin.sys.ISysPosterService;
import com.niu.core.service.admin.sys.param.*;
@ -10,6 +12,8 @@ import com.niu.core.service.admin.sys.vo.SysPosterInfoVo;
import com.niu.core.service.admin.sys.vo.SysPosterListVo;
import com.niu.core.common.domain.PageParam;
import com.niu.core.service.admin.sys.param.SysPosterTemplateSearchParam;
import com.niu.core.service.core.poster.ICorePosterService;
import com.niu.core.service.core.poster.param.GetPosterParam;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@ -24,6 +28,9 @@ import java.util.List;
@SaCheckLogin
public class SysPosterController {
@Resource
private ICorePosterService corePosterService;
@Resource
ISysPosterService sysPosterService;
@ -146,4 +153,16 @@ public class SysPosterController {
sysPosterService.modifyDefault(param.getId());
return Result.success();
}
/**
* 生成海报
* @param param
* @return
*/
@GetMapping("/generate")
public Result<?> poster(GetPosterParam param) {
param.setSiteId(RequestUtils.siteId());
param.setChannel(ObjectUtil.defaultIfNull(param.getChannel(), "h5"));
return Result.success("", corePosterService.get(param));
}
}

View File

@ -3,10 +3,10 @@ package com.niu.core.controller.api.pay;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.util.ObjectUtil;
import com.niu.core.common.domain.Result;
import com.niu.core.common.utils.RequestUtils;
import com.niu.core.service.api.pay.IPayService;
import com.niu.core.common.loader.pay.param.PayAsyncNotifyParam;
import com.niu.core.common.loader.pay.param.PayParam;
import com.niu.core.common.utils.RequestUtils;
import com.niu.core.service.api.pay.IPayService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@ -62,8 +62,12 @@ public class PayController {
* @return
*/
@GetMapping("/pay/info/{trade_type}/{trade_id}")
public Result<?> info(@PathVariable("trade_type") String tradeType, @PathVariable("trade_id") Integer tradeId) {
return Result.success(payService.getInfoByTrade(tradeType, tradeId));
public Result<?> info(@PathVariable("trade_type") String tradeType, @PathVariable("trade_id") Integer tradeId, String scene) {
return Result.success(payService.getInfoByTrade(tradeType, tradeId, scene));
}
@GetMapping("/pay/friendspay/info/{trade_type}/{trade_id}")
public Result<?> friendspayInfo(@PathVariable("trade_type") String tradeType, @PathVariable("trade_id") Integer tradeId) {
return Result.success(payService.friendspayInfo(tradeType, tradeId));
}
}

View File

@ -0,0 +1,4 @@
package com.niu.core.enums.sys;
public enum ExportDataType {
}

View File

@ -1,9 +1,10 @@
package com.niu.core.enums.sys;
import com.niu.core.common.utils.language.LanguageUtils;
import cn.hutool.core.util.ObjectUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@ -14,10 +15,9 @@ import java.util.Map;
@AllArgsConstructor
public enum ExportEnum {
EXPORTING(LanguageUtils.get("dict_export.status_exporting"), 1),
SUCCESS(LanguageUtils.get("dict_export.status_success"), 1),
FAIL(LanguageUtils.get("dict_export.status_fail"), 1)
;
EXPORTING("导出中", 1),
SUCCESS("导出成功", 2),
FAIL("导出失败", -1);
private final String name;
private final Integer code;
@ -25,14 +25,20 @@ public enum ExportEnum {
/**
* 获取状态
*
* @return
*/
public static Map<Integer, String> getStatus() {
Map<Integer, String> map = new HashMap<>();
for(ExportEnum item : ExportEnum.values()){
for (ExportEnum item : ExportEnum.values()) {
map.put(item.getCode(), item.getName());
}
return map;
}
public static String getNameByCode(Integer code) {
return Arrays.stream(ExportEnum.values())
.filter(s -> ObjectUtil.equal(s.getCode(), code))
.findFirst()
.map(ExportEnum::getName)
.orElse("");
}
}

View File

@ -0,0 +1,30 @@
package com.niu.core.event.pay;
import cn.hutool.json.JSONObject;
import com.niu.core.common.component.context.event.Event;
import com.niu.core.common.component.context.event.EventResult;
import com.niu.core.common.component.context.listener.CallbackListener;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
public abstract class PayTradeInfoDefiner extends CallbackListener<PayTradeInfoDefiner.PayTradeInfoEvent> {
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class PayTradeInfoEvent extends Event {
private String tradeType;
private Integer tradeId;
}
@EqualsAndHashCode(callSuper = true)
@Data
public static class PayTradeInfoEventResult extends EventResult {
private JSONObject jsonObject;
}
}

View File

@ -7,6 +7,7 @@ import com.niu.core.common.component.context.event.EventResult;
import com.niu.core.common.component.context.listener.CallbackListener;
import com.niu.core.common.domain.PageParam;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
@ -14,42 +15,54 @@ import lombok.experimental.Accessors;
*/
public abstract class ExportDataEventDefiner extends CallbackListener<ExportDataEventDefiner.ExportDataEvent> {
// 事件响应
public abstract ExportDataEventResult handleCallback(ExportDataEvent exportDataEvent);
/**
* 事件主题 数据导出类型
*
* <p>
* 定义传入参数
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
public static class ExportDataEvent extends Event {
/** 站点id */
/**
* 站点id
*/
private Integer siteId;
/** 数据导出类型 */
/**
* 数据导出类型
*/
private String type;
/** 查询条件 */
/**
* 查询条件
*/
private JSONObject where;
/** 分页参数 */
/**
* 分页参数
*/
private PageParam pageParam;
}
/**
* 事件结果
*
* <p>
* 返回数据类型
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
public static class ExportDataEventResult extends EventResult {
/** 返回的结果集 */
/**
* 返回的结果集
*/
private JSONArray resultData;
}
// 事件响应
public abstract ExportDataEventResult handleCallback(ExportDataEvent exportDataEvent);
}

View File

@ -0,0 +1,23 @@
package com.niu.core.event.sys;
import cn.hutool.json.JSONObject;
import com.niu.core.common.component.context.event.Event;
import com.niu.core.common.component.context.event.EventResult;
import com.niu.core.common.component.context.listener.CallbackListener;
import lombok.Data;
import lombok.EqualsAndHashCode;
public abstract class ExportDataTypeEventDefiner extends CallbackListener<ExportDataTypeEventDefiner.ExportDataTypeEvent> {
@EqualsAndHashCode(callSuper = true)
@Data
public static class ExportDataTypeEvent extends Event {
}
@EqualsAndHashCode(callSuper = true)
@Data
public static class ExportDataTypeResult extends EventResult {
private JSONObject result;
}
}

View File

@ -0,0 +1,127 @@
package com.niu.core.listener.poster;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.niu.core.common.annotation.EventCallback;
import com.niu.core.common.utils.QrcodeUtils;
import com.niu.core.common.utils.RequestUtils;
import com.niu.core.entity.member.Member;
import com.niu.core.entity.pay.Pay;
import com.niu.core.enums.pay.PayStatusEnum;
import com.niu.core.event.sys.GetPosterDataEventDefiner;
import com.niu.core.mapper.member.MemberMapper;
import com.niu.core.mapper.pay.PayMapper;
import com.niu.core.service.core.sys.ICoreSysConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@EventCallback("shop")
@Component
public class GetPosterDataListener extends GetPosterDataEventDefiner {
private PayMapper payMapper;
private MemberMapper memberMapper;
private ICoreSysConfigService coreSysConfigService;
public GetPosterDataEventDefiner.GetPosterDataResult handleCallback(GetPosterDataEventDefiner.GetPosterDataEvent event) {
final Map<String, Object> param = event.getParam();
GetPosterDataEventDefiner.GetPosterDataResult result = new GetPosterDataEventDefiner.GetPosterDataResult();
if (event.getType().equals("friendspay")) {
Object tradeId = param.get("id");
Object tradeType = param.get("type");
String wapUrl = coreSysConfigService.getSceneDomain(event.getSiteId()).getWapUrl();
if (ObjectUtil.equal(param.get("mode"), "preview")) {
Map<String, Object> data = new HashMap<>(8, 1);
data.put("nickname", "会员昵称的帮付");
data.put("headimg", "static/resource/images/default_headimg.png");
data.put("friendspay_message", "帮我付一下这笔订单吧,谢谢啦~");
data.put("friendspay_money", "¥369.00");
Map<String, Object> url = Map.of("url", wapUrl,
"page", "app/pages/friendspay/money",
"data", Map.of("id", tradeId, "type", param.get("type")));
data.put("url", url);
result.setData(data);
return result;
}
QueryWrapper<Pay> wrapper = new QueryWrapper<>();
wrapper.eq("site_id", event.getSiteId())
.eq("trade_id", tradeId)
.eq("trade_type", tradeType)
.ne("status", PayStatusEnum.STATUS_CANCLE.getCode());
List<Pay> pays = payMapper.selectList(wrapper);
if (ObjectUtil.isEmpty(pays)) {
return result;
}
Map<String, Object> data = new HashMap<>(8, 1);
data.put("friendspay_message", "帮我付一下这笔订单吧,谢谢啦~");
data.put("friendspay_money", "¥369.00");
// 生成二维码
String url = QrcodeUtils.qrcodeToFile(
event.getSiteId(),
event.getChannel(),
coreSysConfigService.getSceneDomain(event.getSiteId()).getWapUrl(),
"addon/shop/pages/goods/detail",
Map.of("id", tradeId, "type", param.get("type")),
""
);
data.put("url", url);
String memberId = event.getParam().getOrDefault("member_id", 0).toString();
if (ObjectUtil.isNotEmpty(memberId)) {
Member member = memberMapper.selectById(memberId);
if (ObjectUtil.isNotEmpty(member)) {
if (ObjectUtil.isEmpty(member.getHeadimg())) {
member.setHeadimg("static/resource/images/default_headimg.png");
}
data.put("nickname", member.getNickname().length() > 12 ? member.getNickname().substring(12) + "...的帮付" : member.getNickname() + "的帮付");
data.put("headimg", member.getHeadimg());
}
}
result.setData(data);
return result;
}
Member member = memberMapper.selectById(param.getOrDefault("member_id", "").toString());
if (member == null) {
return new GetPosterDataEventDefiner.GetPosterDataResult();
}
if (member.getNickname().length() > 10) {
member.setNickname(member.getNickname().substring(10) + "...");
}
String headimg = Optional.ofNullable(member.getHeadimg()).orElse("static/resource/images/default_headimg.png");
member.setHeadimg(headimg);
Map<String, Object> map = Map.of("nickname", member.getNickname(), "headimg", member.getHeadimg());
result.setData(map);
return result;
}
@Autowired
public void setPayMapper(PayMapper payMapper) {
this.payMapper = payMapper;
}
@Autowired
public void setMemberMapper(MemberMapper memberMapper) {
this.memberMapper = memberMapper;
}
@Autowired
public void setCoreSysConfigService(ICoreSysConfigService coreSysConfigService) {
this.coreSysConfigService = coreSysConfigService;
}
}

View File

@ -1,45 +1,66 @@
package com.niu.core.listener.sys;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.niu.core.common.annotation.EventCallback;
import com.niu.core.common.domain.BeanJsonSerializer;
import com.niu.core.common.domain.PageResult;
import com.niu.core.common.utils.date.DateUtils;
import com.niu.core.event.sys.ExportDataEventDefiner;
import com.niu.core.service.admin.member.IMemberService;
import com.niu.core.service.admin.member.param.MemberSearchParam;
import com.niu.core.service.admin.member.vo.MemberListVo;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;
import javax.annotation.Resource;
import java.util.List;
@EventCallback("core")
@Component
public class MemberExportDataListener extends ExportDataEventDefiner {
private final Class<? extends MemberListVo> clazz = MemberListVo.class;
@Resource
IMemberService memberService;
@Override
public ExportDataEventResult handleCallback(ExportDataEvent exportDataEvent) {
JSONArray result=new JSONArray();
ExportDataEventResult exportDataEventResult=new ExportDataEventResult();
if(exportDataEvent.getType().equals("member")){
JSONObject whereJson=exportDataEvent.getWhere();
JSONArray result = new JSONArray();
ExportDataEventResult exportDataEventResult = new ExportDataEventResult();
if (exportDataEvent.getType().equals("member")) {
JSONObject whereJson = exportDataEvent.getWhere();
MemberSearchParam memberSearchParam=new MemberSearchParam();
MemberSearchParam memberSearchParam = new MemberSearchParam();
memberSearchParam.setMemberLabel(whereJson.getInt("member_label", 0));
memberSearchParam.setMemberLevel(whereJson.getInt("member_level", 0));
String[] createTime=whereJson.get("create_time", String[].class);
String[] createTime = whereJson.get("create_time", String[].class);
memberSearchParam.setCreateTime(createTime);
memberSearchParam.setKeyword(whereJson.getStr("keyword", ""));
memberSearchParam.setRegisterChannel(whereJson.getStr("register_channel", ""));
memberSearchParam.setRegisterType(whereJson.getStr("register_type", ""));
memberSearchParam.setIsDel(whereJson.getInt("is_del", 0));
PageResult<MemberListVo> memberListVoPageResult= memberService.list(exportDataEvent.getPageParam(), memberSearchParam);
List<MemberListVo> memberList=memberListVoPageResult.getData();
result= JSONUtil.parseArray(memberList);
PageResult<MemberListVo> memberListVoPageResult = memberService.list(exportDataEvent.getPageParam(), memberSearchParam);
for (MemberListVo vo : memberListVoPageResult.getData()) {
JSONObject jsonObject = new JSONObject();
ReflectionUtils.doWithFields(clazz, field -> {
field.setAccessible(true);
String name = field.getName();
Object value = field.get(vo);
JsonSerialize anno = field.getAnnotation(JsonSerialize.class);
if (anno != null && anno.using().equals(BeanJsonSerializer.LongDateToStringSerializer.class) &&
value instanceof Long) {
value = DateUtils.timestampToString((Long) value);
}
jsonObject.set(StrUtil.toUnderlineCase(name), value);
});
result.add(jsonObject);
}
}
exportDataEventResult.setResultData(result);
return exportDataEventResult;

View File

@ -0,0 +1,46 @@
package com.niu.core.listener.sys;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpUtil;
import com.niu.core.common.annotation.EventCallback;
import com.niu.core.common.component.context.WebAppEnvs;
import com.niu.core.common.exception.CommonException;
import com.niu.core.common.utils.code.QRCodeUtils;
import com.niu.core.event.sys.GetQrcodeOfChannelDefiner;
import com.niu.core.service.core.weapp.ICoreWeappService;
import com.qcloud.cos.utils.Base64;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.nio.charset.Charset;
@EventCallback("core")
@Component
public class WeappQrcodeListener extends GetQrcodeOfChannelDefiner {
@Resource
ICoreWeappService coreWeappService;
@Override
public GetQrcodeOfChannelResult handleCallback(GetQrcodeOfChannelEvent event) {
if (event.getChannel().equals("weapp")) {
try {
GetQrcodeOfChannelResult result = new GetQrcodeOfChannelResult();
if (event.getOutfile()) {
String filePath = event.getFilePath() + "/";
File qrcode = coreWeappService.qrcodeFile(event.getSiteId(), WebAppEnvs.get().webRootDownResource + filePath, event.getPage(), event.getData(), 430);
result.setPath(filePath + qrcode.getName());
} else {
result.setPath("data:image/png;base64," + Base64.encodeAsString(coreWeappService.qrcodeBytes(event.getSiteId(), event.getPage(), event.getData(), 430)));
}
return result;
} catch (Exception e) {
throw new CommonException(e.getMessage());
}
}
return null;
}
}

View File

@ -31,6 +31,10 @@ public interface IAuthService {
*/
void checkRole(HttpServletRequest request);
/**
* 检测是否是演示环境
*/
void checkIsDemo(HttpServletRequest request);
/**
* 当前授权用户接口权限

View File

@ -6,7 +6,9 @@ import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.niu.core.common.component.context.cache.Cached;
import com.niu.core.common.config.GlobalConfig;
import com.niu.core.common.exception.AuthException;
import com.niu.core.common.exception.CommonException;
import com.niu.core.common.utils.RequestUtils;
import com.niu.core.common.utils.TreeUtils;
import com.niu.core.common.utils.crypto.PasswordEncipher;
@ -153,6 +155,15 @@ public class AuthServiceImpl implements IAuthService {
}
@Override
public void checkIsDemo(HttpServletRequest request) {
String method = RequestUtils.getRequestMethod();
if (!method.equals("get") && GlobalConfig.isDemo) {
throw new CommonException("演示环境不允许操作");
}
}
/**
* 当前授权用户接口权限
*

View File

@ -203,11 +203,10 @@ public class DiyServiceImpl implements IDiyService {
update.setIsDefault(0);
diyPageMapper.update(update, new QueryWrapper<DiyPage>().eq("name", model.getName()).eq("site_id", RequestUtils.siteId()));
DiyPage updateDefault = new DiyPage();
update.setId(id);
update.setIsDefault(1);
update.setUpdateTime(System.currentTimeMillis() / 1000);
diyPageMapper.updateById(updateDefault);
diyPageMapper.updateById(update);
}

View File

@ -7,6 +7,8 @@ import com.niu.core.common.domain.PageParam;
import com.niu.core.service.admin.member.vo.MemberAddressInfoVo;
import com.niu.core.service.admin.member.vo.MemberAddressListVo;
import java.util.List;
/**
* 会员收货地址服务接口
*/
@ -15,11 +17,9 @@ public interface IMemberAddressService {
/**
* 会员收货地址列表
* @param pageParam 分页参数
* @param searchParam 搜索参数
* @return PageResult<MemberAddressListVo>
* @return List<MemberAddressListVo>
*/
PageResult<MemberAddressListVo> list(PageParam pageParam, MemberAddressSearchParam searchParam);
List<MemberAddressListVo> list(MemberAddressSearchParam searchParam);
/**
* 会员收货地址详情

View File

@ -1,10 +1,12 @@
package com.niu.core.service.admin.member.impl;
import cn.hutool.core.util.ObjectUtil;
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.common.utils.RequestUtils;
import com.niu.core.entity.member.MemberAddress;
import com.niu.core.mapper.member.MemberAddressMapper;
import com.niu.core.service.admin.member.param.MemberAddressParam;
@ -12,6 +14,7 @@ import com.niu.core.service.admin.member.param.MemberAddressSearchParam;
import com.niu.core.service.admin.member.IMemberAddressService;
import com.niu.core.service.admin.member.vo.MemberAddressInfoVo;
import com.niu.core.service.admin.member.vo.MemberAddressListVo;
import org.bouncycastle.cert.ocsp.Req;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
@ -31,26 +34,23 @@ public class MemberAddressServiceImpl implements IMemberAddressService {
/**
* 会员收货地址列表
* @param pageParam 分页参数
* @param searchParam 搜索参数
* @return PageResult<MemberAddressListVo>
* @return List<MemberAddressListVo>
*/
@Override
public PageResult<MemberAddressListVo> list(PageParam pageParam, MemberAddressSearchParam searchParam) {
Integer page = pageParam.getPage();
Integer limit =pageParam.getLimit();
public List<MemberAddressListVo> list(MemberAddressSearchParam searchParam) {
QueryWrapper<MemberAddress> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("id");
queryWrapper.eq("site_id", RequestUtils.siteId());
if (ObjectUtil.isNotEmpty(searchParam.getMemberId())) queryWrapper.eq("member_id", searchParam.getMemberId());
IPage<MemberAddress> iPage = memberAddressMapper.selectPage(new Page<>(page, limit), queryWrapper);
List<MemberAddress> records = memberAddressMapper.selectList(queryWrapper);
List<MemberAddressListVo> list = new LinkedList<>();
for (MemberAddress item : iPage.getRecords()) {
for (MemberAddress item : records) {
MemberAddressListVo vo = new MemberAddressListVo();
BeanUtils.copyProperties(item, vo);
list.add(vo);
}
return PageResult.build(page, limit, iPage.getTotal()).setData(list);
return list;
}
/**
@ -63,7 +63,8 @@ public class MemberAddressServiceImpl implements IMemberAddressService {
MemberAddress model = memberAddressMapper.selectOne(
new QueryWrapper<MemberAddress>()
.eq("id", id)
.last("limit 1"));
.eq("site_id", RequestUtils.siteId())
);
Assert.notNull(model, "数据不存在");
@ -79,20 +80,8 @@ public class MemberAddressServiceImpl implements IMemberAddressService {
@Override
public void add(MemberAddressParam addParam) {
MemberAddress model = new MemberAddress();
model.setMemberId(addParam.getMemberId());
model.setSiteId(addParam.getSiteId());
model.setName(addParam.getName());
model.setMobile(addParam.getMobile());
model.setProvinceId(addParam.getProvinceId());
model.setCityId(addParam.getCityId());
model.setDistrictId(addParam.getDistrictId());
model.setAddress(addParam.getAddress());
model.setAddressName(addParam.getAddressName());
model.setFullAddress(addParam.getFullAddress());
model.setLng(addParam.getLng());
model.setLat(addParam.getLat());
model.setIsDefault(addParam.getIsDefault());
model.setType(addParam.getType());
BeanUtils.copyProperties(addParam, model);
model.setSiteId(RequestUtils.siteId());
memberAddressMapper.insert(model);
}
@ -105,25 +94,12 @@ public class MemberAddressServiceImpl implements IMemberAddressService {
public void edit(Integer id, MemberAddressParam editParam) {
MemberAddress model = memberAddressMapper.selectOne(
new QueryWrapper<MemberAddress>()
.eq("id", id)
.last("limit 1"));
.eq("id", id)
.eq("site_id", RequestUtils.siteId())
);
Assert.notNull(model, "数据不存在!");
model.setId(id);
model.setMemberId(editParam.getMemberId());
model.setSiteId(editParam.getSiteId());
model.setName(editParam.getName());
model.setMobile(editParam.getMobile());
model.setProvinceId(editParam.getProvinceId());
model.setCityId(editParam.getCityId());
model.setDistrictId(editParam.getDistrictId());
model.setAddress(editParam.getAddress());
model.setAddressName(editParam.getAddressName());
model.setFullAddress(editParam.getFullAddress());
model.setLng(editParam.getLng());
model.setLat(editParam.getLat());
model.setIsDefault(editParam.getIsDefault());
model.setType(editParam.getType());
BeanUtils.copyProperties(editParam, model);
memberAddressMapper.updateById(model);
}
@ -136,7 +112,7 @@ public class MemberAddressServiceImpl implements IMemberAddressService {
MemberAddress model = memberAddressMapper.selectOne(
new QueryWrapper<MemberAddress>()
.eq("id", id)
.last("limit 1"));
.eq("site_id", RequestUtils.siteId()));
Assert.notNull(model, "数据不存在!");

View File

@ -1,5 +1,6 @@
package com.niu.core.service.admin.member.impl;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
@ -17,9 +18,14 @@ import com.niu.core.common.utils.RequestUtils;
import com.niu.core.common.utils.mapper.QueryMapperUtils;
import com.niu.core.entity.member.Member;
import com.niu.core.entity.member.MemberLabel;
import com.niu.core.entity.member.MemberLevel;
import com.niu.core.enums.common.ChannelEnum;
import com.niu.core.enums.common.SexEnum;
import com.niu.core.enums.member.MemberRegisterChannelEnum;
import com.niu.core.enums.member.MemberRegisterTypeEnum;
import com.niu.core.enums.member.StatusEnum;
import com.niu.core.mapper.member.MemberLabelMapper;
import com.niu.core.mapper.member.MemberLevelMapper;
import com.niu.core.mapper.member.MemberMapper;
import com.niu.core.service.admin.member.IMemberService;
import com.niu.core.service.admin.member.param.MemberAddParam;
@ -36,10 +42,8 @@ import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
/**
* 会员实现
@ -53,6 +57,9 @@ public class MemberServiceImpl implements IMemberService {
@Resource
MemberLabelMapper memberLabelMapper;
@Resource
MemberLevelMapper memberLevelMapper;
@Resource
ICoreMemberService iCoreMemberService;
@ -86,13 +93,13 @@ public class MemberServiceImpl implements IMemberService {
if (ObjectUtil.isNotNull(searchParam.getIsDel()) && ObjectUtil.isNotEmpty(searchParam.getKeyword())) {
queryWrapper.eq("is_del", searchParam.getIsDel());
}
if (ObjectUtil.isNotEmpty(searchParam.getMemberLevel())) {
if (ObjectUtil.isNotEmpty(searchParam.getMemberLevel()) && searchParam.getMemberLevel() != 0) {
queryWrapper.eq("member_level", searchParam.getMemberLevel());
}
if (ObjectUtil.isNotEmpty(searchParam.getRegisterChannel())) {
queryWrapper.eq("register_channel", searchParam.getRegisterChannel());
}
if (ObjectUtil.isNotEmpty(searchParam.getMemberLabel())) {
if (ObjectUtil.isNotEmpty(searchParam.getMemberLabel()) && searchParam.getMemberLabel() != 0) {
queryWrapper.like("member_label", searchParam.getMemberLabel());
}
if (ObjectUtil.isNotEmpty(searchParam.getRegisterType())) {
@ -110,10 +117,22 @@ public class MemberServiceImpl implements IMemberService {
} else {
memberList = memberMapper.selectList(queryWrapper);
}
Map<Integer, MemberLevel> levelMap = Collections.emptyMap();
Set<Integer> levelIds = CollStreamUtil.toSet(memberList, Member::getMemberLevel);
if (ObjectUtil.isNotEmpty(levelIds)) {
levelMap = memberLevelMapper.selectBatchIds(levelIds).stream().collect(Collectors.toMap(MemberLevel::getLevelId, e -> e));
}
List<MemberListVo> list = new LinkedList<>();
for (Member item : memberList) {
MemberListVo vo = new MemberListVo();
BeanUtils.copyProperties(item, vo);
vo.setSexName(SexEnum.getNameBySex(item.getSex()));
vo.setStatusName(StatusEnum.getNameByStatus(item.getStatus()));
vo.setRegisterChannelName(ChannelEnum.getNameByCode(item.getRegisterChannel()));
vo.setMemberLevelName(levelMap.getOrDefault(item.getMemberLevel(), new MemberLevel()).getLevelName());
if (!item.getMemberLabel().isEmpty()) {
JSONArray memberLabelArrays = JSONUtil.parseArray(vo.getMemberLabel());
if (memberLabelArrays != null && memberLabelArrays.size() > 0) {

View File

@ -1,56 +1,49 @@
package com.niu.core.service.admin.member.param;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import javax.validation.constraints.*;
/**
* 会员收货地址参数
*/
*/
@Data
public class MemberAddressParam implements Serializable {
private static final long serialVersionUID = 1L;
@NotNull(message = "memberId参数缺失")
@NotNull(message = "缺少必须参数member_id")
private Integer memberId;
@NotNull(message = "siteId参数缺失")
private Integer siteId;
@NotNull(message = "name参数缺失")
@NotNull(message = "缺少必须参数name")
private String name;
@NotNull(message = "mobile参数缺失")
@NotNull(message = "缺少必须参数mobile")
private String mobile;
@NotNull(message = "provinceId参数缺失")
@NotNull(message = "缺少必须参数province_id")
private Integer provinceId;
@NotNull(message = "cityId参数缺失")
@NotNull(message = "缺少必须参数city_id")
private Integer cityId;
@NotNull(message = "districtId参数缺失")
@NotNull(message = "缺少必须参数district_id")
private Integer districtId;
@NotNull(message = "address参数缺失")
@NotNull(message = "缺少必须参数address")
private String address;
@NotNull(message = "addressName参数缺失")
private String addressName;
@NotNull(message = "fullAddress参数缺失")
@NotNull(message = "缺少必须参数full_address")
private String fullAddress;
@NotNull(message = "lng参数缺失")
private String lng;
private String lng = "";
@NotNull(message = "lat参数缺失")
private String lat;
private String lat = "";
@NotNull(message = "isDefault参数缺失")
private Integer isDefault;
@NotNull(message = "type参数缺失")
private String type;
private Integer isDefault = 0;
}

View File

@ -1,5 +1,7 @@
package com.niu.core.service.admin.member.param;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
@ -12,30 +14,4 @@ public class MemberAddressSearchParam implements Serializable {
private Integer memberId;
private Integer siteId;
private String name;
private String mobile;
private Integer provinceId;
private Integer cityId;
private Integer districtId;
private String address;
private String addressName;
private String fullAddress;
private String lng;
private String lat;
private Integer isDefault;
private String type;
}

View File

@ -1,11 +1,16 @@
package com.niu.core.service.admin.pay;
import com.niu.core.common.domain.PageParam;
import com.niu.core.common.domain.PageResult;
import com.niu.core.service.admin.pay.param.GetFriendspayInfoByTradeParam;
import com.niu.core.service.admin.pay.param.PayParam;
import com.niu.core.service.admin.pay.param.PaySearchParam;
import com.niu.core.common.domain.PageParam;
import com.niu.core.service.admin.pay.vo.FriendsPayInfoByTradeVo;
import com.niu.core.service.admin.pay.vo.PayInfoVo;
import com.niu.core.service.admin.pay.vo.PayListVo;
import com.niu.core.service.core.pay.vo.PayTypeVo;
import java.util.List;
/**
* 支付记录服务接口
@ -15,7 +20,8 @@ public interface IPayService {
/**
* 支付记录列表
* @param pageParam 分页参数
*
* @param pageParam 分页参数
* @param searchParam 搜索参数
* @return PageResult<PayListVo>
*/
@ -23,6 +29,7 @@ public interface IPayService {
/**
* 支付记录详情
*
* @param id 主键ID
* @return PayInfoVo
*/
@ -30,21 +37,30 @@ public interface IPayService {
/**
* 支付记录添加
*
* @param addParam 添加参数
*/
void add(PayParam addParam);
/**
* 支付记录编辑
* @param id 主键
*
* @param id 主键
* @param editParam 编辑参数
*/
void edit(Integer id, PayParam editParam);
/**
* 支付记录删除
*
* @param id 主键ID
*/
void del(Integer id);
FriendsPayInfoByTradeVo getFriendspayInfoByTrade(GetFriendspayInfoByTradeParam param);
List<PayTypeVo> getPayTypeList();
Object pay(com.niu.core.common.loader.pay.param.PayParam param);
}

View File

@ -1,23 +1,43 @@
package com.niu.core.service.admin.pay.impl;
import cn.hutool.core.util.ObjectUtil;
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.common.domain.PageResult;
import com.niu.core.common.utils.QrcodeUtils;
import com.niu.core.common.utils.RequestUtils;
import com.niu.core.common.utils.date.DateUtils;
import com.niu.core.entity.member.Member;
import com.niu.core.entity.pay.Pay;
import com.niu.core.entity.sys.SysPoster;
import com.niu.core.enums.common.ChannelEnum;
import com.niu.core.mapper.member.MemberMapper;
import com.niu.core.mapper.pay.PayMapper;
import com.niu.core.mapper.sys.SysPosterMapper;
import com.niu.core.service.admin.pay.IPayService;
import com.niu.core.service.admin.pay.param.GetFriendspayInfoByTradeParam;
import com.niu.core.service.admin.pay.param.PayParam;
import com.niu.core.service.admin.pay.param.PaySearchParam;
import com.niu.core.service.admin.pay.IPayService;
import com.niu.core.service.admin.pay.vo.FriendsPayInfoByTradeVo;
import com.niu.core.service.admin.pay.vo.PayInfoVo;
import com.niu.core.service.admin.pay.vo.PayListVo;
import com.niu.core.service.core.pay.ICorePayService;
import com.niu.core.service.core.pay.vo.GetInfoByTradeVo;
import com.niu.core.service.core.pay.vo.PayTypeVo;
import com.niu.core.service.core.sys.ICoreSysConfigService;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
@ -25,20 +45,33 @@ import java.util.List;
*/
@Service
public class PayServiceImpl implements IPayService {
@Resource
PayMapper payMapper;
@Resource
ICorePayService corePayService;
@Resource
SysPosterMapper sysPosterMapper;
@Resource
MemberMapper memberMapper;
@Resource
ICoreSysConfigService coreSysConfigService;
/**
* 支付记录列表
* @param pageParam 分页参数
*
* @param pageParam 分页参数
* @param searchParam 搜索参数
* @return PageResult<PayListVo>
*/
@Override
public PageResult<PayListVo> list(PageParam pageParam, PaySearchParam searchParam) {
Integer page = pageParam.getPage();
Integer limit =pageParam.getLimit();
Integer page = pageParam.getPage();
Integer limit = pageParam.getLimit();
QueryWrapper<Pay> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("id");
@ -55,6 +88,7 @@ public class PayServiceImpl implements IPayService {
/**
* 支付记录详情
*
* @param id 主键
* @return PayInfoVo
*/
@ -62,8 +96,8 @@ public class PayServiceImpl implements IPayService {
public PayInfoVo info(Integer id) {
Pay model = payMapper.selectOne(
new QueryWrapper<Pay>()
.eq("id", id)
.last("limit 1"));
.eq("id", id)
.last("limit 1"));
Assert.notNull(model, "数据不存在");
@ -74,6 +108,7 @@ public class PayServiceImpl implements IPayService {
/**
* 支付记录添加
*
* @param addParam 参数
*/
@Override
@ -110,8 +145,8 @@ public class PayServiceImpl implements IPayService {
public void edit(Integer id, PayParam editParam) {
Pay model = payMapper.selectOne(
new QueryWrapper<Pay>()
.eq("id", id)
.last("limit 1"));
.eq("id", id)
.last("limit 1"));
Assert.notNull(model, "数据不存在!");
model.setId(id);
@ -138,18 +173,104 @@ public class PayServiceImpl implements IPayService {
/**
* 支付记录删除
*
* @param id 主键ID
*/
@Override
public void del(Integer id) {
Pay model = payMapper.selectOne(
new QueryWrapper<Pay>()
.eq("id", id)
.last("limit 1"));
.eq("id", id)
.last("limit 1"));
Assert.notNull(model, "数据不存在!");
payMapper.delete(new QueryWrapper<Pay>().eq("id", id));
}
@Override
public FriendsPayInfoByTradeVo getFriendspayInfoByTrade(GetFriendspayInfoByTradeParam param) {
GetInfoByTradeVo payInfo = corePayService.getInfoByTrade(RequestUtils.siteId(), param.getTradeType(), param.getTradeId(), param.getChannel(), "friendspay");
if (ObjectUtil.isEmpty(payInfo)) {
return new FriendsPayInfoByTradeVo();
}
FriendsPayInfoByTradeVo vo = new FriendsPayInfoByTradeVo();
BeanUtils.copyProperties(payInfo, vo);
vo.setConfig(payInfo.getConfig());
vo.setCreateTime(DateUtils.timestampToString(payInfo.getCreateTime()));
if (payInfo.getCancelTime() > 0) {
vo.setCancelTime(DateUtils.timestampToString(payInfo.getCancelTime()));
}
if (payInfo.getPayTime() > 0) {
vo.setPayTime(DateUtils.timestampToString(payInfo.getPayTime()));
}
QueryWrapper<SysPoster> posterQueryWrapper = new QueryWrapper<>();
posterQueryWrapper.eq("site_id", RequestUtils.siteId())
.eq("type", "friendspay")
.eq("status", 1)
.eq("is_default", 1);
SysPoster poster = sysPosterMapper.selectOne(posterQueryWrapper);
if (ObjectUtil.isNotEmpty(poster)) {
vo.setPosterId(poster.getId());
}
QueryWrapper<Member> memberQueryWrapper = new QueryWrapper<>();
memberQueryWrapper.eq("site_id", RequestUtils.siteId())
.eq("member_id", vo.getMainId());
Member member = memberMapper.selectOne(memberQueryWrapper);
vo.setMember(member);
QR qrcode = getQrcode(param.getTradeType(), param.getTradeId(), param.getChannel());
vo.setLink(qrcode.link);
vo.setQrcode(qrcode.qrcode);
return vo;
}
@Override
public List<PayTypeVo> getPayTypeList() {
List<PayTypeVo> payTypeList = corePayService.getPayTypeByTrade(RequestUtils.siteId(), "", ChannelEnum.H5);
if (ObjectUtil.isEmpty(payTypeList)) {
return Collections.emptyList();
}
return payTypeList.stream().filter(o -> o.getKey().equals("balancepay") || o.getKey().equals("friendspay")).toList();
}
@Override
public Object pay(com.niu.core.common.loader.pay.param.PayParam param) {
param.setSiteId(RequestUtils.siteId());
return corePayService.pay(param);
}
private QR getQrcode(String tradeType, Integer tradeId, String channel) {
String url = coreSysConfigService.getSceneDomain(RequestUtils.siteId()).getWapUrl();
String page = "app/pages/friendspay/money";
String dir = "upload/" + RequestUtils.siteId() + "/friendspay_qrcode";
String path = "";
Map<String, Object> data = Map.of("id", tradeId, "type", tradeType);
try {
path = QrcodeUtils.qrcodeToFile(RequestUtils.siteId(), channel, url, page, data, dir);
} catch (Exception e) {
}
url = url + "/" + page;
List<String> scene = data.entrySet().stream().map(entry -> entry.getKey() + "=" + entry.getValue()).toList();
url += "?" + String.join("&", scene);
return new QR(url, path);
}
@Data
@AllArgsConstructor
private static class QR {
private String link;
private String qrcode;
}
}

View File

@ -0,0 +1,10 @@
package com.niu.core.service.admin.pay.param;
import lombok.Data;
@Data
public class GetFriendspayInfoByTradeParam {
private String tradeType;
private Integer tradeId;
private String channel;
}

View File

@ -0,0 +1,36 @@
package com.niu.core.service.admin.pay.vo;
import cn.hutool.json.JSONObject;
import com.niu.core.entity.member.Member;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class FriendsPayInfoByTradeVo {
private Integer id;
private Integer siteId;
private Integer mainId;
private String outTradeNo;
private String tradeType;
private Integer tradeId;
private String tradeNo;
private String body;
private BigDecimal money;
private String voucher;
private Integer status;
private String json;
private String createTime;
private String payTime;
private String cancelTime;
private String type;
private String mchId;
private String mainType;
private String channel;
private String failReason;
private Integer posterId;
private Member member;
private String link;
private String qrcode;
private JSONObject config;
}

View File

@ -1,22 +1,26 @@
package com.niu.core.service.admin.sys.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
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.github.yulichang.query.MPJQueryWrapper;
import com.niu.core.common.domain.PageParam;
import com.niu.core.common.domain.PageResult;
import com.niu.core.common.utils.RequestUtils;
import com.niu.core.common.utils.date.DateUtils;
import com.niu.core.common.utils.json.JsonModuleLoader;
import com.niu.core.entity.sys.SysExport;
import com.niu.core.enums.sys.ExportEnum;
import com.niu.core.mapper.sys.SysExportMapper;
import com.niu.core.service.admin.sys.ISysExportService;
import com.niu.core.service.admin.sys.param.SysExportSearchParam;
import com.niu.core.service.admin.sys.vo.SysExportListVo;
import com.niu.core.service.core.sys.ICoreExportService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
@ -48,15 +52,18 @@ public class SysExportServiceImpl implements ISysExportService {
Integer page = pageParam.getPage();
Integer limit = pageParam.getLimit();
MPJQueryWrapper<SysExport> queryWrapper = new MPJQueryWrapper<>();
QueryWrapper<SysExport> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("id");
queryWrapper.like("export_key", searchParam.getExportKey());
queryWrapper.eq("export_status", searchParam.getExportStatus());
if (ObjectUtil.isNotEmpty(searchParam.getExportKey())) {
queryWrapper.eq("export_status", searchParam.getExportStatus());
}
if (ObjectUtil.isNotEmpty(searchParam.getCreateTime())) {
String[] createTime = searchParam.getCreateTime();
Long startTime = (createTime[0] == null) ? 0 : DateUtils.StringToTimestamp(createTime[0]);
Long endTime = (createTime[1] == null) ? 0 : DateUtils.StringToTimestamp(createTime[1]);
long startTime = (createTime[0] == null) ? 0 : DateUtils.StringToTimestamp(createTime[0]);
long endTime = (createTime[1] == null) ? 0 : DateUtils.StringToTimestamp(createTime[1]);
if (startTime > 0 && endTime > 0) {
queryWrapper.between("create_time", startTime, endTime);
} else if (startTime > 0 && endTime == 0) {
@ -66,8 +73,25 @@ public class SysExportServiceImpl implements ISysExportService {
}
}
IPage<SysExportListVo> iPage = sysExportMapper.selectJoinPage(new Page<>(page, limit), SysExportListVo.class, queryWrapper);
return PageResult.build(page, limit, iPage.getTotal()).setData(iPage.getRecords());
JSONArray results = JsonModuleLoader.build().mergeResultSet("export/ExportType.json");
IPage<SysExport> iPage = sysExportMapper.selectPage(new Page<>(page, limit), queryWrapper);
IPage<SysExportListVo> converted = iPage.convert(export -> {
SysExportListVo vo = new SysExportListVo();
BeanUtils.copyProperties(export, vo);
vo.setCreateTime(DateUtils.timestampToString(export.getCreateTime()));
vo.setExportStatusName(ExportEnum.getNameByCode(export.getExportStatus()));
results.stream()
.map(JSONUtil::parseObj)
.filter(o -> o.containsKey(export.getExportKey()))
.findFirst()
.map(o -> o.getJSONObject(export.getExportKey()))
.ifPresent(o -> vo.setExportKeyName(o.getStr("name")));
return vo;
});
return PageResult.build(converted);
}
/**
@ -89,8 +113,6 @@ public class SysExportServiceImpl implements ISysExportService {
/**
* 获取导出数据类型列表
*
* @return
*/
@Override
public Map<String, String> getExportDataType() {
@ -99,14 +121,9 @@ public class SysExportServiceImpl implements ISysExportService {
/**
* 检查导出数据源是否为空
*
* @param type
* @param whereMap
* @return
*/
@Override
public Boolean checkExportData(String type, Map<String, Object> whereMap) {
Integer siteId = RequestUtils.siteId();
JSONObject whereJson = new JSONObject();
whereJson.set("keyword", whereMap.getOrDefault("keyword", ""));
whereJson.set("register_type", whereMap.getOrDefault("register_type", ""));
@ -119,15 +136,12 @@ public class SysExportServiceImpl implements ISysExportService {
PageParam pageParam = new PageParam();
pageParam.setPage(Integer.parseInt(whereMap.getOrDefault("page", 0).toString()));
pageParam.setLimit(Integer.parseInt(whereMap.getOrDefault("limit", 0).toString()));
JSONArray jsonArray = coreExportService.getExportData(siteId, type, whereJson, pageParam);
return jsonArray.size() > 0;
JSONArray jsonArray = coreExportService.getExportData(RequestUtils.siteId(), type, whereJson, pageParam);
return !jsonArray.isEmpty();
}
/**
* 导出数据
*
* @param type
* @param whereMap
*/
@Override
public void exportData(String type, Map<String, Object> whereMap) {
@ -147,7 +161,15 @@ public class SysExportServiceImpl implements ISysExportService {
JSONArray dataColumn = coreExportService.getExportDataColumn(type);
JSONArray dataArray = coreExportService.getExportData(siteId, type, whereJson, pageParam);
coreExportService.export(siteId, type, dataColumn, dataArray);
SysExport export = new SysExport();
export.setSiteId(RequestUtils.siteId());
export.setExportKey(type);
export.setExportNum(CollectionUtil.size(dataArray));
export.setCreateTime(System.currentTimeMillis() / 1000);
coreExportService.add(export);
coreExportService.export(siteId, export.getId(), type, dataColumn, dataArray);
}
}

View File

@ -1,7 +1,9 @@
package com.niu.core.service.admin.sys.vo;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.niu.core.common.domain.BeanJsonSerializer;
import com.niu.core.enums.poster.PosterTypeEnum;
@ -21,11 +23,15 @@ public class SysPosterInitVo implements Serializable {
private String name = ""; // 海报名称
private String type = ""; // 海报类型
private String channel = ""; // 海报支持渠道
@JsonSerialize(using = BeanJsonSerializer.StringToJSONObjectSerializer.class)
private String value = ""; // 配置值json
private Integer status = 1; // 是否启用 1启用 2不启用
private String addon = ""; // 所属插件
private Integer isDefault = 0; // 是否默认海报10
private JSONObject posterType;
private JSONObject component;
public Object getValue() {
if (ObjectUtil.isEmpty(value)) return "";
return JSONUtil.parseObj(value);
}
}

View File

@ -35,6 +35,7 @@ import com.niu.core.service.core.app.tools.SQLScriptRunnerTools;
import com.niu.core.service.core.schedule.ICoreScheduleService;
import com.niu.core.service.core.sys.ICoreMenuService;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.IOFileFilter;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
@ -492,13 +493,21 @@ public class UpgradeServiceImpl implements IUpgradeService {
}
}
IOFileFilter envFile = FileTools.createExclusionFilter(new String[]{
"application-prod.yml",
".env.development",
".env.production",
".env.dev",
".env.product"
});
// 覆盖变更文件
File codeDir = new File(upgradeDir(vo) + "/download/" + versionNo);
if (vo.getAddon().equals(GlobalConfig.appKey)) {
File[] childFile = codeDir.listFiles();
for (File file : childFile) {
if (file.isDirectory()) {
if (new File(sourceFile, file.getName()).exists()) FileUtils.copyDirectory(file, new File(sourceFile, file.getName()));
if (new File(sourceFile, file.getName()).exists()) FileUtils.copyDirectory(file, new File(sourceFile, file.getName()), envFile);
} else {
FileUtils.copyFile(file, new File(sourceFile, file.getName()));
}
@ -757,6 +766,7 @@ public class UpgradeServiceImpl implements IUpgradeService {
// 获取方法对象
java.lang.reflect.Method method = clazz.getMethod(methodName, extractParameterTypes(args));
// 调用方法
System.out.println("dynamicMethodCall method" + methodName);
Object result = method.invoke(this, args);
if (method.getReturnType() == void.class) {
return null;
@ -764,7 +774,11 @@ public class UpgradeServiceImpl implements IUpgradeService {
return result;
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
if (e instanceof InvocationTargetException) {
((InvocationTargetException) e).getCause().printStackTrace();
} else {
e.printStackTrace();
}
return null;
}
}

View File

@ -58,12 +58,15 @@ public class DiyServiceImpl implements IDiyService {
Integer id = ObjectUtil.defaultIfNull(param.getId(), 0);
String name = ObjectUtil.defaultIfNull(param.getName(), "");
log.info("id: {}, name: {}", id, name);
StartUpPageConfigVo startUpPage = null;
JSONObject template = null;
if (!StrUtil.isEmpty(name)) {
// 查询启动页
startUpPage = coreDiyConfigService.getStartUpPageConfig(param.siteId(), name);
log.info("startUpPage: {}", JSONUtil.toJsonStr(startUpPage));
TemplateParam templateParam = new TemplateParam();
String[] key = { name };
@ -72,13 +75,16 @@ public class DiyServiceImpl implements IDiyService {
}
if (id == 0 && startUpPage != null && template != null && !startUpPage.getPage().equals(template.getStr("page"))) {
log.info("enter if, template: {}", template.toString());
return startUpPage;
} else {
QueryWrapper<DiyPage> queryWrapper = new QueryWrapper();
queryWrapper.eq("site_id", param.siteId());
log.info("site_id: {}",param.siteId() );
DiyPage info = null;
log.info("id: {}, name: {}", id, name);
if (id > 0) {
queryWrapper.eq("id", id);
info = diyPageMapper.selectOne(queryWrapper);
@ -88,6 +94,8 @@ public class DiyServiceImpl implements IDiyService {
info = diyPageMapper.selectOne(queryWrapper);
}
log.info("info: {}", JSONUtil.toJsonStr(info));
if (info == null) {
if (!name.isEmpty()) {
JSONObject pageData = getFirstPageData(name, "");
@ -98,10 +106,12 @@ public class DiyServiceImpl implements IDiyService {
}
}
log.info("info: {}", JSONUtil.toJsonStr(info));
if (info == null) return null;
DiyInfoVo vo = new DiyInfoVo();
BeanUtils.copyProperties(info, vo);
log.info("vo: {}", JSONUtil.toJsonStr(vo));
return vo;
}
}

View File

@ -65,17 +65,33 @@ public class MemberLevelServiceImpl implements IMemberLevelService {
JSONObject levelStyle = MemberLevelStyleEnum.getStyle();
JSONObject filling = new JSONObject();
filling.put("benefits_one", new JSONObject().set("title", "专属客服").set("desc", "专业服务").set("icon", "/static/resource/images/member/benefits/benefits_kefu.png"));
filling.put("benefits_two", new JSONObject().set("title", "专属徽章").set("desc", "专属徽章").set("icon", "/static/resource/images/member/benefits/benefits_badge.png"));
filling.put("benefits_four", new JSONObject().set("title", "经验累计").set("desc", "经验累计").set("icon", "/static/resource/images/member/benefits/benefits_experience.png"));
filling.put("benefits_three", new JSONObject().set("title", "尊享客服").set("desc", "尊享客服").set("icon", "/static/resource/images/member/benefits/benefits_badge.png"));
Integer index = 0;
List<MemberLevelInfoVo> list = new LinkedList<>();
for (MemberLevel level : memberLevelList) {
MemberLevelInfoVo vo = new MemberLevelInfoVo();
BeanUtils.copyProperties(level, vo);
if (!level.getLevelBenefits().isEmpty()) {
if (ObjectUtil.isNotEmpty(level.getLevelBenefits())) {
JSONObject benefits = JSONUtil.parseObj(level.getLevelBenefits());
benefits = coreMemberService.getBenefitsContent(param.siteId(), benefits, "member_level");
vo.setLevelBenefits(benefits);
} else {
vo.setLevelBenefits(filling);
}
if (vo.getLevelBenefits().size() < 4) {
for(String key : filling.keySet()) {
if (vo.getLevelBenefits().size() == 4) break;
vo.getLevelBenefits().set(key, filling.get(key));
}
}
if (!level.getLevelGifts().isEmpty()) {
JSONObject gifts = JSONUtil.parseObj(level.getLevelGifts());
gifts = coreMemberService.getGiftContent(param.siteId(), gifts, "member_level");

View File

@ -1,8 +1,9 @@
package com.niu.core.service.api.pay;
import com.niu.core.service.api.pay.vo.PayInfoVo;
import com.niu.core.common.loader.pay.param.PayAsyncNotifyParam;
import com.niu.core.common.loader.pay.param.PayParam;
import com.niu.core.service.api.pay.vo.FriendspayInfoVo;
import com.niu.core.service.core.pay.vo.GetInfoByTradeVo;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -13,5 +14,7 @@ public interface IPayService {
Object asyncNotify(PayAsyncNotifyParam param, HttpServletRequest request, HttpServletResponse response);
PayInfoVo getInfoByTrade(String tradeType, Integer tradeId);
GetInfoByTradeVo getInfoByTrade(String tradeType, Integer tradeId, String scene);
FriendspayInfoVo friendspayInfo(String tradeType, Integer tradeId);
}

View File

@ -3,18 +3,24 @@ package com.niu.core.service.api.pay.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.niu.core.common.utils.RequestUtils;
import com.niu.core.entity.member.Member;
import com.niu.core.entity.pay.Pay;
import com.niu.core.enums.common.ChannelEnum;
import com.niu.core.mapper.member.MemberMapper;
import com.niu.core.service.api.pay.IPayService;
import com.niu.core.service.api.pay.vo.PayInfoVo;
import com.niu.core.service.core.pay.ICorePayChannelService;
import com.niu.core.service.core.pay.ICorePayService;
import com.niu.core.common.loader.pay.param.PayAsyncNotifyParam;
import com.niu.core.common.loader.pay.param.PayParam;
import com.niu.core.service.core.pay.vo.PayTypeVo;
import com.niu.core.common.utils.RequestUtils;
import com.niu.core.common.utils.date.DateUtils;
import com.niu.core.entity.member.Member;
import com.niu.core.entity.pay.Pay;
import com.niu.core.entity.sys.SysPoster;
import com.niu.core.enums.common.ChannelEnum;
import com.niu.core.event.pay.PayTradeInfoDefiner;
import com.niu.core.mapper.member.MemberMapper;
import com.niu.core.mapper.pay.PayMapper;
import com.niu.core.mapper.sys.SysPosterMapper;
import com.niu.core.service.api.pay.IPayService;
import com.niu.core.service.api.pay.vo.FriendspayInfoVo;
import com.niu.core.service.core.app.helper.EventAndSubscribeOfPublisher;
import com.niu.core.service.core.pay.ICorePayChannelService;
import com.niu.core.service.core.pay.ICorePayService;
import com.niu.core.service.core.pay.vo.GetInfoByTradeVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@ -36,8 +42,15 @@ public class PayServiceImpl implements IPayService {
@Resource
ICorePayChannelService corePayChannelService;
@Resource
PayMapper payMapper;
@Resource
SysPosterMapper sysPosterMapper;
/**
* 支付
*
* @param param
* @return
*/
@ -70,20 +83,59 @@ public class PayServiceImpl implements IPayService {
return corePayService.asyncNotify(param, request, response);
}
public PayInfoVo getInfoByTrade(String tradeType, Integer tradeId) {
Pay pay = null;
pay = corePayService.findPayInfoByTrade(RequestUtils.siteId(), tradeType, tradeId);
public GetInfoByTradeVo getInfoByTrade(String tradeType, Integer tradeId, String scene) {
return corePayService.getInfoByTrade(RequestUtils.siteId(), tradeType, tradeId, RequestUtils.channel(), scene);
}
if (pay == null) {
pay = corePayService.createByTrade(RequestUtils.siteId(), tradeType, tradeId);
@Override
public FriendspayInfoVo friendspayInfo(String tradeType, Integer tradeId) {
QueryWrapper<Pay> payQueryWrapper = new QueryWrapper<>();
payQueryWrapper.eq("trade_type", tradeType)
.eq("trade_id", tradeId);
List<Pay> fromPayInfos = payMapper.selectList(payQueryWrapper);
if (ObjectUtil.isEmpty(fromPayInfos) || fromPayInfos.stream().noneMatch(o -> o.getSiteId().equals(RequestUtils.siteId()))) {
throw new RuntimeException("支付单据不存在");
}
PayInfoVo vo = new PayInfoVo();
BeanUtil.copyProperties(pay, vo);
GetInfoByTradeVo payInfo = getInfoByTrade(tradeType, tradeId, "friendspay");
if (ObjectUtil.isEmpty(payInfo)) {
return new FriendspayInfoVo();
}
List<PayTypeVo> payTypeList = corePayChannelService.getAllowPayTypeByChannel(RequestUtils.siteId(), RequestUtils.channel(), tradeType);
vo.setPayTypeList(payTypeList);
FriendspayInfoVo vo = new FriendspayInfoVo();
BeanUtil.copyProperties(payInfo, vo);
vo.setConfig(payInfo.getConfig());
vo.setPayTypeList(payInfo.getPayTypeList());
vo.setCreateTime(DateUtils.timestampToString(payInfo.getCreateTime()));
if (payInfo.getPayTime() != 0) {
vo.setPayTime(DateUtils.timestampToString(payInfo.getPayTime()));
}
if (payInfo.getCancelTime() != 0) {
vo.setCancelTime(DateUtils.timestampToString(payInfo.getCancelTime()));
}
PayTradeInfoDefiner.PayTradeInfoEvent event = new PayTradeInfoDefiner.PayTradeInfoEvent(tradeType, tradeId);
List<PayTradeInfoDefiner.PayTradeInfoEventResult> trades = EventAndSubscribeOfPublisher.publishAndCallback(event);
if (ObjectUtil.isNotEmpty(trades)) {
vo.setTradeInfo(trades.get(0).getJsonObject());
}
vo.setSelf(payInfo.getMainId().equals(RequestUtils.memberId()));
QueryWrapper<SysPoster> posterQueryWrapper = new QueryWrapper<>();
posterQueryWrapper.eq("site_id", RequestUtils.siteId())
.eq("type", "friendspay")
.eq("status", 1)
.eq("is_default", 1);
SysPoster sysPoster = sysPosterMapper.selectOne(posterQueryWrapper);
if (ObjectUtil.isNotEmpty(sysPoster)) {
vo.setPosterId(sysPoster.getId());
}
Member member = memberMapper.selectById(payInfo.getMainId());
vo.setMember(member);
return vo;
}
}

View File

@ -0,0 +1,9 @@
package com.niu.core.service.api.pay.param;
import lombok.Data;
@Data
public class FriendspayInfoParam {
private String tradeType;
private Integer tradeId;
}

View File

@ -0,0 +1,39 @@
package com.niu.core.service.api.pay.vo;
import cn.hutool.json.JSONObject;
import com.niu.core.entity.member.Member;
import com.niu.core.service.core.pay.vo.PayTypeVo;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Data
public class FriendspayInfoVo {
private Integer id;
private Integer siteId;
private Integer mainId;
private String outTradeNo;
private String tradeType;
private Integer tradeId;
private String tradeNo;
private String body;
private BigDecimal money;
private String voucher;
private Integer status;
private String json;
private String createTime;
private String payTime;
private String cancelTime;
private String type;
private String mchId;
private String mainType;
private String channel;
private String failReason;
private int posterId;
private Member member;
private boolean isSelf;
private Object tradeInfo;
private JSONObject config;
private List<PayTypeVo> payTypeList;
}

View File

@ -1,82 +0,0 @@
package com.niu.core.service.api.pay.vo;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.niu.core.common.domain.BeanJsonSerializer;
import com.niu.core.service.core.pay.vo.PayTypeVo;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
@Data
public class PayInfoVo implements Serializable {
private static final long serialVersionUID = 1L;
/** 主键 */
private Integer id;
/** 站点id */
private Integer siteId;
/** 支付会员id */
private Integer mainId;
/** 支付流水号 */
private String outTradeNo;
/** 业务类型 */
private String tradeType;
/** 业务id */
private Integer tradeId;
/** 交易单号 */
private String tradeNo;
/** 支付主体 */
private String body;
/** 支付金额 */
private BigDecimal money;
/** 支付票据 */
private String voucher;
/** 支付状态0.待支付 1. 支付中 2. 已支付 -1已取消 */
private Integer status;
/** 支付扩展用支付信息 */
private String json;
/** 创建时间 */
@JsonSerialize(using = BeanJsonSerializer.LongDateToStringSerializer.class)
private Long createTime;
/** 支付时间 */
@JsonSerialize(using = BeanJsonSerializer.LongDateToStringSerializer.class)
private Long payTime;
/** 关闭时间 */
@JsonSerialize(using = BeanJsonSerializer.LongDateToStringSerializer.class)
private Long cancelTime;
/** 支付方式 */
private String type;
/** 商户收款账号 */
private String mchId;
private String mainType;
/** 支付渠道 */
private String channel;
/** 失败原因 */
private String failReason;
private List<PayTypeVo> payTypeList;
}

View File

@ -7,13 +7,13 @@ import cn.hutool.json.JSONUtil;
import com.google.common.io.Files;
import com.niu.core.common.component.context.SpringContext;
import com.niu.core.common.component.context.WebAppEnvs;
import com.niu.core.common.config.GlobalConfig;
import com.niu.core.common.utils.file.AddonUpgradeHelper;
import com.niu.core.common.utils.file.FileTools;
import com.niu.core.common.utils.file.PipeNameUtils;
import com.niu.core.common.utils.json.JsonLoadUtils;
import com.niu.core.common.utils.system.LocalMavenTools;
import com.niu.core.common.utils.system.RuntimeTools;
import com.niu.core.common.config.GlobalConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
@ -45,7 +45,7 @@ public class AddonInstallJavaTools {
// 开发环境
WebAppEnvs webAppEnvs = WebAppEnvs.get();
String webRootDownAddon = webAppEnvs.projectNiucloudAddon;
String addonPomPath = webRootDownAddon + '/' + addonName + "/pom.xml";
String addonPomPath = webRootDownAddon + addonName + "/pom.xml";
// 存在pom.xml说明是源码安装
if (LocalMavenTools.existPomXmlFile(addonPomPath)) {
// ==========================================================================================//

View File

@ -243,8 +243,10 @@ public class CoreAddonInstallServiceImpl extends CoreAddonBaseService implements
this.installStep.add("installSql");
try {
String sqlContent = FileUtils.readFileToString(installSql, "UTF-8");
sqlContent = sqlContent.replace("{{prefix}}", GlobalConfig.tablePrefix);
SQLScriptRunnerTools.execScript(sqlContent);
if (!sqlContent.isEmpty()) {
sqlContent = sqlContent.replace("{{prefix}}", GlobalConfig.tablePrefix);
SQLScriptRunnerTools.execScript(sqlContent);
}
} catch (Exception e) {
throw new CommonException(e.getMessage());
}

View File

@ -1,11 +1,15 @@
package com.niu.core.service.core.app.tools;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ObjectUtil;
import com.niu.core.common.component.context.SpringContext;
import org.apache.ibatis.jdbc.ScriptRunner;
import org.springframework.jdbc.core.JdbcTemplate;
import java.io.*;
import java.io.File;
import java.io.FileReader;
import java.io.Reader;
import java.io.StringReader;
import java.sql.Connection;
public final class SQLScriptRunnerTools {
@ -38,6 +42,9 @@ public final class SQLScriptRunnerTools {
public static void execScript(Reader fileReader) {
JdbcTemplate jdbcTemplate = SpringContext.bean(JdbcTemplate.class);
String sql = IoUtil.read(fileReader);
if (ObjectUtil.hasEmpty(jdbcTemplate, sql)) {
return;
}
jdbcTemplate.execute(sql);
}

View File

@ -1,6 +1,7 @@
package com.niu.core.service.core.generator;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ClassLoaderUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
@ -641,7 +642,7 @@ public class CoreGenerateService {
public static MapperInfoVo getMapperInfo(String mapper) {
MapperInfoVo vo = new MapperInfoVo();
try {
Class<?> mapperClass = Class.forName(mapper);
Class<?> mapperClass = ClassLoaderUtil.loadClass(mapper);
if (!mapperClass.isInterface() || !mapperClass.isAnnotationPresent(Mapper.class)) {
throw new CommonException("提供的类不是有效的MyBatis Mapper接口");

View File

@ -3,6 +3,7 @@ package com.niu.core.service.core.member.impl;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import cn.hutool.core.util.ClassLoaderUtil;
import com.niu.core.common.utils.StringUtils;
import com.niu.core.common.utils.date.DateUtils;
import com.niu.core.entity.member.Member;
@ -130,7 +131,7 @@ public class CoreMemberServiceImpl implements ICoreMemberService {
JSONObject config = gifts.getJSONObject(key);
String driver = (String) giftEnum.getByPath(key + ".content." + scene + ".driver");
if (config.getInt("is_use") != null && config.getInt("is_use") > 0 && driver != null && !driver.isEmpty()) {
Class<?> clazz = Class.forName(driver);
Class<?> clazz = ClassLoaderUtil.loadClass(driver);
Object obj = clazz.getDeclaredConstructor().newInstance();
Method method = clazz.getMethod("content", Integer.class, JSONObject.class, String.class);
Object[] params = {siteId, config, scene};
@ -161,7 +162,7 @@ public class CoreMemberServiceImpl implements ICoreMemberService {
JSONObject config = benefits.getJSONObject(key);
String driver = (String) benefitsEnum.getByPath(key + ".content." + scene + ".driver");
if (config.getInt("is_use") != null && config.getInt("is_use") > 0 && driver != null && !driver.isEmpty()) {
Class<?> clazz = Class.forName(driver);
Class<?> clazz = ClassLoaderUtil.loadClass(driver);
Object obj = clazz.getDeclaredConstructor().newInstance();
Method method = clazz.getMethod("content", Integer.class, JSONObject.class, String.class);
Object[] params = {siteId, config, scene};
@ -192,7 +193,7 @@ public class CoreMemberServiceImpl implements ICoreMemberService {
JSONObject config = rules.getJSONObject(key);
String driver = (String) growthRuleEnum.getByPath(key + ".content." + scene + ".driver");
if (config.getInt("is_use") != null && config.getInt("is_use") > 0 && driver != null && !driver.isEmpty()) {
Class<?> clazz = Class.forName(driver);
Class<?> clazz = ClassLoaderUtil.loadClass(driver);
Object obj = clazz.getDeclaredConstructor().newInstance();
Method method = clazz.getMethod("content", Integer.class, JSONObject.class, String.class);
Object[] params = {siteId, config, scene};
@ -223,7 +224,7 @@ public class CoreMemberServiceImpl implements ICoreMemberService {
JSONObject config = rules.getJSONObject(key);
String driver = (String) pointRuleEnum.getByPath(key + ".content." + scene + ".driver");
if (config.getInt("is_use") != null && config.getInt("is_use") > 0 && driver != null && !driver.isEmpty()) {
Class<?> clazz = Class.forName(driver);
Class<?> clazz = ClassLoaderUtil.loadClass(driver);
Object obj = clazz.getDeclaredConstructor().newInstance();
Method method = clazz.getMethod("content", Integer.class, JSONObject.class, String.class);
Object[] params = {siteId, config, scene};
@ -254,7 +255,7 @@ public class CoreMemberServiceImpl implements ICoreMemberService {
JSONObject config = rules.getJSONObject(key);
String driver = (String) pointRuleEnum.getByPath(key + ".content." + scene + ".driver");
if (config.getInt("is_use") != null && config.getInt("is_use") > 0 && driver != null && !driver.isEmpty()) {
Class<?> clazz = Class.forName(driver);
Class<?> clazz = ClassLoaderUtil.loadClass(driver);
Object obj = clazz.getDeclaredConstructor().newInstance();
Method method = clazz.getMethod("content", Integer.class, JSONObject.class, String.class);
Object[] params = {siteId, config, scene};
@ -290,7 +291,7 @@ public class CoreMemberServiceImpl implements ICoreMemberService {
if (driver.isEmpty()) return;
try {
Class<?> clazz = Class.forName(driver);
Class<?> clazz = ClassLoaderUtil.loadClass(driver);
Object obj = clazz.getDeclaredConstructor().newInstance();
Method method = clazz.getMethod("calculate", Integer.class, String.class, JSONObject.class, Map.class);
Object[] params = {siteId, key, config, data};
@ -327,7 +328,7 @@ public class CoreMemberServiceImpl implements ICoreMemberService {
if (driver.isEmpty()) return;
try {
Class<?> clazz = Class.forName(driver);
Class<?> clazz = ClassLoaderUtil.loadClass(driver);
Object obj = clazz.getDeclaredConstructor().newInstance();
Method method = clazz.getMethod("calculate", Integer.class, String.class, JSONObject.class, Map.class);
Object[] params = {siteId, key, config, data};
@ -360,7 +361,7 @@ public class CoreMemberServiceImpl implements ICoreMemberService {
JSONObject config = gifts.getJSONObject(key);
String driver = (String) giftEnum.getByPath(key + ".grant.driver");
if (config.getInt("is_use") != null && config.getInt("is_use") > 0 && driver != null && !driver.isEmpty()) {
Class<?> clazz = Class.forName(driver);
Class<?> clazz = ClassLoaderUtil.loadClass(driver);
Object obj = clazz.getDeclaredConstructor().newInstance();
Method method = clazz.getMethod("grant", Integer.class, Integer.class, JSONObject.class, Map.class);
Object[] params = {siteId, memberId, config, vars};

View File

@ -1,13 +1,17 @@
package com.niu.core.service.core.pay;
import com.niu.core.common.loader.pay.BasePay;
import com.niu.core.entity.pay.Pay;
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.PayNotifyParam;
import com.niu.core.common.loader.pay.param.PayParam;
import com.niu.core.entity.pay.Pay;
import com.niu.core.enums.common.ChannelEnum;
import com.niu.core.service.core.pay.vo.GetInfoByTradeVo;
import com.niu.core.service.core.pay.vo.PayTypeVo;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
* 支付记录服务接口
@ -18,6 +22,8 @@ public interface ICorePayService {
BasePay driver(Integer siteId, String channel, String type);
GetInfoByTradeVo getInfoByTrade(Integer siteId, String tradeType, Integer tradeId, String channel, String scene);
Pay findPayInfoByTrade(Integer siteId, String tradeType, Integer tradeId);
Pay findPayInfoByOutTradeNo(Integer siteId, String outTradeNo);
@ -31,4 +37,6 @@ public interface ICorePayService {
String buildNotifyUrl(Integer siteId, String channel, String type, String action);
void closeByTrade(Integer siteId, String tradeType, Integer tradeId);
List<PayTypeVo> getPayTypeByTrade(Integer siteId, String tradeType, ChannelEnum channel);
}

View File

@ -48,7 +48,7 @@ public class Balancepay extends BasePay {
// 扣除账户余额
Pay pay = param.getPay();
String memo = MemberAccountChangeTypeEnum.getType(AccountTypeEnum.BALANCE.getType()).getByPath("order.name", String.class);
coreMemberAccountService().addLog(param.getSiteId(), param.getBuyerId(), AccountTypeEnum.BALANCE.getType(), pay.getMoney().negate().doubleValue(), "order", memo, pay.getOutTradeNo());
coreMemberAccountService().addLog(param.getSiteId(), param.getPay().getMainId(), AccountTypeEnum.BALANCE.getType(), pay.getMoney().negate().doubleValue(), "order", memo, pay.getOutTradeNo());
PayNotifyParam notifyParam = new PayNotifyParam();
notifyParam.setSiteId(param.getSiteId());

View File

@ -0,0 +1,60 @@
package com.niu.core.service.core.pay.driver;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.niu.core.common.loader.pay.BasePay;
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.RefundParam;
import com.niu.core.common.loader.pay.param.TransferParam;
import com.niu.core.entity.pay.Pay;
import com.niu.core.enums.pay.PayTypeEnum;
import com.niu.core.service.core.pay.vo.PayTypeVo;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class FriendPay extends BasePay {
@Override
public BasePay init(JSONObject config) {
return this;
}
@Override
public Object pay(PayParam param) {
return null;
}
@Override
public void scan() {
}
@Override
public void close(Pay pay) {
}
@Override
public Object asyncNotify(PayAsyncNotifyParam param, HttpServletRequest request, HttpServletResponse response) {
return null;
}
@Override
public void transfer(TransferParam param) {
}
@Override
public void refund(RefundParam param) {
}
@Override
public PayTypeVo filterPayTypeByTradeType(String tradeType) {
return JSONUtil.toBean(PayTypeEnum.getType().getJSONObject("friendspay"), PayTypeVo.class);
}
}

View File

@ -6,15 +6,14 @@ import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.niu.core.entity.pay.PayChannel;
import com.niu.core.mapper.pay.PayChannelMapper;
import com.niu.core.service.core.pay.vo.PayTypeVo;
import com.niu.core.service.core.pay.ICorePayChannelService;
import com.niu.core.service.core.pay.ICorePayService;
import com.niu.core.service.core.pay.param.PayChannelSearchParam;
import com.niu.core.service.core.pay.vo.PayTypeVo;
import com.niu.core.service.core.weapp.ICoreWeappConfigService;
import com.niu.core.service.core.weapp.vo.WeappConfigVo;
import com.niu.core.service.core.wechat.ICoreWechatConfigService;
import com.niu.core.service.core.wechat.vo.WechatConfigVo;
import org.hibernate.validator.constraints.EAN;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
@ -74,7 +73,10 @@ public class CorePayChannelServiceImpl implements ICorePayChannelService {
for (PayChannel item : payChannelList) {
if (item.getConfig().isEmpty()) continue;
PayTypeVo type = corePayService.driver(siteId, channel, item.getType()).filterPayTypeByTradeType(tradeType);
if (type != null) list.add(type);
if (type != null) {
type.setConfig(item.getConfig());
list.add(type);
}
}
return list;

View File

@ -6,6 +6,7 @@ import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
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.component.context.cache.Cached;
import com.niu.core.common.exception.CommonException;
@ -16,6 +17,7 @@ import com.niu.core.common.loader.pay.param.PayNotifyParam;
import com.niu.core.common.loader.pay.param.PayParam;
import com.niu.core.common.utils.RequestUtils;
import com.niu.core.entity.pay.Pay;
import com.niu.core.enums.common.ChannelEnum;
import com.niu.core.enums.pay.OnliepayStatusEnum;
import com.niu.core.enums.pay.PayStatusEnum;
import com.niu.core.event.pay.PayCloseEvent;
@ -25,6 +27,8 @@ import com.niu.core.mapper.pay.PayMapper;
import com.niu.core.service.core.app.helper.EventAndSubscribeOfPublisher;
import com.niu.core.service.core.pay.ICorePayChannelService;
import com.niu.core.service.core.pay.ICorePayService;
import com.niu.core.service.core.pay.vo.GetInfoByTradeVo;
import com.niu.core.service.core.pay.vo.PayTypeVo;
import com.niu.core.service.core.sys.ICorePrinterService;
import com.niu.core.service.core.sys.param.SysPrinterPrintTicketParam;
import org.springframework.stereotype.Service;
@ -150,6 +154,31 @@ public class CorePayServiceImpl implements ICorePayService {
return PayLoader.getDriver(type).init(config);
}
@Override
public GetInfoByTradeVo getInfoByTrade(Integer siteId, String tradeType, Integer tradeId, String channel, String scene) {
Pay pay = findPayInfoByTrade(siteId, tradeType, tradeId);
if (pay == null) {
pay = createByTrade(siteId, tradeType, tradeId);
}
GetInfoByTradeVo vo = new GetInfoByTradeVo();
BeanUtil.copyProperties(pay, vo);
List<PayTypeVo> payTypeList = corePayChannelService.getAllowPayTypeByChannel(siteId, channel, tradeType);
vo.setPayTypeList(payTypeList);
if (ObjectUtil.isNotEmpty(payTypeList) && ObjectUtil.equals(scene, "friendspay")) {
payTypeList.stream()
.filter(pt -> pt.getKey().equals("friendspay"))
.findFirst()
.ifPresent(payTypeVo -> vo.setConfig(JSONUtil.parseObj(payTypeVo.getConfig())));
vo.setPayTypeList(payTypeList.stream().filter(pt -> !pt.getKey().equals("friendspay")).toList());
}
return vo;
}
/**
* 通过业务类型和id查询有效的支付单据
*
@ -274,7 +303,6 @@ public class CorePayServiceImpl implements ICorePayService {
payMapper.updateById(pay);
}
/**
* 关闭支付
*
@ -331,4 +359,10 @@ public class CorePayServiceImpl implements ICorePayService {
this.close(siteId, pay);
}
}
@Override
public List<PayTypeVo> getPayTypeByTrade(Integer siteId, String tradeType, ChannelEnum channel) {
return corePayChannelService.getAllowPayTypeByChannel(siteId, channel.getCode(), tradeType);
}
}

View File

@ -0,0 +1,121 @@
package com.niu.core.service.core.pay.vo;
import cn.hutool.json.JSONObject;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.niu.core.common.domain.BeanJsonSerializer;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
@Data
public class GetInfoByTradeVo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
private Integer id;
/**
* 站点id
*/
private Integer siteId;
/**
* 支付会员id
*/
private Integer mainId;
/**
* 支付流水号
*/
private String outTradeNo;
/**
* 业务类型
*/
private String tradeType;
/**
* 业务id
*/
private Integer tradeId;
/**
* 交易单号
*/
private String tradeNo;
/**
* 支付主体
*/
private String body;
/**
* 支付金额
*/
private BigDecimal money;
/**
* 支付票据
*/
private String voucher;
/**
* 支付状态0.待支付 1. 支付中 2. 已支付 -1已取消
*/
private Integer status;
/**
* 支付扩展用支付信息
*/
private String json;
/**
* 创建时间
*/
@JsonSerialize(using = BeanJsonSerializer.LongDateToStringSerializer.class)
private Long createTime;
/**
* 支付时间
*/
@JsonSerialize(using = BeanJsonSerializer.LongDateToStringSerializer.class)
private Long payTime;
/**
* 关闭时间
*/
@JsonSerialize(using = BeanJsonSerializer.LongDateToStringSerializer.class)
private Long cancelTime;
/**
* 支付方式
*/
private String type;
/**
* 商户收款账号
*/
private String mchId;
private String mainType;
/**
* 支付渠道
*/
private String channel;
/**
* 失败原因
*/
private String failReason;
private List<PayTypeVo> payTypeList;
private JSONObject config;
}

View File

@ -14,4 +14,6 @@ public class PayTypeVo implements Serializable {
private String icon;
private String name;
private String config;
}

View File

@ -10,7 +10,6 @@ import java.util.Map;
/**
* 导出服务器底层
*
*/
public interface ICoreExportService {
@ -27,7 +26,7 @@ public interface ICoreExportService {
* @param exportId
* @param sysExportParam
*/
void edit(Integer exportId,SysExportParam sysExportParam);
void edit(Integer exportId, SysExportParam sysExportParam);
/**
* 获取导出数据类型列表
@ -63,7 +62,7 @@ public interface ICoreExportService {
* @param dataColumn
* @param data
*/
void export(Integer siteId, String dataKey, JSONArray dataColumn, JSONArray data);
void export(Integer siteId, Integer exportId, String dataKey, JSONArray dataColumn, JSONArray data);
/**
* 删除导出报表文件

View File

@ -1,8 +1,11 @@
package com.niu.core.service.core.sys.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.niu.core.common.component.context.WebAppEnvs;
import com.niu.core.common.domain.PageParam;
import com.niu.core.common.utils.Export.BusinessExcelUtil;
@ -16,6 +19,7 @@ import com.niu.core.mapper.sys.SysExportMapper;
import com.niu.core.service.core.app.helper.EventAndSubscribeOfPublisher;
import com.niu.core.service.core.sys.ICoreExportService;
import com.niu.core.service.core.sys.param.SysExportParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
@ -25,17 +29,16 @@ import java.util.*;
/**
* 导出服务层
*
*/
@Slf4j
@Service
public class CoreExportServiceImpl implements ICoreExportService {
@Resource
SysExportMapper sysExportMapper;
/**
* 添加导出记录
*
* @param sysExport
*/
@Override
@Transactional
@ -45,13 +48,10 @@ public class CoreExportServiceImpl implements ICoreExportService {
/**
* 编辑导出记录
*
* @param exportId
* @param sysExportParam
*/
@Override
public void edit(Integer exportId, SysExportParam sysExportParam) {
SysExport sysExport=sysExportMapper.selectById(exportId);
SysExport sysExport = sysExportMapper.selectById(exportId);
Assert.notNull(sysExport, "数据不存在");
@ -66,42 +66,33 @@ public class CoreExportServiceImpl implements ICoreExportService {
/**
* 获取导出数据类型列表
*
* @return
*/
@Override
public Map<String, String> getExportDataType() {
Map<String, String> dataType=new HashMap<>();
JSONArray jsonArray=JsonModuleLoader.build().mergeResultSet("export/ExportType.json");
for (Object obj:jsonArray) {
JSONObject jsonObject=(JSONObject) obj;
Set<String> setString=jsonObject.keySet();
for (String key: setString) {
JSONObject values=jsonObject.getJSONObject(key);
dataType.put(key, values.getStr("name"));
}
Map<String, String> map = new HashMap<>();
for (Object res : JsonModuleLoader.build().mergeResultSet("export/ExportType.json")) {
JSONObject result = JSONUtil.parseObj(res);
result.keySet().forEach(key -> map.put(key, result.getJSONObject(key).getStr("name")));
}
return dataType;
return map;
}
/**
* 获取导出数据列
*
* @param type
* @return
*/
@Override
public JSONArray getExportDataColumn(String type) {
JSONArray exportDataColumn=JsonModuleLoader.build().mergeResultSet("export/ExportType.json");
if(ObjectUtil.isNotNull(type) && ObjectUtil.isNotEmpty(type)){
JSONArray typeColumn=new JSONArray();
for (Object obj:exportDataColumn) {
JSONObject jsonObject=(JSONObject) obj;
Set<String> setString=jsonObject.keySet();
for (String key: setString) {
if(key.equals(type)){
JSONObject values=jsonObject.getJSONObject(key);
typeColumn=values.getJSONArray("column");
JSONArray exportDataColumn = JsonModuleLoader.build().mergeResultSet("export/ExportType.json");
if (ObjectUtil.isNotNull(type) && ObjectUtil.isNotEmpty(type)) {
JSONArray typeColumn = new JSONArray();
for (Object obj : exportDataColumn) {
JSONObject jsonObject = (JSONObject) obj;
Set<String> setString = jsonObject.keySet();
for (String key : setString) {
if (key.equals(type)) {
JSONObject values = jsonObject.getJSONObject(key);
typeColumn = values.getJSONArray("column");
}
}
}
@ -112,24 +103,18 @@ public class CoreExportServiceImpl implements ICoreExportService {
/**
* 获取导出数据源
*
* @param siteId
* @param type
* @param where
* @param pageParam
* @return
*/
@Override
public JSONArray getExportData(Integer siteId, String type, JSONObject where, PageParam pageParam) {
ExportDataEventDefiner.ExportDataEvent exportDataEvent=new ExportDataEventDefiner.ExportDataEvent();
ExportDataEventDefiner.ExportDataEvent exportDataEvent = new ExportDataEventDefiner.ExportDataEvent();
exportDataEvent.setSiteId(siteId);
exportDataEvent.setType(type);
exportDataEvent.setWhere(where);
exportDataEvent.setPageParam(pageParam);
List<ExportDataEventDefiner.ExportDataEventResult> resultList= EventAndSubscribeOfPublisher.publishAndCallback(exportDataEvent);
JSONArray exportResult=new JSONArray();
for (ExportDataEventDefiner.ExportDataEventResult itemResult:resultList){
if(itemResult.getResultData().size()>0){
List<ExportDataEventDefiner.ExportDataEventResult> resultList = EventAndSubscribeOfPublisher.publishAndCallback(exportDataEvent);
JSONArray exportResult = new JSONArray();
for (ExportDataEventDefiner.ExportDataEventResult itemResult : resultList) {
if (ObjectUtil.isNotEmpty(itemResult.getResultData())) {
exportResult.addAll(itemResult.getResultData());
}
}
@ -138,52 +123,55 @@ public class CoreExportServiceImpl implements ICoreExportService {
/**
* 导出数据
*
* @param siteId
* @param dataType
* @param headColumn
* @param valueData
*/
@Override
public void export(Integer siteId, String dataType, JSONArray headColumn, JSONArray valueData) {
ExportDynamic exportDynamic=new ExportDynamic();
String fileName=dataType+"_"+ DateUtils.currTime()+".xlsx";
public void export(Integer siteId, Integer exportId, String dataType, JSONArray headColumn, JSONArray valueData) {
ExportDynamic exportDynamic = new ExportDynamic();
String fileName = dataType + "_" + DateUtils.currTime() + ".xlsx";
String relativePath = "upload/export/";
exportDynamic.setFileName(fileName);
String filePath=WebAppEnvs.get().webRootDownResource+"/upload"+"/export/";
String filePath = WebAppEnvs.get().webRootDownResource + relativePath;
exportDynamic.setFilePath(filePath);
List<ExportHeads> headsList=new ArrayList<>();
List<String> keyList=new ArrayList<>();
for (Object headObj: headColumn) {
JSONObject itemObject=(JSONObject) headObj;
String itemKey=itemObject.keySet().stream().iterator().next();
JSONObject itemValue=itemObject.getJSONObject(itemKey);
String titleHead=itemValue.getStr("name");
ExportHeads exportHeads=new ExportHeads();
List<ExportHeads> headsList = new ArrayList<>(CollectionUtil.size(headColumn));
List<String> keyList = new ArrayList<>(CollectionUtil.size(headColumn));
for (Object headObj : headColumn) {
JSONObject itemObject = (JSONObject) headObj;
String itemKey = itemObject.keySet().stream().iterator().next();
JSONObject itemValue = itemObject.getJSONObject(itemKey);
String titleHead = itemValue.getStr("name");
ExportHeads exportHeads = new ExportHeads();
exportHeads.setLabel(titleHead);
headsList.add(exportHeads);
keyList.add(itemKey);
}
exportDynamic.setHeads(headsList);
List<List<Object>> datas=new ArrayList<>();
for (Object itemObj: valueData) {
JSONObject itemJsonObject=(JSONObject) itemObj;
List<Object> itemDatas=new ArrayList<>();
for (String itemKey:keyList) {
List<List<Object>> datas = new ArrayList<>(CollectionUtil.size(valueData));
for (Object itemObj : valueData) {
JSONObject itemJsonObject = (JSONObject) itemObj;
List<Object> itemDatas = new ArrayList<>();
for (String itemKey : keyList) {
itemDatas.add(itemJsonObject.getStr(itemKey, ""));
}
datas.add(itemDatas);
}
exportDynamic.setDatas(datas);
BusinessExcelUtil.exportBusinessExcel(exportDynamic);
exportDynamic.setRelativePath(relativePath);
BusinessExcelUtil.exportBusinessExcel(exportId, exportDynamic);
}
/**
* 删除导出报表文件
*
* @param filePath
*/
@Override
public void deleteExportFile(String filePath) {
String path = WebAppEnvs.get().webRootDownResource + filePath;
if (!FileUtil.exist(path)) {
return;
}
boolean del = FileUtil.del(path);
if (!del && log.isInfoEnabled()) {
log.info("报表删除失败");
}
}
}

View File

@ -0,0 +1,11 @@
package com.niu.core.service.core.weapp;
import java.io.File;
import java.util.Map;
public interface ICoreWeappService {
byte[] qrcodeBytes(Integer siteId, String page, Map<String, Object> data, Integer width);
File qrcodeFile(Integer siteId, String filePath, String page, Map<String, Object> data, Integer width);
}

View File

@ -0,0 +1,62 @@
package com.niu.core.service.core.weapp.impl;
import com.niu.core.common.exception.CommonException;
import com.niu.core.common.utils.WechatUtils;
import com.niu.core.service.core.weapp.ICoreWeappService;
import org.springframework.stereotype.Service;
import java.io.File;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@Service
public class CoreWeappServiceImpl implements ICoreWeappService {
@Override
public byte[] qrcodeBytes(Integer siteId, String page, Map<String, Object> data, Integer width) {
try {
List<String> scene = new LinkedList<>();
for (String key : data.keySet()) {
scene.add(data.get(key) + "-" + data.get(key).toString());
}
return WechatUtils.miniapp(siteId).getQrcodeService().createWxaCodeUnlimitBytes(
String.join("&", scene),
page,
false,
"release",
width,
false,
null,
false
);
} catch (Exception e) {
throw new CommonException(e.getMessage());
}
}
@Override
public File qrcodeFile(Integer siteId, String filePath, String page, Map<String, Object> data, Integer width) {
try {
List<String> scene = new LinkedList<>();
for (String key : data.keySet()) {
scene.add(data.get(key) + "-" + data.get(key).toString());
}
return WechatUtils.miniapp(siteId).getQrcodeService().createWxaCodeUnlimit(
String.join("&", scene),
page,
filePath,
false,
"release",
width,
false,
null,
false
);
} catch (Exception e) {
throw new CommonException(e.getMessage());
}
}
}

View File

@ -0,0 +1,13 @@
package com.niu.core.upgrade.v003;
import com.niu.core.common.component.upgrade.IUpgradeProvider;
import com.niu.core.common.component.upgrade.annotation.UpgradeProvider;
@UpgradeProvider(addon = "core", version = "0.0.3")
public class Upgrade extends IUpgradeProvider {
@Override
public void handle() {
System.out.println("core 0.0.3");
}
}

View File

@ -0,0 +1,2 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.niu.core.common.config.executable.initialize.CoreApplicationRunner

View File

@ -19,5 +19,12 @@
"icon": "static/resource/icon/pay_icon/balancepay.png",
"setting_component": "",
"driver": "com.niu.core.service.core.pay.driver.Balancepay"
},
"friendspay": {
"name": "找朋友帮忙付",
"key": "friendspay",
"icon": "static/resource/icon/pay_icon/friendspay.png",
"setting_component": "/src/app/views/setting/components/pay-friendspay.vue",
"driver": "com.niu.core.service.core.pay.driver.FriendPay"
}
}

View File

@ -0,0 +1,169 @@
[
{
"name": "找朋友帮忙付模板",
"type": "friendspay",
"data": {
"global": {
"width": 720,
"height": 1280,
"bgType": "url",
"bgColor": "#ffffff",
"bgUrl": "static/resource/images/pay/friendspay_bg.jpg"
},
"value": [
{
"type": "text",
"path": "text",
"uses": 0,
"relate": "",
"value": "您的帮付金额",
"id": "wgvspr9fafk",
"componentName": "Text",
"componentTitle": "文本",
"width": 518,
"height": 48,
"minWidth": 120,
"minHeight": 44,
"x": "center",
"y": 759,
"angle": 0,
"zIndex": 8,
"fontFamily": "static/font/SourceHanSansCN-Regular.ttf",
"fontSize": 24,
"weight": false,
"lineHeight": 20,
"fontColor": "#333333"
},
{
"type": "text",
"path": "friendspay-money",
"uses": 1,
"relate": "friendspay_money",
"value": "¥369.00",
"id": "2waud25nthq0",
"componentName": "FriendsPayMoney",
"componentTitle": "帮付金额",
"width": 518,
"height": 58,
"minWidth": 120,
"minHeight": 44,
"x": "center",
"y": 694,
"angle": 0,
"zIndex": 9,
"fontFamily": "static/font/price.ttf",
"fontSize": 56,
"weight": false,
"lineHeight": 10,
"fontColor": "#FF4142"
},
{
"type": "text",
"path": "text",
"uses": 0,
"relate": "",
"value": "长按识别二维码,帮我付款",
"id": "639vjo8ebo40",
"componentName": "Text",
"componentTitle": "文本",
"width": 518,
"height": 59,
"minWidth": 120,
"minHeight": 44,
"x": "center",
"y": 1097,
"angle": 0,
"zIndex": 10,
"fontFamily": "static/font/SourceHanSansCN-Regular.ttf",
"fontSize": 26,
"weight": false,
"lineHeight": 26,
"fontColor": "#333333"
},
{
"type": "text",
"path": "friendspay-message",
"uses": 1,
"relate": "friendspay_message",
"value": "帮我付一下这笔订单吧,谢谢啦~",
"id": "5oyikcgoylo0",
"componentName": "FriendsPayMessage",
"componentTitle": "帮付留言",
"width": 600,
"height": 48,
"minWidth": 120,
"minHeight": 44,
"x": "center",
"y": 570,
"angle": 0,
"zIndex": 4,
"fontFamily": "static/font/SourceHanSansCN-Regular.ttf",
"fontSize": 26,
"weight": false,
"lineHeight": 10,
"fontColor": "#666666"
},
{
"type": "qrcode",
"path": "qrcode",
"uses": 1,
"relate": "url",
"value": "",
"id": "3m6szk6d98m0",
"componentName": "Qrcode",
"componentTitle": "二维码",
"width": 214,
"height": 214,
"minWidth": 60,
"minHeight": 60,
"x": 254,
"y": 844,
"angle": 0,
"zIndex": 8
},
{
"type": "text",
"path": "nickname",
"uses": 1,
"relate": "nickname",
"value": "",
"id": "31wsjudfc7m0",
"componentName": "NickName",
"componentTitle": "昵称",
"width": 600,
"height": 40,
"minWidth": 120,
"minHeight": 50,
"x": "center",
"y": 512,
"angle": 0,
"zIndex": 6,
"fontFamily": "static/font/SourceHanSansCN-Regular.ttf",
"fontSize": 30,
"weight": false,
"lineHeight": 10,
"fontColor": "#303133"
},
{
"type": "image",
"path": "headimg",
"uses": 1,
"relate": "headimg",
"value": "",
"id": "5asgzwz9f5s0",
"componentName": "HeadImg",
"componentTitle": "头像",
"width": 149,
"height": 149,
"minWidth": 60,
"minHeight": 60,
"x": 286,
"y": 344,
"angle": 0,
"zIndex": 7,
"shape": "circle"
}
]
}
}
]

View File

@ -0,0 +1,4 @@
ALTER TABLE `{{prefix}}pay` ADD COLUMN `from_main_id` INT(11) NOT NULL DEFAULT 0 COMMENT '发起支付会员id';
ALTER TABLE `{{prefix}}pay` MODIFY `from_main_id` INT(11) NOT NULL DEFAULT 0 COMMENT '发起支付会员id' AFTER `main_id`;

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

View File

@ -418,6 +418,7 @@ public class ProjectCompileAndBuildTools {
/**
* 排除目录
*
* @param dirs
* @return
*/

View File

@ -24,7 +24,7 @@ spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/***?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai
username: root
password:
password:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
druid:

View File

@ -24,7 +24,7 @@ spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/***?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai
username: root
password:
password:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
druid:

View File

@ -1,6 +1,6 @@
NODE_ENV = 'development'
# api请求地址
# api请求地址
VITE_APP_BASE_URL = ''
# 图片服务器地址

View File

@ -1,4 +1,26 @@
const fs = require('fs')
const { spawn } = require('child_process');
const path = require('path');
const main = () => {
const params = process.argv.slice(2) || []
const port = params[0] || ''
const mode = params[1] || ''
switch (port) {
case 'h5':
publish()
break;
case 'mp-weixin':
if (mode == 'build') {
handleWeappAddonComponents(mode)
handleWeappLanguage(mode)
} else if (mode == 'dev') {
listenWeappRunDev()
}
break;
}
}
const publish = () => {
const src = './dist/build/h5'
@ -48,4 +70,52 @@ const solve = () => {
})
}
publish()
const handleWeappAddonComponents = (mode) => {
const src = `./dist/${mode}/mp-weixin/addon/components/diy/group/index.json`
try {
const data = JSON.parse(fs.readFileSync(src, 'utf8'));
data.componentPlaceholder = {};
Object.keys(data.usingComponents).map(key => {
data.componentPlaceholder[key] = "view";
})
fs.writeFileSync(src, JSON.stringify(data))
} catch (err) {
}
}
const handleWeappLanguage = (mode) => {
const src = `./dist/${mode}/mp-weixin/locale/language.js`
try {
let content = fs.readFileSync(src, 'utf8');
content = content.replace(/Promise\.resolve\(require\(("[^"]+")\)\)/g, 'require.async($1)')
fs.writeFileSync(src, content)
} catch (err) {
console.log(err)
}
}
const listenWeappRunDev = () => {
const devProcess = spawn('npm', ['run', 'dev:niu-mp-weixin'], {
stdio: ['pipe', 'pipe', 'pipe'],
shell: true
});
let serverReady = false;
// 监听 stdout 输出
devProcess.stdout.on('data', (data) => {
const message = data.toString();
console.log(message)
if (!serverReady && message.includes('DONE Build complete')) {
serverReady = true;
handleWeappAddonComponents('dev')
handleWeappLanguage('dev')
}
});
}
main()

View File

@ -75,6 +75,7 @@
<diy-picture-show :component="component" :global="data.global" :index="index"
:pullDownRefreshCount="props.pullDownRefreshCount" />
</template>
</view>
</view>
<template v-if="diyStore.mode == '' && data.global.bottomTabBarSwitch">
@ -84,6 +85,7 @@
</view>
</template>
<script lang="ts" setup>
import topTabbar from '@/components/top-tabbar/top-tabbar.vue'
import { useDiyGroup } from './useDiyGroup'
import useDiyStore from '@/app/stores/diy';

View File

@ -0,0 +1,8 @@
import request from '@/utils/request'
/**
*
*/
export function getFriendspayInfo(tradeType: string, tradeId: number) {
return request.get(`pay/friendspay/info/${tradeType}/${tradeId}`, {}, {showErrorMessage: true})
}

View File

@ -3,13 +3,13 @@ import request from '@/utils/request'
/**
*
*/
export function pay(data : AnyObject) {
return request.post(`pay`, data, { showErrorMessage: true })
export function pay(data: AnyObject) {
return request.post(`pay`, data, {showErrorMessage: true})
}
/**
*
*/
export function getPayInfo(tradeType : string, tradeId : number) {
return request.get(`pay/info/${tradeType}/${tradeId}`, {}, { showErrorMessage: true })
export function getPayInfo(tradeType: string, tradeId: number, params: Record<string, any>) {
return request.get(`pay/info/${tradeType}/${tradeId}`, params, {showErrorMessage: true})
}

View File

@ -0,0 +1,11 @@
{
"payMoney":"实付金额",
"help":"帮",
"pay":"付款",
"helpPayInfo":"帮付订单信息",
"common": "共",
"goods":"种商品",
"finish":"该订单已完成",
"close":"该订单已关闭",
"payGenerously":"找朋友帮忙付"
}

View File

@ -0,0 +1,9 @@
{
"payMoney": "实付金额",
"friendPayOrderInfo": "帮付订单信息",
"common": "共",
"goods": "种商品",
"finish": "该订单已完成",
"close": "该订单已关闭",
"friendPay": "找朋友帮忙付"
}

View File

@ -69,11 +69,11 @@
<button class="w-[630rpx] h-[88rpx] !mx-[0] !bg-[#fff] !border-[var(--primary-color)] border-solid border-[2rpx] text-[26rpx] rounded-[44rpx] leading-[84rpx] !text-[var(--primary-color)]" @click="redirect({ url: '/app/pages/auth/login',param:{type:'username'}})">{{t('accountLogin')}}</button>
</view>
<view v-if="loginConfig.agreement_show" class="w-full flex items-center justify-center mt-[28rpx]">
<view class="flex items-center justify-center mt-[28rpx] py-[10rpx]" @click.stop="agreeChange">
<view class="flex items-center justify-center mt-[28rpx] py-[14rpx] px-[50rpx]" @click.stop="agreeChange">
<u-checkbox-group @change="agreeChange">
<u-checkbox activeColor="var(--primary-color)" :checked="isAgree" shape="circle" size="26rpx" :customStyle="{ 'marginTop': '5rpx !important' }" />
<u-checkbox activeColor="var(--primary-color)" :checked="isAgree" shape="circle" size="30rpx" />
</u-checkbox-group>
<view class="text-[24rpx] text-[var(--text-color-light6)] flex items-center flex-wrap">
<view class="text-[24rpx] text-[var(--text-color-light6)] flex items-center flex-wrap leading-[30rpx]">
<text>{{ t('agreeTips') }}</text>
<text @click.stop="redirect({ url: '/app/pages/auth/agreement?key=privacy' })" class="text-primary">{{t('privacyAgreement')}}</text>
<text>{{ t('and') }}</text>
@ -85,7 +85,7 @@
<view class="footer w-full" v-if="loginConfig.is_mobile && loginConfig.is_username">
<view class="text-[26rpx] leading-[36rpx] text-[333] text-center mb-[30rpx] font-400">{{t('otherLogin')}}</view>
<view class="flex justify-center">
<view class="h-[80rpx] w-[80rpx] text-center leading-[78rpx] border-[2rpx] text-primary rounded-[50%] border-solid border-[#ddd] nc-iconfont nc-icon-a-wodeV6xx-36 text-[46rpx] overflow-hidden" @click="redirect({ url: '/app/pages/auth/login',param:{type:'username'}})"></view>
<view class="h-[80rpx] w-[80rpx] text-center leading-[78rpx] border-[2rpx] text-[#FF7100] rounded-[50%] border-solid border-[#ddd] nc-iconfont nc-icon-wodeV6mm3 text-[46rpx] overflow-hidden" @click="redirect({ url: '/app/pages/auth/login',param:{type:'username'}})"></view>
</view>
<view class="text-[24rpx] leading-[36rpx] text-[var(--text-color-light9)] text-center font-400 mt-[30rpx]">{{t('accountLogin')}}</view>
</view>

View File

@ -47,11 +47,11 @@
</u-form>
<view v-if="type == 'username'" class="text-right text-[24rpx] text-[var(--text-color-light9)] leading-[34rpx] mt-[20rpx]" @click="redirect({ url: '/app/pages/auth/resetpwd' })">{{t('resetpwd')}}</view>
<view :class="{'mt-[160rpx]':type != 'username','mt-[106rpx]':type == 'username'}">
<view v-if="configStore.login.agreement_show" class="flex items-center mb-[20rpx] py-[10rpx]" @click.stop="agreeChange">
<view v-if="configStore.login.agreement_show" class="flex items-center mb-[20rpx] py-[14rpx]" @click.stop="agreeChange">
<u-checkbox-group @change="agreeChange">
<u-checkbox activeColor="var(--primary-color)" :checked="isAgree" shape="circle" size="24rpx" :customStyle="{ 'marginTop': '4rpx' }"/>
<u-checkbox activeColor="var(--primary-color)" :checked="isAgree" shape="circle" size="30rpx"/>
</u-checkbox-group>
<view class="text-[24rpx] text-[var(--text-color-light6)] flex items-center flex-wrap">
<view class="text-[24rpx] text-[var(--text-color-light6)] flex items-center flex-wrap leading-[30rpx]">
<text>{{ t('agreeTips') }}</text>
<text @click.stop="redirect({ url: '/app/pages/auth/agreement?key=privacy' })" class="text-primary">{{t('privacyAgreement')}}</text>
<text>{{ t('and') }}</text>

View File

@ -68,11 +68,11 @@
</template>
</u-form>
<view class="mt-[160rpx]">
<view v-if="configStore.login.agreement_show" class="flex items-center mb-[20rpx] py-[10rpx]" @click.stop="agreeChange">
<view v-if="configStore.login.agreement_show" class="flex items-center mb-[20rpx] py-[14rpx]" @click.stop="agreeChange">
<u-checkbox-group @change="agreeChange">
<u-checkbox activeColor="var(--primary-color)" :checked="isAgree" shape="circle" size="24rpx" :customStyle="{ 'marginTop': '4rpx' }" />
<u-checkbox activeColor="var(--primary-color)" :checked="isAgree" shape="circle" size="30rpx" />
</u-checkbox-group>
<view class="text-[24rpx] text-[var(--text-color-light6)] flex items-center flex-wrap">
<view class="text-[24rpx] text-[var(--text-color-light6)] flex items-center flex-wrap leading-[30rpx]">
<text>{{ t('agreeTips') }}</text>
<text @click.stop="redirect({ url: '/app/pages/auth/agreement?key=privacy' })" class="text-primary">{{t('privacyAgreement')}}</text>
<text>{{ t('and') }}</text>
@ -212,12 +212,21 @@
const rules = computed(()=>{
return {
'username': {
type: 'string',
required: type.value == 'username',
message: t('usernamePlaceholder'),
trigger: ['blur', 'change'],
},
'username': [
{
type: 'string',
required: type.value == 'username',
message: t('usernamePlaceholder'),
trigger: ['blur', 'change'],
},
{
validator(rule: any, value: any){
return !uni.$u.test.number(value)
},
message: t('usernameTips'),
trigger: ['change','blur'],
}
],
'password': {
type: 'string',
required: type.value == 'username',
@ -278,7 +287,6 @@
formRef.value.validate().then(() => {
if (configStore.login.agreement_show && !isAgree.value) {
popupRef.value.open();
// uni.showToast({ title: t('isAgreeTips'), icon: 'none' });
return false;
}
if (loading.value) return

View File

@ -0,0 +1,39 @@
<template>
<view @touchmove.prevent.stop>
<u-popup :show="messagePopup" @close="closeFn" mode="center" round="var(--rounded-big)">
<view class="w-[570rpx] px-[32rpx] popup-common center" v-if="Object.keys(configInfo).length">
<view class="title">{{ configInfo.pay_explain_title }}</view>
<scroll-view :scroll-y="true" class="px-[30rpx] box-border max-h-[260rpx]" v-if="configInfo.pay_explain_content">
<block v-for="(item) in configInfo.pay_explain_content.split('\n')">
<view class="text-[28rpx] leading-[40rpx] mb-[20rpx]">{{ item }}</view>
</block>
</scroll-view>
<view class="btn-wrap !pt-[40rpx]">
<button class="primary-btn-bg w-[480rpx] h-[70rpx] text-[26rpx] leading-[70rpx] rounded-[35rpx] !text-[#fff] font-500" @click="closeFn">我知道了</button>
</view>
</view>
</u-popup>
</view>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const messagePopup = ref(false)
const configInfo = ref<any>({})
const closeFn = () =>{
messagePopup.value = false
}
const open = (data: any) => {
configInfo.value = data
messagePopup.value = true;
}
defineExpose({
open
})
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,219 @@
<template>
<view :style="themeColor()">
<view class="bg-[var(--page-bg-color)] min-h-screen overflow-hidden" v-if="Object.keys(friendsInfo).length && !loading">
<view :style="{background: 'url(' + img('static/resource/images/app/friendpay_money.png') + ') left bottom / cover no-repeat'}" class="pb-[194rpx] overflow-hidden">
<!-- #ifdef MP-WEIXIN -->
<view class="sticky top-0 left-0 right-0 z-100">
<top-tabbar :data="topTabbarData" :scrollBool="topTabarObj.getScrollBool()" />
</view>
<!-- #endif -->
<view class="mt-[20rpx] flex flex-col items-center">
<u-avatar :src="img(friendsInfo.member.headimg)" size="50" leftIcon="none" :default-url="img('static/resource/images/default_headimg.png')" />
<view class="flex items-center mt-[20rpx] text-[#fff] text-[26rpx] leading-[36rpx]">
<text class="font-bold mr-[10rpx] max-w-[250rpx] truncate">{{ friendsInfo.member.nickname }}</text>
<text>请您帮忙付款~</text>
</view>
<view class="message bg-[#fe0708] relative max-w-[520rpx] px-[20rpx] py-[12rpx] rounded-[12rpx] border-solid border-[1rpx] border-color text-[24rpx] text-[#fff] leading-[30rpx] box-border text-center mt-[20rpx] mx-[114rpx]" v-if="friendsInfo.config.pay_leave_message">{{ friendsInfo.config.pay_leave_message }}</view>
</view>
</view>
<view class="-mt-[154rpx] card-template sidebar-margin mb-[var(--top-m)]">
<view class="text-[24rpx] text-center mb-[10rpx]">{{ t('payMoney') }}</view>
<view class="text-center mb-[50rpx]">
<text class="text-[32rpx] font-500 price-font text-[#FF4142]"></text>
<text class="text-[56rpx] font-bold price-font text-[#FF4142]">{{ parseFloat(friendsInfo.money).toFixed(2).split('.')[0] }}</text>
<text class="text-[32rpx] font-500 price-font text-[#FF4142]">.{{ parseFloat(friendsInfo.money).toFixed(2).split('.')[1] }}</text>
</view>
<view class="px-[20rpx] box-border">
<button class="bg-[#FFB4B1] !text-[#fff] h-[80rpx] leading-[80rpx] rounded-[100rpx] text-[26rpx] font-500" hover-class="none" v-if="friendsInfo.status == 2 ">{{ t('finish') }}</button>
<button class="bg-[#FFB4B1] !text-[#fff] h-[80rpx] leading-[80rpx] rounded-[100rpx] text-[26rpx] font-500" hover-class="none" v-else-if="friendsInfo.status == -1">{{ t('close') }}</button>
<button class="primary-btn-bg !text-[#fff] h-[80rpx] leading-[80rpx] rounded-[100rpx] text-[26rpx] font-500" hover-class="none" v-else :loading="operateLoading" @click="save">{{ friendsInfo.config.pay_button_name ? friendsInfo.config.pay_button_name : t('payGenerously') }}</button>
</view>
<view class="mt-[20rpx] flex items-baseline justify-center text-[var(--text-color-light9)]" @click="redirect({url: '/app/pages/index/index'})">
<text class="text-[24rpx] mr-[6rpx]">返回首页</text>
</view>
</view>
<view class="card-template sidebar-margin mb-[var(--top-m)]">
<template v-if="friendsInfo.config.pay_info_switch">
<template v-if="JSON.stringify(friendsInfo.trade_info) !== '[]' && friendsInfo.trade_info.item_list.length">
<view class="flex justify-between items-center mb-[30rpx]">
<view class="text-[30rpx] text-[#333] font-500">{{ t('helpPayInfo') }}</view>
<view class="flex-shrink-0" @click="handleMessage" v-if="friendsInfo.config.pay_explain_switch">
<text class="mr-[8rpx] text-[24rpx]">{{ friendsInfo.config.pay_explain_title }}</text>
<text class="nc-iconfont nc-icon-jichuxinxiV6xx text-[26rpx]"></text>
</view>
</view>
<view class="border-0 border-solid border-b-[1rpx] border-[#f6f6f6] mb-[20rpx]">
<view v-for="(item, index) in friendsInfo.trade_info.item_list" class="flex justify-between" :class="{' mb-[34rpx]': (index + 1) != friendsInfo.trade_info.length }">
<view class="w-[170rpx] h-[170rpx] rounded-[var(--goods-rounded-big)] overflow-hidden flex-shrink-0">
<u--image class="overflow-hidden" radius="var(--goods-rounded-big)" width="170rpx" height="170rpx" :src="img(item.item_image ? item.item_image : '')" model="aspectFill">
<template #error>
<image class="w-[170rpx] h-[170rpx] rounded-[var(--goods-rounded-big)] overflow-hidden" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill" />
</template>
</u--image>
</view>
<view class="ml-[20rpx] flex flex-1 flex-col justify-between">
<view>
<view class="text-[28rpx] using-hidden leading-[40rpx] text-[#333]">{{ item.item_name }}</view>
<view class="text-[24rpx] mt-[14rpx] text-[var(--text-color-light9)] using-hidden leading-[28rpx]" v-if="item.item_sub_name ">{{ item.item_sub_name }}</view>
</view>
<view class="flex justify-between items-baseline">
<view class="price-font text-[#FF4142]">
<text class="text-[24rpx]"></text>
<text class="text-[40rpx] font-500">{{ parseFloat(item.item_price).toFixed(2).split('.')[0] }}</text>
<text class="text-[24rpx] font-500">.{{ parseFloat(item.item_price).toFixed(2).split('.')[1] }}</text>
</view>
<text class="text-right text-[26rpx]">x{{ item.item_num }}</text>
</view>
</view>
</view>
</view>
<view class="text-[26rpx] text-right">{{ friendsInfo.trade_info.item_total }}</view>
</template>
<template v-else>
<view class="text-[28rpx] leading-[40rpx] text-[#333]">{{ friendsInfo.body }}</view>
</template>
</template>
</view>
</view>
<!-- 帮付说明 -->
<message ref="messageRef"></message>
<!-- 支付 -->
<pay ref="payRef" />
<loading-page :loading="loading"></loading-page>
</view>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { t } from '@/locale'
import { img, redirect, getToken,handleOnloadParams,goback } from '@/utils/common';
import { onLoad, onShow,onHide,onUnload } from '@dcloudio/uni-app'
import { topTabar } from '@/utils/topTabbar';
import { getFriendspayInfo } from '@/app/api/friendspay'
import Message from '@/app/pages/friendspay/components/message.vue'
import { useLogin } from '@/hooks/useLogin'
import { onPageScroll } from '@dcloudio/uni-app';
/********* 自定义头部 - start ***********/
const topTabarObj = topTabar()
let topTabbarData = topTabarObj.setTopTabbarParam({ title: '' })
/********* 自定义头部 - end ***********/
const loading = ref<boolean>(true);
const tradeId = ref<number>(0);
const tradeType = ref<string>('');
const friendsInfo = ref<any>({})
const operateLoading = ref(false)
const firstCall = ref<boolean>(true)
const timeOut: any = ref(null)
onLoad((option: any) =>{
// #ifdef MP-WEIXIN
//
option = handleOnloadParams(option);
// #endif
tradeId.value = option.id || 0;
tradeType.value = option.type || '';
})
onShow(()=>{
if(tradeId.value && tradeType.value){
getFriendspayInfoFn(tradeType.value, tradeId.value)
}
})
onHide(()=>{
if(timeOut.value) {
clearTimeout(timeOut.value);
timeOut.value = null;
}
})
onUnload(()=>{
if(timeOut.value) {
clearTimeout(timeOut.value);
timeOut.value = null;
}
})
const getFriendspayInfoFn = (tradeType : string, tradeId : number) => {
if (firstCall.value) { //
loading.value = true;
firstCall.value = false; // false
}
getFriendspayInfo(tradeType, tradeId).then((res: any) => {
friendsInfo.value = res.data
uni.setNavigationBarTitle({
title: friendsInfo.value.config.pay_page_name
})
topTabbarData = topTabarObj.setTopTabbarParam({ title: friendsInfo.value.config.pay_page_name })
loading.value = false
if( friendsInfo.value.status != 2 && friendsInfo.value.status != 1 && friendsInfo.value.status != -1){
// 3
timeOut.value = setTimeout(() => {
getFriendspayInfoFn(tradeType, tradeId)
}, 1000 * 3)
}else{
clearTimeout(timeOut.value);
timeOut.value = null;
}
}).catch(()=>{
if(timeOut.value) {
clearTimeout(timeOut.value);
timeOut.value = null;
}
loading.value = false
let parameter = {
title: '未找到帮付订单信息',
url: '/app/pages/index/index',
mode: 'reLaunch'
};
goback(parameter)
})
}
//
const messageRef = ref<any>(null);
const handleMessage = () => {
messageRef.value.open(friendsInfo.value.config)
}
const payRef = ref()
const save = () =>{
if(getToken()){
payRef.value?.open(friendsInfo.value.trade_type, friendsInfo.value.trade_id, '/app/pages/index/index', 'friendspay')
} else {
useLogin().setLoginBack({
url: '/app/pages/friendspay/money',
param: { id: friendsInfo.value.trade_id, type: friendsInfo.value.trade_type }
})
}
}
</script>
<style lang="scss" scoped>
.border-color{
border-color: rgba(255, 255, 255, 0.7);
}
.message{
&::after{
content: '';
width: 16rpx;
height: 16rpx;
background-color: #fe0708;
border: solid 1rpx transparent;
border-top-color: #fff;
border-left-color: #fff;
border-top-left-radius:4rpx;
position: absolute;
left: 50%;
top: 0;
transform: translateX(-50%) translateY(-50%) rotate(45deg);
}
}
</style>

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