feat(用户余额): 添加用户余额修改功能
- 新增用户余额实体和API接口 - 在用户详情页添加余额修改按钮和弹窗 - 实现金额单位转换和表单验证 - 添加相关文档说明
This commit is contained in:
parent
040fb4acaa
commit
1a30197960
|
|
@ -0,0 +1,130 @@
|
||||||
|
import { http } from "@/utils/http";
|
||||||
|
|
||||||
|
export interface UserBalance {
|
||||||
|
/** 主键ID */
|
||||||
|
userBalanceId: number;
|
||||||
|
/** 企业微信id */
|
||||||
|
corpid: string;
|
||||||
|
/** openid */
|
||||||
|
openid: string;
|
||||||
|
/** 汇邦云用户ID */
|
||||||
|
ab98UserId: number;
|
||||||
|
/** 企业用户id */
|
||||||
|
qyUserId: number;
|
||||||
|
/** 用户余额(单位:分) */
|
||||||
|
balance: number;
|
||||||
|
/** 用户余额(单位:分) */
|
||||||
|
useBalance: number;
|
||||||
|
/** 用户余额(单位:分) */
|
||||||
|
balanceLimit: number;
|
||||||
|
/** 创建者ID */
|
||||||
|
creatorId: number;
|
||||||
|
/** 更新者ID */
|
||||||
|
updaterId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserBalanceListParams {
|
||||||
|
pageNum?: number;
|
||||||
|
pageSize?: number;
|
||||||
|
corpid?: string;
|
||||||
|
openid?: string;
|
||||||
|
ab98UserId?: number;
|
||||||
|
qyUserId?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserBalanceListResponse {
|
||||||
|
rows: UserBalance[];
|
||||||
|
total: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增用户余额请求参数
|
||||||
|
export interface AddUserBalanceCommand {
|
||||||
|
/** 企业微信ID */
|
||||||
|
corpid: string;
|
||||||
|
/** 微信openid */
|
||||||
|
openid?: string;
|
||||||
|
/** 汇邦云用户ID */
|
||||||
|
ab98UserId: number;
|
||||||
|
/** 企业用户ID */
|
||||||
|
qyUserId?: number;
|
||||||
|
/** 用户余额(分) */
|
||||||
|
balance?: number;
|
||||||
|
/** 可用余额(分) */
|
||||||
|
useBalance?: number;
|
||||||
|
/** 余额限制(分) */
|
||||||
|
balanceLimit?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改用户余额请求参数
|
||||||
|
export interface UpdateUserBalanceCommand extends AddUserBalanceCommand { }
|
||||||
|
|
||||||
|
// 余额增减操作请求参数
|
||||||
|
export interface ChangeBalanceCommand {
|
||||||
|
/** 企业微信ID */
|
||||||
|
corpid: string;
|
||||||
|
/** 汇邦云用户ID */
|
||||||
|
ab98UserId: number;
|
||||||
|
/** 金额(分) */
|
||||||
|
amount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据企业微信ID和汇邦云用户ID查询参数
|
||||||
|
export interface QueryByCorpidAb98Params {
|
||||||
|
corpid: string;
|
||||||
|
ab98UserId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据openid查询参数
|
||||||
|
export interface QueryByOpenidParams {
|
||||||
|
openid: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量删除参数
|
||||||
|
export interface BatchDeleteParams {
|
||||||
|
ids: number[];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用户余额相关API
|
||||||
|
export const getUserBalanceListApi = (params: UserBalanceListParams) => {
|
||||||
|
return http.request<ResponseData<PageDTO<UserBalance>>>("get", "/ab98/balance", { params });
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getUserBalanceDetailApi = (id: number) => {
|
||||||
|
return http.request<ResponseData<UserBalance>>("get", `/ab98/balance/${id}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getUserBalanceByCorpidAb98Api = (params: QueryByCorpidAb98Params) => {
|
||||||
|
return http.request<ResponseData<UserBalance>>("get", "/ab98/balance/byCorpidAb98", { params });
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getUserBalanceByOpenidApi = (params: QueryByOpenidParams) => {
|
||||||
|
return http.request<ResponseData<UserBalance>>("get", "/ab98/balance/byOpenid", { params });
|
||||||
|
};
|
||||||
|
|
||||||
|
export const addUserBalanceApi = (data: AddUserBalanceCommand) => {
|
||||||
|
return http.request<ResponseData<UserBalance>>("post", "/ab98/balance", { data });
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateUserBalanceApi = (id: number, data: UpdateUserBalanceCommand) => {
|
||||||
|
return http.request<ResponseData<UserBalance>>("put", `/ab98/balance/${id}`, { data });
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deleteUserBalanceApi = (id: number) => {
|
||||||
|
return http.request<ResponseData<void>>("delete", `/ab98/balance/${id}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const batchDeleteUserBalanceApi = (ids: number[]) => {
|
||||||
|
return http.request<ResponseData<void>>("delete", `/ab98/balance/batch/${ids.join(',')}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const addUserBalanceAmountApi = (data: ChangeBalanceCommand) => {
|
||||||
|
return http.request<ResponseData<string>>("post", "/ab98/balance/addBalance", { data });
|
||||||
|
};
|
||||||
|
|
||||||
|
export const subtractUserBalanceAmountApi = (data: ChangeBalanceCommand) => {
|
||||||
|
return http.request<ResponseData<string>>("post", "/ab98/balance/subtractBalance", { data });
|
||||||
|
};
|
||||||
|
|
||||||
|
export const insertOrUpdateUserBalanceApi = (data: AddUserBalanceCommand) => {
|
||||||
|
return http.request<ResponseData<UserBalance>>("post", "/ab98/balance/insertOrUpdate", { data });
|
||||||
|
};
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { http } from "@/utils/http";
|
import { http } from "@/utils/http";
|
||||||
|
import { UserBalance } from "./balance";
|
||||||
|
|
||||||
export interface Ab98UserDTO {
|
export interface Ab98UserDTO {
|
||||||
/** 主键ID */
|
/** 主键ID */
|
||||||
|
|
@ -64,7 +65,8 @@ export interface Ab98UserDetailDTO {
|
||||||
useBalance?: number;
|
useBalance?: number;
|
||||||
/** 借呗额度(单位:分) */
|
/** 借呗额度(单位:分) */
|
||||||
balanceLimit?: number;
|
balanceLimit?: number;
|
||||||
|
/** 用户余额实体 */
|
||||||
|
userBalanceEntity?: UserBalance;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Ab98UserQuery extends BasePageQuery {
|
export interface Ab98UserQuery extends BasePageQuery {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,87 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive, watch } from "vue";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
||||||
|
import { insertOrUpdateUserBalanceApi } from "@/api/ab98/balance";
|
||||||
|
import { useWxStore } from "@/store/modules/wx";
|
||||||
|
import Confirm from "@iconify-icons/ep/check";
|
||||||
|
import type { FormRules } from 'element-plus';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
row: {
|
||||||
|
type: Object,
|
||||||
|
default: null
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(["update:visible", "refresh"]);
|
||||||
|
|
||||||
|
const wxStore = useWxStore();
|
||||||
|
const formRef = ref();
|
||||||
|
const formData = reactive({
|
||||||
|
balanceLimit: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
const rules = reactive<FormRules>({
|
||||||
|
balanceLimit: [
|
||||||
|
{ required: true, message: "请输入金额", trigger: "blur" },
|
||||||
|
{ type: 'number', message: '必须为数字类型' },
|
||||||
|
{ validator: (_, v, cb) => v >= 0 ? cb() : cb(new Error('金额不能小于0')), trigger: 'blur' }
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleConfirm = async () => {
|
||||||
|
try {
|
||||||
|
await formRef.value.validate();
|
||||||
|
|
||||||
|
// 将元转换为分
|
||||||
|
const balanceLimitInFen = Math.round(formData.balanceLimit * 100);
|
||||||
|
|
||||||
|
await insertOrUpdateUserBalanceApi({
|
||||||
|
corpid: wxStore.corpid,
|
||||||
|
ab98UserId: props.row.ab98UserId,
|
||||||
|
balanceLimit: balanceLimitInFen
|
||||||
|
});
|
||||||
|
|
||||||
|
ElMessage.success("借呗额度修改成功");
|
||||||
|
emit("refresh");
|
||||||
|
closeDialog();
|
||||||
|
} catch (error) {
|
||||||
|
console.error("表单提交失败", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeDialog = () => {
|
||||||
|
formRef.value.resetFields();
|
||||||
|
emit("update:visible", false);
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(() => props.row, (val) => {
|
||||||
|
if (val) {
|
||||||
|
// 将分转换为元显示
|
||||||
|
formData.balanceLimit = val.balanceLimit ? val.balanceLimit / 100 : 0;
|
||||||
|
}
|
||||||
|
}, { immediate: true });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<el-dialog title="修改借呗额度" :model-value="visible" width="500px" @close="closeDialog">
|
||||||
|
<el-form ref="formRef" :model="formData" :rules="rules" label-width="80px">
|
||||||
|
<el-form-item label="金额" prop="balanceLimit">
|
||||||
|
<el-input-number v-model="formData.balanceLimit" :precision="2" :step="0.1" :min="0" controls-position="right"
|
||||||
|
class="!w-[200px]" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="closeDialog">取消</el-button>
|
||||||
|
<el-button type="primary" :icon="useRenderIcon(Confirm)" @click="handleConfirm">
|
||||||
|
确认
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
@ -8,6 +8,7 @@ import { ElMessage, ElMessageBox } from "element-plus";
|
||||||
import { PureTableBar } from "@/components/RePureTableBar";
|
import { PureTableBar } from "@/components/RePureTableBar";
|
||||||
import { useWxStore } from "@/store/modules/wx";
|
import { useWxStore } from "@/store/modules/wx";
|
||||||
import { formatFenToYuan } from "@/utils/currency";
|
import { formatFenToYuan } from "@/utils/currency";
|
||||||
|
import BalanceEditModal from "./BalanceEditModal.vue";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "Ab98UserDetail"
|
name: "Ab98UserDetail"
|
||||||
|
|
@ -23,6 +24,7 @@ const showAddTagDialog = ref(false);
|
||||||
const addTagForm = ref({
|
const addTagForm = ref({
|
||||||
tagName: ''
|
tagName: ''
|
||||||
});
|
});
|
||||||
|
const balanceVisible = ref(false);
|
||||||
|
|
||||||
// 基础信息
|
// 基础信息
|
||||||
const basicInfo = ref({
|
const basicInfo = ref({
|
||||||
|
|
@ -130,6 +132,10 @@ async function handleDeleteTag(tagId: number) {
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
fetchUserDetail();
|
fetchUserDetail();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
async function handleModifyBalance() {
|
||||||
|
balanceVisible.value = true;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -169,8 +175,11 @@ onMounted(() => {
|
||||||
<el-descriptions-item label="会员ID">{{ userInfo.ab98UserId }}</el-descriptions-item>
|
<el-descriptions-item label="会员ID">{{ userInfo.ab98UserId }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="微信openid">{{ userInfo.openid }}</el-descriptions-item>
|
<el-descriptions-item label="微信openid">{{ userInfo.openid }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="注册时间" :span="2">{{ userInfo.createTime }}</el-descriptions-item>
|
<el-descriptions-item label="注册时间" :span="2">{{ userInfo.createTime }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="借呗额度" :span="2">{{ formatFenToYuan(userInfo.balanceLimit)
|
<el-descriptions-item label="借呗额度" :span="2">{{ formatFenToYuan(userInfo.balanceLimit) }}
|
||||||
}}</el-descriptions-item>
|
<el-button type="primary" size="small" @click="handleModifyBalance">
|
||||||
|
修改
|
||||||
|
</el-button>
|
||||||
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="剩余借呗">{{ formatFenToYuan(userInfo.balance) }}</el-descriptions-item>
|
<el-descriptions-item label="剩余借呗">{{ formatFenToYuan(userInfo.balance) }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="已使用借呗">{{ formatFenToYuan(userInfo.useBalance) }}</el-descriptions-item>
|
<el-descriptions-item label="已使用借呗">{{ formatFenToYuan(userInfo.useBalance) }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="标签" :span="2">
|
<el-descriptions-item label="标签" :span="2">
|
||||||
|
|
@ -257,6 +266,7 @@ onMounted(() => {
|
||||||
<el-button type="primary" @click="handleAddTag">确定</el-button>
|
<el-button type="primary" @click="handleAddTag">确定</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
<BalanceEditModal v-model:visible="balanceVisible" :row="userInfo" @refresh="fetchUserDetail" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue