Compare commits

..

No commits in common. "46c7ff60c822547e6ee035b123716b3b3eac4fab" and "3dd6b192056298147e4a6c4bdec697e36dca011f" have entirely different histories.

23 changed files with 199 additions and 557 deletions

View File

@ -7,7 +7,36 @@ name: filesystem-drone # 定义流水线名称
steps: # 定义流水线执行步骤,这些步骤将顺序执行
- name: package-and-push-image
- name: package # 流水线名称
image: maven:3-jdk-8 # 定义创建容器的Docker镜像
volumes: # 将容器内目录挂载到宿主机仓库需要开启Trusted设置
- name: maven-cache
path: /root/.m2 # 将maven下载依赖的目录挂载出来防止重复下载
- name: maven-build
path: /app/build # 将应用打包好的Jar和执行脚本挂载出来
commands: # 定义在Docker容器中执行的shell命令
- mvn package -Dmaven.test.skip=true # 应用打包命令
# - cd yudao-server/target/
# - ls
- cp yudao-server/target/yudao-server.jar /app/build/yudao-server.jar
- cp yudao-server/Dockerfile /app/build/Dockerfile
- cp yudao-server/run.sh /app/build/run.sh
- name: copy package
image: appleboy/drone-ssh # SSH工具镜像
@ -26,17 +55,8 @@ steps: # 定义流水线执行步骤,这些步骤将顺序执行
command_timeout: 5m # 远程执行命令超时时间
script:
- cd /root/allLikeMall
- git fetch origin
- git reset --hard origin/main
- git clean -fd
- mvn package -Dmaven.test.skip=true
- cd yudao-server
- chmod +x push.sh
- ./push.sh
- scp ./run.sh root@1.14.205.126:/zymail
# - ls
# - scp -r /zymail/maven/build root@1.14.205.126:/zymail
- scp -r /zymail/maven/build root@1.14.205.126:/zymail
# - ssh root@1.14.205.126
# - ls
@ -66,3 +86,13 @@ steps: # 定义流水线执行步骤,这些步骤将顺序执行
- cd /zymail/build
- chmod +x run.sh # 更改为可执行脚本
- ./run.sh # 运行脚本打包应用镜像并运行
volumes: # 定义流水线挂载目录,用于共享数据
- name: maven-build
host:
path: /zymail/maven/build # 从宿主机中挂载的目录
- name: maven-cache
host:
path: /zymail/maven/cache # 从宿主机中挂载的目录

View File

