|
|
<script setup> import { ref, onMounted, reactive, computed, watch, nextTick } from 'vue' import { ElMessage } from 'element-plus' import { Plus } from '@element-plus/icons-vue' import axios from 'axios' import { ElMessageBox } from 'element-plus' import API from '@/util/http' import { uploadFile } from '@/util/request'; import moment from 'moment' import { range, re } from 'mathjs' import { utils, read } from 'xlsx' import throttle from 'lodash/throttle' // 定义 fixedAdminId
// const fixedAdminId = 1;
// 精网号去空格
const trimJwCode = () => { if (recharge.value.jwcode) { recharge.value.jwcode = recharge.value.jwcode.replace(/\s/g, ''); } } // 上传图片前的验证函数
const beforeAvatarUpload = (file) => { const validTypes = ['image/jpeg', 'image/png']; const isImage = validTypes.includes(file.type); const isLt1M = file.size / 1024 / 1024 < 1;
if (!isImage) { ElMessage.error('只能上传 JPG/PNG 图片!'); return false; } if (!isLt1M) { ElMessage.error('图片大小不能超过 1MB!'); return false; } return true; }; // 这是添加上传图片的接口
const imageUrl = ref('') const voucher = ref('') // const rateName = ref()
const adminData = ref({}) // 获取管理员信息
const getAdminData = async function () { try { const result = await API({ url: '/admin/userinfo', data: {} }) adminData.value = result recharge.value.adminId = adminData.value.id recharge.value.market = adminData.value.market console.log('请求成功', result) console.log('用户信息', user.value) } catch (error) { console.log('请求失败', error) } }
// 这是添加充值信息的表单
const recharge = ref({ jwcode: '', // jwcode 字段
activity: '', // activity 字段
voucher: '', rechargeWay: '客服充值', freeGold: '', money: null, permanentGold: '', rateName: null, rateId: null, payModel: '', // payModel 字段
payTime: null, // payTime 字段
remark: '', // remark 字段
rechargeRatio: '' }) // 这是添加充值信息的接口
const add = async function () { try {
const formattedRecharge = { ...recharge.value}
// 将永久金币数、免费金币数和充值金额数乘以 100
if (formattedRecharge.permanentGold) { formattedRecharge.permanentGold = Number(formattedRecharge.permanentGold) * 100; } if (formattedRecharge.freeGold) { formattedRecharge.freeGold = Number(formattedRecharge.freeGold) * 100; } if (formattedRecharge.money) { formattedRecharge.money = Number(formattedRecharge.money) * 100; }
if (formattedRecharge.payTime) { // 使用 moment.js 格式化 payTime
formattedRecharge.payTime = moment(formattedRecharge.payTime).format('YYYY-MM-DD HH:mm:ss') }
console.log('开始添加充值信息', recharge.value) // 发送POST请求
const result = await API({ url: '/recharge/add', data: formattedRecharge }) if (result.code === 0) { ElMessage.error(result.msg) return } // 将响应结果存储到响应式数据中
console.log('请求成功', result) // 显示成功消息
ElMessage.success('添加成功') // 重置表单
recharge.value = {} recharge.value.adminId = adminData.value.id recharge.value.market = adminData.value.market recharge.value.voucher = '' recharge.value.rechargeWay = '客服充值' recharge.value.freeGold = '' recharge.value.money = null recharge.value.permanentGold = '' recharge.value.rateId = null imageUrl.value = '' recharge.value.rateName = null user.value = {} } catch (error) { console.log('请求失败', error) // 在这里可以处理错误逻辑,比如显示错误提示等
} }
//添加充值信息前的按钮点击事件,进行表单验证和用户确认操作
const addBefore = () => { Ref.value.validate(async (valid) => { if (valid) { if (recharge.value.rateName == null || recharge.value.rateName == '' || recharge.value.rateName == undefined) { ElMessage({ type: 'error', message: '请选择币种' }) return } if(recharge.value.money == null || recharge.value.money == '' || recharge.value.money == undefined){ ElMessage({ type: 'error', message: '请输入充值金额' }) return } // 根据选择的货币名称找到对应的 rateId
const selectedRate = rateName.find(item => item.value === recharge.value.rateName) if (selectedRate) { recharge.value.rateId = selectedRate.rateId } ElMessageBox.confirm('确认充值?') .then(() => { add() console.log('充值成功') }) .catch(() => { console.log('取消充值') }) } else { //提示
ElMessage({ type: 'error', message: '请检查输入内容' }) } }) }
// 表单验证
// 开始时间改变时,重新验证结束时间
const Ref = ref(null)
const rules = reactive({ jwcode: [{ required: true, message: '请输入精网号', trigger: 'blur' }], activity: [{ required: true, message: '请选择活动名称', trigger: 'blur' }], permanentGold: [ { required: true, message: '请输入永久金币数', trigger: 'blur' }, { validator: (rule, value, callback) => { // 检查是否包含特殊符号
if (/[^0-9.]/.test(value)) { callback(new Error('不能包含特殊符号或负数')); return; }
// 检查整数位数
const integerPart = value.split('.')[0]; if (integerPart.length > 6) { callback(new Error('整数位数不能超过6位')); return; } // 检查小数位数
if (value.includes('.')) { const decimalPart = value.split('.')[1]; if (decimalPart.length > 2) { callback(new Error('小数位数不能超过两位')); return; } } const numValue = Number(value); if (isNaN(numValue)) { callback(new Error('请输入有效的数字')); } else if (numValue <= 0) { callback(new Error('输入金额必须大于0')); } else { callback(); } }, trigger: 'blur' } ], freeGold: [ { required: true, message: '请输入免费金币数', trigger: 'blur' }, { validator: (rule, value, callback) => { // 检查是否包含特殊符号
if (/[^0-9.]/.test(value)) { callback(new Error('不能包含特殊符号或负数')); return; }
// 检查整数位数
const integerPart = value.split('.')[0]; if (integerPart.length > 6) { callback(new Error('整数位数不能超过6位')); return; }
// 检查小数位数
if (value.includes('.')) { const decimalPart = value.split('.')[1]; if (decimalPart.length > 2) { callback(new Error('小数位数不能超过两位')); return; } }
const numValue = Number(value); if (isNaN(numValue)) { callback(new Error('请输入有效的数字')); } else if (numValue < 0) { callback(new Error('输入金额不能小于0')); } else { callback(); } }, trigger: 'blur' } ], rateName: [{ required: true, message: '请选择货币名称', trigger: 'blur' }], money: [ { required: true, message: '请输入充值金额', trigger: 'blur' }, { validator: (rule, value, callback) => { // 检查是否包含特殊符号
if (/[^0-9.]/.test(value)) { callback(new Error('不能包含特殊符号或负数')); return; }
// 检查整数位数
const integerPart = value.split('.')[0]; if (integerPart.length > 6) { callback(new Error('整数位数不能超过6位')); return; }
// 检查小数位数
if (value.includes('.')) { const decimalPart = value.split('.')[1]; if (decimalPart.length > 2) { callback(new Error('小数位数不能超过两位')); return; } }
const numValue = Number(value); if (isNaN(numValue)) { callback(new Error('请输入有效的数字')); } else if (numValue <= 0) { callback(new Error('输入金额必须大于0')); } else { callback(); } }, trigger: 'blur' } ], payModel: [{ required: true, message: '请选择付款方式', trigger: 'blur' }], payTime: [{ required: true, message: '请选择交款时间', trigger: 'blur' }] });
// 查找客户信息的方法
const user = ref({}) const getUser = async function (jwcode) { trimJwCode(); try {
// 发送POST请求
const result = await API({ url: '/user/selectUser', data: { jwcode: recharge.value.jwcode } }) console.log('请求成功', result)
if (result.code === 0) { ElMessage.error(result.msg); } else if (result.data === null) { ElMessage.error("用户不存在"); recharge.value.jwcode = '' } else { user.value = result.data; console.log("用户信息", user.value); ElMessage.success(result.msg); } } catch (error) { console.log("请求失败", error); ElMessage.error("精网号错误"); recharge.value.jwcode = '' } }
// 这是查询活动的接口,一期没有调用这个接口
const activity = ref([]) // const getActivity = async function () {
// try {
// // 发送POST请求
// const result = await API({
// url: '/general/activity',
// data: {
// }
// })
// // 将响应结果存储到响应式数据中
// console.log('请求成功', result)
// // 存储表格数据
// activity.value = result.data
// console.log('活动信息', activity.value)
// } catch (error) {
// console.log('activity请求失败', error)
// // 在这里可以处理错误逻辑,比如显示错误提示等
// }
// }
//货币条目
const rateName = [ { value: 'USD', label: 'USD', rateId: 1 }, { value: 'HKD', label: 'HKD', rateId: 2 }, { value: 'THB', label: 'THB', rateId: 3 }, { value: 'VND', label: 'VND', rateId: 4 }, { value: 'CAD', label: 'CAD', rateId: 5 }, { value: 'MYR', label: 'MYR', rateId: 6 }, { value: 'KRW', label: 'KRW', rateId: 7 }, { value: 'JPY', label: 'JPY', rateId: 8 }, { value: 'CNY', label: 'CNY', rateId: 9 } ]
// 修改上传处理
const customUpload = async (options) => { try { const formData = new FormData(); formData.append('file', options.file); const response = await axios.post(import.meta.env.VITE_UPLOAD_URL, formData, { headers: { 'Content-Type': 'multipart/form-data', 'Authorization': `Bearer ${localStorage.getItem('token')}` } }); if (response.data.code === 200 && response.data.data) { // 传递原始文件对象和响应数据
handleAvatarSuccess(response.data, options.file); ElMessage.success('上传成功'); } else { ElMessage.error(response.data.msg || '上传失败'); } } catch (error) { console.error('上传错误:', error); ElMessage.error(`上传失败: ${error.response?.data?.message || error.message}`); } };
// 获取环境变量
// const uploadUrl = import.meta.env.VITE_UPLOAD_URL;
// 上传图片成功的回调函数
const handleAvatarSuccess = (response, file) => { // 直接使用 file 对象创建 Object URL
imageUrl.value = URL.createObjectURL(file); // 使用服务器返回的文件路径(根据实际响应结构调整)
if (response && response.filePath) { recharge.value.voucher = response.filePath; } else if (response && response.url) { recharge.value.voucher = response.url; } else if (response && response.data) { // 假设响应结构为 { code: 200, data: { filePath: ... } }
recharge.value.voucher = response.data.filePath || response.data.url; } else { // 后备方案:使用环境变量中的上传URL
recharge.value.voucher = import.meta.env.VITE_UPLOAD_URL; } }
//支付方式条目
const payModel = [ { value: '现金', label: '现金' }, { value: '支票', label: '支票' }, { value: '刷卡', label: '刷卡' }, { value: '其他(各地区电子支付)', label: '其他(各地区电子支付)' } ]
// }
function handleActivityChange(value) { // 在这里执行你的逻辑,例如获取选中的值
console.log('选中的值:', value) getActivityById(value) console.log('看看', recharge.value) }
//这是重置重置表单的方法
const deleteRecharge = function () { recharge.value = { adminId: adminData.value.id, //adminId: fixedAdminId,
market: adminData.value.market, voucher: '', rechargeWay: '客服充值', freeGold: Number(), money: null, permanentGold: Number(), rateId: null } imageUrl.value = '' recharge.value.rateName = '' }
onMounted(async function () { await getAdminData() // await getCurrency()
await getActivity()// 现在的活动就是文字输入框,不需要请求接口,具体等后续需求
}) onMounted(() => { console.log('上传URL:', import.meta.env.VITE_UPLOAD_URL); }); </script>
<template> <div>
<el-form :model="recharge" ref="Ref" :rules="rules" label-width="auto" style="max-width: 600px" class="add-form" > <el-form-item prop="jwcode" label="精网号"> <el-input v-model="recharge.jwcode" style="width: 220px" @blur="getUser(recharge.jwcode)" /> <el-button type="primary" style="margin-left: 20px" >查询</el-button > </el-form-item> <!-- <el-form-item prop="activity" label="活动名称"> <el-select v-model="recharge.activity" placeholder="请选择" style="width: 300px" @change="handleActivityChange" > <el-option v-for="(item, index) in activity" :key="index" :label="item" :value="item" /> </el-select> </el-form-item> --> <el-form-item prop="activity" label="活动名称"> <el-input v-model="recharge.activity" placeholder="请输入活动名称" style="width: 300px" /> </el-form-item> <el-form-item prop="permanentGold" label="永久金币"> <el-input v-model="recharge.permanentGold" style="width: 100px" /> <p>个</p> </el-form-item> <el-form-item prop="freeGold" label="免费金币"> <el-input v-model="recharge.freeGold" style="width: 100px" /> <p>个</p> </el-form-item> <!-- <el-form-item label="充值金额"> <el-select prop="moneys" v-model="rateName" placeholder="货币名称" style="width: 95px; margin-right: 5px" aria-required="true" > <el-option v-for="item in rateName" :key="item.value" :label="item.label" :value="item.value" /> </el-select> <el-input prop="money" v-model="recharge.money" style="width: 200px" aria-required="true"/> </el-form-item> -->
<el-form-item label="充值金额" required> <!-- 货币名称 --> <el-form-item prop="rateName" style="display: inline-block; margin-left:0;"> <el-select v-model="recharge.rateName" placeholder="货币名称" style="width: 100px" > <el-option v-for="item in rateName" :key="item.value" :label="item.label" :value="item.value" /> </el-select> </el-form-item> <!-- 充值金额 --> <el-form-item prop="money" style="display: inline-block; margin-left:10px;"> <el-input v-model="recharge.money" style="width: 190px"/> </el-form-item> </el-form-item>
<el-form-item prop="payModel" label="收款方式"> <el-select v-model="recharge.payModel" placeholder="请选择" style="width: 300px" > <el-option v-for="item in payModel" :key="item.value" :label="item.label" :value="item.value" /> </el-select> </el-form-item> <el-form-item prop="payTime" label="交款时间"> <!-- 修改 type 属性为 datetime 以支持时分秒选择 --> <el-date-picker v-model="recharge.payTime" type="datetime" style="width: 300px" /> </el-form-item> <el-form-item prop="voucher" label="交款凭证" style="margin-bottom: 5px" > <el-upload :http-request="customUpload" class="avatar-uploader" :show-file-list="false" :before-upload="beforeAvatarUpload" style="width: 100px; height: 115px" > <img v-if="imageUrl" :src="imageUrl" class="avatar" style="width: 100px; height: 115px" /> <el-icon v-else class="avatar-uploader-icon" style="width: 100px; height: 100px" > <Plus /> </el-icon> </el-upload> <p style="margin-left: 10px; color: rgb(177, 176, 176)"> 仅支持.jpg .png格式,文件≤1MB </p> </el-form-item> <el-form-item prop="remark" label="备注"> <el-input v-model="recharge.remark" style="width: 300px" :rows="2" maxlength="100" show-word-limit type="textarea" /> </el-form-item> <el-form-item prop="adminName" label="提交人"> <el-input style="width: 300px" :value="adminData.adminName" disabled placeholder="提交人姓名" /> </el-form-item> <el-button @click="deleteRecharge" style="margin-left: 280px" type="success" >重置</el-button > <el-button type="primary" @click="addBefore"> 提交 </el-button> </el-form>
<!-- 客户信息栏 --> <el-card v-if="user.jwcode" style="width: 800px; float: right" class="customer-info"> <el-form :model="user" label-width="auto" style="max-width: 1000px" label-position="left" > <el-text size="large" style="margin-left: 20px">客户信息</el-text>
<!-- 第一行:姓名 + 历史金币 --> <el-row style="margin-top: 20px"> <el-col :span="9"> <el-form-item label="姓名:"> <p>{{ user.name }}</p> </el-form-item> </el-col> <el-col :span="14"> <el-form-item label="历史金币总数"> <!-- 检查 user.historySumGold 是否为有效的数字 --> <p style="color: #2fa1ff; margin-right: 5px" v-if="!isNaN(Number(user.historySumGold))"> {{ Number(user.historySumGold ) /100 }} </p> <!-- 如果不是有效的数字,显示默认值 --> <p v-else></p> </el-form-item> <el-form-item style="margin-top: -23px"> <span style="display: inline; white-space: nowrap; color: #b1b1b1" v-if="user.historyPermanentGold !== undefined" >(永久金币:{{ user.historyPermanentGold /100 }};免费金币:{{ (user.historyFreeGold) /100 }};任务金币:{{ user.historyTaskGold /100}})</span> </el-form-item> </el-col> </el-row>
<!-- 第二行:精网号 + 当前金币(独立行) --> <el-row style="margin-top:-23px"> <el-col :span="9"> <el-form-item label="精网号"> <p>{{ user.jwcode }}</p> </el-form-item> </el-col> <el-col :span="14"> <el-form-item label="当前金币总数" style="width: 500px"> <span style="color: #2fa1ff; margin-right: 5px" v-if="user.nowSumGold !== undefined" >{{ user.nowSumGold /100}}</span> </el-form-item> <!-- 金币详情独立显示 --> <el-form-item style="margin-top: -23px"> <!-- 负边距减少间距 --> <span style="color: #b1b1b1; margin-left: 0px" v-if="user.nowPermanentGold !== undefined" >(永久金币:{{ user.nowPermanentGold /100}}; 免费金币:{{ user.nowFreeGold /100}}; 任务金币:{{ user.nowTaskGold /100}})</span> </el-form-item> </el-col> </el-row>
<!-- 第三行:首次充值日期 + 充值次数 --> <el-row style="margin-top:-23px"> <el-col :span="9"> <el-form-item label="首次充值日期"> <p v-if="user.firstRecharge"> {{ moment(user.firstRecharge).format('YYYY-MM-DD HH:mm:ss') }} </p> </el-form-item> </el-col> <el-col :span="14"> <el-form-item label="充值次数"> <p style="color: #2fa1ff">{{ user.rechargeNum }}</p> </el-form-item> </el-col> </el-row>
<!-- 第四行:消费次数 + 所属门店 --> <el-row> <el-col :span="9"> <el-form-item label="消费次数"> <p style="color: #2fa1ff">{{ user.consumeNum }}</p> </el-form-item> </el-col> <el-col :span="9"> <el-form-item label="所属门店"> <p>{{ user.market }}</p> </el-form-item> </el-col> </el-row> </el-form> </el-card>
</div> </template>
<style scoped> p { margin: 0px; }
.batch-btn { margin-top: 20px; margin-left: auto; }
.el-form-item { margin-left: 50px; }
/* 上传图片的格式 */ .avatar-uploader .avatar { width: 50px; height: 50px; display: block; } </style>
<style> .error-message { color: red; font-size: 8px; }
.is-invalid .el-input__inner { border-color: red; }
.avatar-uploader .el-upload { border: 1px dashed var(--el-border-color); border-radius: 6px; cursor: pointer; position: relative; overflow: hidden; transition: var(--el-transition-duration-fast); }
.avatar-uploader .el-upload:hover { border-color: var(--el-color-primary); }
.el-icon.avatar-uploader-icon { font-size: 28px; color: #8c939d; width: 50px; height: 50px; text-align: center; }
.add-form { margin-top: 50px; max-width: 50%; float: left; }
.customer-info { max-width: 60%; } </style>
|