@ -24,8 +24,3 @@ export const getWallet = async (params: PayWalletUserReqVO) => {
export const getWalletPage = async (params) => {
return await request.get({ url: `/pay/wallet/page`, params })
}
// 修改会员钱包余额
export const updateWalletBalance = async (data: any) => {
return await request.post({ url: `/pay/wallet/update`, data })
}

View File

@ -1,45 +1,31 @@
<template>
<div class="min-h-42px flex flex-col">
<div v-for="(item, index) in property.list" :key="index"
class="item h-42px flex flex-row items-center justify-between gap-4px p-x-12px">
<div class="flex flex-1 flex-row items-center gap-8px">
<el-image v-if="item.iconUrl" class="wh" :src="item.iconUrl" />
<span class="text-16px" :style="{ color: item.titleColor }">{{ item.title }}</span>
</div>
<div class="item-center flex flex-row justify-center gap-4px">
<span class="text-12px" :style="{ color: item.subtitleColor }">{{ item.subtitle }}</span>
<Icon icon="ep-arrow-right" color="#000" :size="16" />
</div>
</div>
</div>
<div class="min-h-42px flex flex-col">
<div
v-for="(item, index) in property.list"
:key="index"
class="item h-42px flex flex-row items-center justify-between gap-4px p-x-12px"
>
<div class="flex flex-1 flex-row items-center gap-8px">
<el-image v-if="item.iconUrl" class="h-16px w-16px" :src="item.iconUrl" />
<span class="text-16px" :style="{ color: item.titleColor }">{{ item.title }}</span>
</div>
<div class="item-center flex flex-row justify-center gap-4px">
<span class="text-12px" :style="{ color: item.subtitleColor }">{{ item.subtitle }}</span>
<Icon icon="ep-arrow-right" color="#000" :size="16" />
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { MenuListProperty } from './config'
/** 列表导航 */
defineOptions({ name: 'MenuList' })
defineProps<{ property : MenuListProperty }>()
import { MenuListProperty } from './config'
/** 列表导航 */
defineOptions({ name: 'MenuList' })
defineProps<{ property: MenuListProperty }>()
</script>
<style scoped lang="scss">
.item+.item {
border-top: 1px solid #eee;
}
.wh {
width: 77px;
height: 20px;
position: relative;
padding-right: 10px;
&::after{
position:absolute;
content:'';
top:50%;
right:0;
width:1px;
height:57%;
border-right:1px solid #ababab;
transform: translateY(-50%);
}
}
</style>
.item + .item {
border-top: 1px solid #eee;
}
</style>

View File

@ -1,161 +1,119 @@
<template>
<!-- <el-carousel :height="`${carouselHeight}px`" :autoplay="false" arrow="hover" indicator-position="outside">
<el-carousel-item v-for="(page, pageIndex) in pages" :key="pageIndex">
<div class="flex flex-row flex-wrap">
<div v-for="(item, index) in page" :key="index"
class="relative flex flex-col items-center justify-center"
:style="{ width: columnWidth, height: `${rowHeight}px` }"> -->
<!-- 图标 + 角标 -->
<!-- <div class="relative" :class="`h-${ICON_SIZE}px w-${ICON_SIZE}px`"> -->
<!-- 右上角角标 -->
<!-- <span v-if="item.badge?.show"
class="absolute right--10px top--10px z-1 h-20px rounded-10px p-x-6px text-center text-12px leading-20px"
:style="{ color: item.badge.textColor, backgroundColor: item.badge.bgColor }">
{{ item.badge.text }}
</span>
<el-image v-if="item.iconUrl" :src="item.iconUrl" class="h-full w-full" />
</div> -->
<!-- 标题 -->
<!-- <span v-if="property.layout === 'iconText'" class="text-12px" :style="{
color: item.titleColor,
height: `${TITLE_HEIGHT}px`,
lineHeight: `${TITLE_HEIGHT}px`
}">
{{ item.title }}
</span>
</div>
</div>
</el-carousel-item>
</el-carousel> -->
<view class="title">
我的服务
</view>
<view class="newList">
<view class="new_menu" v-for="(page, pageIndex) in pages" :key="pageIndex">
<view v-for="(item, index) in page" :key="index" class="new_items" :style="{ width: columnWidth}">
<!-- 图标 + 角标 -->
<div class="relative" :class="`h-24px w-24px`">
<!-- 右上角角标 -->
<span v-if="item.badge?.show"
class="absolute right--10px top--10px z-1 h-20px rounded-10px p-x-6px text-center text-12px leading-20px"
:style="{ color: item.badge.textColor, backgroundColor: item.badge.bgColor }">
{{ item.badge.text }}
</span>
<el-image v-if="item.iconUrl" :src="item.iconUrl" class="h-full w-full" />
</div>
<!-- 标题 -->
<span v-if="property.layout === 'iconText'" class="text-12px new_title" :style="{
color: item.titleColor,
height: `${TITLE_HEIGHT}px`,
lineHeight: `${TITLE_HEIGHT}px`
}">
{{ item.title }}
</span>
</view>
</view>
</view>
<el-carousel
:height="`${carouselHeight}px`"
:autoplay="false"
arrow="hover"
indicator-position="outside"
>
<el-carousel-item v-for="(page, pageIndex) in pages" :key="pageIndex">
<div class="flex flex-row flex-wrap">
<div
v-for="(item, index) in page"
:key="index"
class="relative flex flex-col items-center justify-center"
:style="{ width: columnWidth, height: `${rowHeight}px` }"
>
<!-- 图标 + 角标 -->
<div class="relative" :class="`h-${ICON_SIZE}px w-${ICON_SIZE}px`">
<!-- 右上角角标 -->
<span
v-if="item.badge?.show"
class="absolute right--10px top--10px z-1 h-20px rounded-10px p-x-6px text-center text-12px leading-20px"
:style="{ color: item.badge.textColor, backgroundColor: item.badge.bgColor }"
>
{{ item.badge.text }}
</span>
<el-image v-if="item.iconUrl" :src="item.iconUrl" class="h-full w-full" />
</div>
<!-- 标题 -->
<span
v-if="property.layout === 'iconText'"
class="text-12px"
:style="{
color: item.titleColor,
height: `${TITLE_HEIGHT}px`,
lineHeight: `${TITLE_HEIGHT}px`
}"
>
{{ item.title }}
</span>
</div>
</div>
</el-carousel-item>
</el-carousel>
</template>
<script setup lang="ts">
import { MenuSwiperProperty, MenuSwiperItemProperty } from './config'
/** 菜单导航 */
defineOptions({ name: 'MenuSwiper' })
const props = defineProps<{ property : MenuSwiperProperty }>()
//
const TITLE_HEIGHT = 20
//
const ICON_SIZE = 42
//
const SPACE_Y = 16
import { MenuSwiperProperty, MenuSwiperItemProperty } from './config'
/** 菜单导航 */
defineOptions({ name: 'MenuSwiper' })
const props = defineProps<{ property: MenuSwiperProperty }>()
//
const TITLE_HEIGHT = 20
//
const ICON_SIZE = 42
//
const SPACE_Y = 16
//
const pages = ref<MenuSwiperItemProperty[][]>([])
//
const carouselHeight = ref(0)
//
const rowHeight = ref(0)
//
const columnWidth = ref('')
watch(
() => props.property,
() => {
//
columnWidth.value = `${100 * (1 / props.property.column)}%`
// + 0 + * 2
rowHeight.value =
(props.property.layout === 'iconText' ? ICON_SIZE + TITLE_HEIGHT : ICON_SIZE) + SPACE_Y * 2
// *
carouselHeight.value = props.property.row * rowHeight.value
//
const pages = ref<MenuSwiperItemProperty[][]>([])
//
const carouselHeight = ref(0)
//
const rowHeight = ref(0)
//
const columnWidth = ref('')
watch(
() => props.property,
() => {
//
columnWidth.value = `${100 * (1 / props.property.column)}%`
// + 0 + * 2
rowHeight.value =
(props.property.layout === 'iconText' ? ICON_SIZE + TITLE_HEIGHT : ICON_SIZE) + SPACE_Y * 2
// *
carouselHeight.value = props.property.row * rowHeight.value
// *
const pageSize = props.property.row * props.property.column
//
pages.value = []
//
let pageItems : MenuSwiperItemProperty[] = []
for (const item of props.property.list) {
//
if (pageItems.length === pageSize) {
pageItems = []
}
//
if (pageItems.length === 0) {
pages.value.push(pageItems)
}
//
pageItems.push(item)
}
},
{ immediate: true, deep: true }
)
// *
const pageSize = props.property.row * props.property.column
//
pages.value = []
//
let pageItems: MenuSwiperItemProperty[] = []
for (const item of props.property.list) {
//
if (pageItems.length === pageSize) {
pageItems = []
}
//
if (pageItems.length === 0) {
pages.value.push(pageItems)
}
//
pageItems.push(item)
}
},
{ immediate: true, deep: true }
)
</script>
<style lang="scss">
.title {
padding: 10px 20px;
height: 20px;
line-height: 20px;
font-size: 12px;
font-weight: 600;
// border-bottom: 1px solid #dcdcdc;
margin-bottom:20px;
}
.new_menu {
display: flex;
flex-wrap: wrap;
.new_items {
width: 25%;
margin-bottom: 20px;
display: flex;
justify-content: center;
flex-wrap: wrap;
.new_title{
width:100%;
text-align: center;
}
}
}
// APP
:root {
.el-carousel__indicator {
padding-top: 0;
padding-bottom: 0;
.el-carousel__button {
--el-carousel-indicator-height: 6px;
--el-carousel-indicator-width: 6px;
--el-carousel-indicator-out-color: #ff6000;
border-radius: 6px;
}
}
.el-carousel__indicator.is-active {
.el-carousel__button {
--el-carousel-indicator-width: 12px;
}
}
}
</style>
// APP
:root {
.el-carousel__indicator {
padding-top: 0;
padding-bottom: 0;
.el-carousel__button {
--el-carousel-indicator-height: 6px;
--el-carousel-indicator-width: 6px;
--el-carousel-indicator-out-color: #ff6000;
border-radius: 6px;
}
}
.el-carousel__indicator.is-active {
.el-carousel__button {
--el-carousel-indicator-width: 12px;
}
}
}
</style>

View File

@ -1,27 +1,7 @@
<template>
<div class="min-h-30px" >
<view class="floxt">
<view class="addClass" v-for="(item, index) in article?.list" :key="index" >
<view class="image">
<img
:src="item.picUrl"
alt="" />
</view>
<view class="text">
<view class="top">
{{item.title}}
</view>
<view class="bottom">
<!-- {{ sheep.$helper.timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss') }} -->
{{ formatDate(item.createTime) }}
</view>
</view>
</view>
</view>
</div>
<div class="min-h-30px" v-html="article?.content"></div>
</template>
<script setup lang="ts">
import { formatDate } from '@/utils/formatTime'
import { PromotionArticleProperty } from './config'
import * as ArticleApi from '@/api/mall/promotion/article/index'
@ -35,9 +15,7 @@ watch(
() => props.property.id,
async () => {
if (props.property.id) {
// article.value = await ArticleApi.getArticle(props.property.id)
article.value = await ArticleApi.getArticlePage()
console.log(article.value,"article.value");
article.value = await ArticleApi.getArticle(props.property.id)
}
},
{
@ -46,44 +24,4 @@ watch(
)
</script>
<style scoped lang="scss">
.floxt {
width: 100%;
.addClass {
background:white;
display: flex;
justify-content: space-between;
width: 100%;
margin:8px 0;
// padding: 40px;
// padding-right: 0;
// height: 200px;
.image {
width: 130px;
height: 81px;
margin-right: 18px;
padding:8px 8px;
display:flex;
img{
width: 100%;
height: 100%;
}
}
.text {
display: flex;
width: 100%;
// text-align: center;
padding:20px 20px;
flex:1;
flex-direction: column;
justify-content: space-between;
.bottom{
color: #999;
font-size: 12px;
}
}
}
}
</style>
<style scoped lang="scss"></style>

View File

@ -135,11 +135,11 @@ export const PAGE_LIBS = [
]
},
{ name: '商品组件', extended: true, components: ['ProductCard', 'ProductList'] },
// {
// name: '用户组件',
// extended: true,
// components: ['UserCard', 'UserOrder', 'UserWallet', 'UserCoupon']
// },
{
name: '用户组件',
extended: true,
components: ['UserCard', 'UserOrder', 'UserWallet', 'UserCoupon']
},
{
name: '营销组件',
extended: true,

View File

@ -1,134 +0,0 @@
<template>
<Dialog title="修改用户余额" v-model="dialogVisible" width="600">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="用户编号" prop="userId">
<el-input v-model="formData.userId" class="!w-240px" disabled />
</el-form-item>
<el-form-item label="用户昵称" prop="nickname">
<el-input v-model="formData.nickname" class="!w-240px" disabled />
</el-form-item>
<el-form-item label="变动前余额" prop="balance">
<el-input-number v-model="formData.balance" class="!w-240px" :precision="2" disabled />
</el-form-item>
<el-form-item label="变动类型" prop="changeType">
<el-radio-group v-model="formData.changeType">
<el-radio :label="1">增加</el-radio>
<el-radio :label="-1">减少</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="变动余额" prop="changePoint">
<el-input-number v-model="formData.changePoint" class="!w-240px" :min="0" :precision="2" />
</el-form-item>
<el-form-item label="变动后余额">
<el-input-number v-model="pointResult" class="!w-240px" :precision="2" disabled />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import * as UserApi from '@/api/pay/wallet/balance'
import * as UserApi2 from '@/api/member/user'
/** 修改用户余额表单 */
defineOptions({ name: 'UpdatePointForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const formLoading = ref(false) // 12
const formData = ref({
id: undefined,
userId: undefined,
nickname: undefined,
balance: 0,
changePoint: 0,
changeType: 1
})
const formRules = reactive({
changePoint: [{ required: true, message: '变动余额不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (id?: number) => {
dialogVisible.value = true
resetForm()
//
if (id) {
formLoading.value = true
try {
const param = { userId: id }
const wallet = await UserApi.getWallet(param)
formData.value = wallet
formData.value.balance = wallet.balance / 100.0;
const user = await UserApi2.getUser(id);
formData.value.nickname = user.nickname;
formData.value.changeType = 1 //
formData.value.changePoint = 0 // 0
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
if (!formRef) return
const valid = await formRef.value.validate()
if (!valid) return
if (formData.value.changePoint < 1) {
message.error('变动余额不能小于 1')
return
}
if (pointResult.value < 0) {
message.error('变动后的余额不能小于 0')
return
}
//
formLoading.value = true
try {
await UserApi.updateWalletBalance({
id: formData.value.id,
balance: formData.value.changePoint * formData.value.changeType
})
message.success(t('common.updateSuccess'))
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
nickname: undefined,
balance: undefined,
reason: undefined
}
formRef.value?.resetFields()
}
/** 变动后的余额 */
const pointResult = computed(
() => formData.value.balance + formData.value.changePoint * formData.value.changeType
)
</script>

View File

@ -106,7 +106,6 @@
</template>
</el-table-column>
<el-table-column align="center" label="积分" prop="point" width="100px" />
<el-table-column align="center" label="余额" prop="balance" width="100px" />
<el-table-column align="center" label="状态" prop="status" width="100px">
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
@ -197,8 +196,6 @@
<UserLevelUpdateForm ref="updateLevelFormRef" @success="getList" />
<!-- 修改用户积分弹窗 -->
<UserPointUpdateForm ref="updatePointFormRef" @success="getList" />
<!-- 修改用户余额弹窗 -->
<UserBalanceUpdateForm ref="updateBalanceFormRef" @success="getList" />
<!-- 发送优惠券弹窗 -->
<CouponSendForm ref="couponSendFormRef" />
</template>
@ -212,7 +209,6 @@ import MemberLevelSelect from '@/views/member/level/components/MemberLevelSelect
import MemberGroupSelect from '@/views/member/group/components/MemberGroupSelect.vue'
import UserLevelUpdateForm from './UserLevelUpdateForm.vue'
import UserPointUpdateForm from './UserPointUpdateForm.vue'
import UserBalanceUpdateForm from './UserBalanceUpdateForm.vue'
import { CouponSendForm } from '@/views/mall/promotion/coupon/components'
import { checkPermi } from '@/utils/permission'
@ -237,7 +233,6 @@ const queryParams = reactive({
const queryFormRef = ref() //
const updateLevelFormRef = ref() //
const updatePointFormRef = ref() //
const updateBalanceFormRef = ref() //
const selectedIds = ref<number[]>([]) // ID
/** 查询列表 */
@ -304,7 +299,7 @@ const handleCommand = (command: string, row: UserApi.UserVO) => {
updatePointFormRef.value.open(row.id)
break
case 'handleUpdateBlance':
updateBalanceFormRef.value.open(row.id)
// todo @jason
break
default:
break

View File

@ -33,11 +33,6 @@
<artifactId>yudao-module-infra-api</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-pay-api</artifactId>
<version>2.1.0-jdk8-snapshot</version>
</dependency>
<!-- 业务组件 -->
<dependency>

View File

@ -15,7 +15,6 @@ import cn.iocoder.yudao.module.member.service.level.MemberLevelService;
import cn.iocoder.yudao.module.member.service.point.MemberPointRecordService;
import cn.iocoder.yudao.module.member.service.tag.MemberTagService;
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
import cn.iocoder.yudao.module.pay.api.wallet.PayWalletApi;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
@ -25,7 +24,6 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
@ -52,8 +50,6 @@ public class MemberUserController {
private MemberGroupService memberGroupService;
@Resource
private MemberPointRecordService memberPointRecordService;
@Resource
private PayWalletApi payWalletApi;
@PutMapping("/update")
@Operation(summary = "更新会员用户")
@ -119,11 +115,7 @@ public class MemberUserController {
// 处理用户分组返显
List<MemberGroupDO> groups = memberGroupService.getGroupList(
convertSet(pageResult.getList(), MemberUserDO::getGroupId));
PageResult<MemberUserRespVO> convertPage = MemberUserConvert.INSTANCE.convertPage(pageResult, tags, levels, groups);
for (MemberUserRespVO respVO : convertPage.getList()) {
respVO.setBalance(new BigDecimal(payWalletApi.getUserBalance(respVO.getId())).divide(BigDecimal.valueOf(100)).toString());
}
return success(convertPage);
return success(MemberUserConvert.INSTANCE.convertPage(pageResult, tags, levels, groups));
}
}

View File

@ -34,9 +34,6 @@ public class MemberUserRespVO extends MemberUserBaseVO {
@Schema(description = "积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer point;
@Schema(description = "余额", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private String balance;
@Schema(description = "总积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000")
private Integer totalPoint;

View File

@ -218,8 +218,7 @@ public class MemberUserServiceImpl implements MemberUserService {
@Override
public boolean isPasswordMatch(String rawPassword, String encodedPassword) {
return true;
// return passwordEncoder.matches(rawPassword, encodedPassword);
return passwordEncoder.matches(rawPassword, encodedPassword);
}
/**

View File

@ -1,5 +0,0 @@
package cn.iocoder.yudao.module.pay.api.wallet;
public interface PayWalletApi {
Integer getUserBalance (Long id);
}

View File

@ -47,7 +47,6 @@ public interface ErrorCodeConstants {
ErrorCode WALLET_REFUND_EXIST = new ErrorCode(1_007_007_003, "已经存在钱包退款");
ErrorCode WALLET_FREEZE_PRICE_NOT_ENOUGH = new ErrorCode(1_007_007_004, "钱包冻结余额不足");
// ========== 钱包充值模块 1-007-008-000 ==========
ErrorCode WALLET_RECHARGE_NOT_FOUND = new ErrorCode(1_007_008_000, "钱包充值记录不存在");
ErrorCode WALLET_RECHARGE_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1_007_008_001, "钱包充值更新支付状态失败,钱包充值记录不是【未支付】状态");
@ -63,8 +62,6 @@ public interface ErrorCodeConstants {
ErrorCode WALLET_RECHARGE_PACKAGE_NOT_FOUND = new ErrorCode(1_007_008_011, "钱包充值套餐不存在");
ErrorCode WALLET_RECHARGE_PACKAGE_IS_DISABLE = new ErrorCode(1_007_008_012, "钱包充值套餐已禁用");
ErrorCode WALLET_RECHARGE_PACKAGE_NAME_EXISTS = new ErrorCode(1_007_008_013, "钱包充值套餐名称已存在");
ErrorCode WALLET_RECHARGE_RANGE_EXCEPTION = new ErrorCode(1_007_007_004, "充值后余额异常");
// ========== 转账模块 1-007-009-000 ==========
ErrorCode PAY_TRANSFER_SUBMIT_CHANNEL_ERROR = new ErrorCode(1_007_009_000, "发起转账报错,错误码:{},错误提示:{}");

View File

@ -18,8 +18,7 @@ public enum PayWalletBizTypeEnum implements IntArrayValuable {
RECHARGE(1, "充值"),
RECHARGE_REFUND(2, "充值退款"),
PAYMENT(3, "支付"),
PAYMENT_REFUND(4, "支付退款"),
ADMIN_MODIFY(5, "管理员修改");
PAYMENT_REFUND(4, "支付退款");
// TODO 后续增加

View File

@ -1,22 +0,0 @@
package cn.iocoder.yudao.module.pay.api.wallet;
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
import cn.iocoder.yudao.module.pay.service.wallet.PayWalletService;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import static cn.iocoder.yudao.framework.common.enums.UserTypeEnum.MEMBER;
@Service
@Validated
public class PayWalletApiImpl implements PayWalletApi{
@Resource
private PayWalletService payWalletService;
@Override
public Integer getUserBalance(Long id) {
PayWalletDO walletDO = payWalletService.getOrCreateWallet(id, MEMBER.getValue());
return walletDO.getBalance();
}
}

View File

@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.wallet.PayWalletPageReqVO;
import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.wallet.PayWalletRespVO;
import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.wallet.PayWalletUserBalanceVo;
import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.wallet.PayWalletUserReqVO;
import cn.iocoder.yudao.module.pay.convert.wallet.PayWalletConvert;
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
@ -14,7 +13,9 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.validation.Valid;
@ -40,14 +41,6 @@ public class PayWalletController {
return success(PayWalletConvert.INSTANCE.convert02(wallet));
}
@PostMapping("/update")
@PreAuthorize("@ss.hasPermission('pay:wallet:update')")
@Operation(summary = "修改用户钱包余额(后台操作)")
public CommonResult<Boolean> updateWallet(@Valid @RequestBody PayWalletUserBalanceVo reqVo){
payWalletService.updateWallet(reqVo);
return success(true);
}
@GetMapping("/page")
@Operation(summary = "获得会员钱包分页")
@PreAuthorize("@ss.hasPermission('pay:wallet:query')")

View File

@ -1,17 +0,0 @@
package cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.wallet;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
@Schema(description = "管理后台 - 用户修改余额 Request VO")
@Data
public class PayWalletUserBalanceVo {
@Schema(description = "钱包编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id;
@Schema(description = "余额", requiredMode = Schema.RequiredMode.REQUIRED)
private BigDecimal balance;
}

View File

@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.pay.service.wallet;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.wallet.PayWalletPageReqVO;
import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.wallet.PayWalletUserBalanceVo;
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO;
import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum;
@ -98,10 +97,4 @@ public interface PayWalletService {
*/
void unfreezePrice(Long id, Integer price);
/**
* 修改钱包余额后台操作
* @param reqVo
* @return void
*/
void updateWallet(PayWalletUserBalanceVo reqVo);
}

View File

@ -2,9 +2,7 @@ package cn.iocoder.yudao.module.pay.service.wallet;
import cn.hutool.core.lang.Assert;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.wallet.PayWalletPageReqVO;
import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.wallet.PayWalletUserBalanceVo;
import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO;
import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
@ -20,7 +18,6 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@ -35,7 +32,7 @@ import static cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum.PAYM
*/
@Service
@Slf4j
public class PayWalletServiceImpl implements PayWalletService {
public class PayWalletServiceImpl implements PayWalletService {
@Resource
private PayWalletMapper walletMapper;
@ -105,7 +102,7 @@ public class PayWalletServiceImpl implements PayWalletService {
/**
* 校验是否能退款
*
* @param refundId 支付退款单 id
* @param refundId 支付退款单 id
* @param walletPayNo 钱包支付 no
*/
private Long validateWalletCanRefund(Long refundId, String walletPayNo) {
@ -208,37 +205,4 @@ public class PayWalletServiceImpl implements PayWalletService {
}
}
@Override
public void updateWallet(PayWalletUserBalanceVo reqVo) {
// 如果
if (reqVo.getBalance().compareTo(BigDecimal.ZERO) == 0) {
return;
}
// 把单位从元转为分
BigDecimal change = new BigDecimal("100");
// 查出对应钱包信息
PayWalletDO walletDO = walletMapper.selectById(reqVo.getId());
if (reqVo.getBalance().compareTo(new BigDecimal("21474836.47")) > 0) {
throw exception(WALLET_RECHARGE_RANGE_EXCEPTION);
}
// 总共改变的金额
long changeBalance = (reqVo.getBalance().multiply(change)).longValue();
// 总余额
long totalBalance = walletDO.getBalance() + changeBalance;
// 总充值
long totalRecharge = walletDO.getTotalRecharge() + changeBalance;
if (totalBalance > 2147483647 || totalRecharge > 2147483647 || totalBalance < 0 || totalRecharge < 0) {
throw exception(WALLET_RECHARGE_RANGE_EXCEPTION);
}
walletDO.setBalance((int) totalBalance);
walletDO.setTotalRecharge((int) totalRecharge);
walletMapper.updateById(walletDO);
String title = "后台操作给用户" + (totalBalance > 0 ? "增加" : "减少") + "余额" + Math.abs(changeBalance)/100.0 + "";
WalletTransactionCreateReqBO transactionCreateReqBO = new WalletTransactionCreateReqBO()
.setWalletId(reqVo.getId()).setPrice((int) changeBalance).setBalance((int) totalBalance)
.setBizType(PayWalletBizTypeEnum.ADMIN_MODIFY.getType()).setBizId("0").setTitle(title);
walletTransactionService.createWalletTransaction(transactionCreateReqBO);
}
}

View File

@ -4,13 +4,13 @@ FROM openjdk:8-jre
RUN mkdir -p /yudao-server
WORKDIR /yudao-server
## 将后端项目的 Jar 文件,复制到镜像中
ADD ./target/yudao-server.jar app.jar
ADD yudao-server.jar app.jar
## 设置 TZ 时区
ENV TZ=Asia/Shanghai
## 设置 JAVA_OPTS 环境变量,可通过 docker run -e "JAVA_OPTS=" 进行覆盖
ENV JAVA_OPTS="-Xms512m -Xmx512m -Djava.security.egd=file:/dev/./urandom"
Duser.timezone=Asia/Shanghai"
## 应用参数
ENV ARGS=""

View File

@ -1,11 +0,0 @@
app_name='zymall'
# 定义应用版本
app_version='1.0.0'
app_repository='mt.ptzykjgs.com:8080/serve'
# 打包编译docker镜像
echo '----build image----'
docker buildx build -f Dockerfile -t "${app_name}:${app_version}" .
echo '----tag image----'
docker tag "${app_name}:${app_version}" "${app_repository}/${app_name}:${app_version}"
echo '----push image----'
docker push "${app_repository}/${app_name}:${app_version}"

View File

@ -1,7 +1,6 @@
app_name='zymall'
# 定义应用版本
app_version='1.0.0'
app_repository='mt.ptzykjgs.com:8080/serve'
# 定义应用环境
#profile_active='prod'
echo '----stop container----'
@ -9,8 +8,9 @@ docker stop ${app_name}
echo '----rm container----'
docker rm ${app_name}
echo '----rm image----'
docker rmi -f "${app_name}:${app_version}"
echo '----pull image----'
docker pull "${app_repository}/${app_name}:${app_version}"
docker rmi ${app_name}:${app_version}
# 打包编译docker镜像
echo '----build image----'
docker buildx build -f Dockerfile -t ${app_name}:${app_version} .
echo '----start container----'
docker run -d -p 6127:6127 --name ${app_name} --restart always "${app_repository}/${app_name}:${app_version}"
docker run -d -p 6127:6127 --name ${app_name} --restart always ${app_name}:${app_version}