2025-09-09

修改创建直营用户
This commit is contained in:
2025-09-09 19:21:51 +08:00
parent 383f6d63c2
commit 8cb66058ae
2 changed files with 222 additions and 25 deletions

View File

@@ -209,6 +209,8 @@ const api = {
getDirectSales: (params) => request.get('/direct-sale', {params}),// 获取直营列表
createDirectSale: (data) => request.post('/direct-sale', data),// 创建直营
withdraw: (id) => request.post(`/direct-sale/${id}/withdraw`),// 提现
// 直营用户
addUser: (data) => request.post(`/users/create`, data),
},
// 文件上传

View File

@@ -6,7 +6,9 @@
<p>查看代理下的直营用户</p>
</div>
<el-button type="primary" @click="createDirectSaler">
<el-icon><Plus /></el-icon>
<el-icon>
<Plus/>
</el-icon>
创建直营
</el-button>
</div>
@@ -188,11 +190,70 @@
</div>
</el-card>
</div>
<el-dialog
v-model="dialogVisible"
:title="isEdit ? '编辑用户' : '添加直营用户'"
width="600px"
:before-close="handleDialogClose"
>
<el-form
ref="userFormRef"
:model="userForm"
:rules="userRules"
label-width="100px"
>
<el-form-item label="手机号" prop="phone">
<el-input
v-model="userForm.phone"
placeholder="请输入手机号"
maxlength="11"
/>
</el-form-item>
<el-form-item label="真实姓名" prop="real_name">
<el-input
v-model="userForm.real_name"
placeholder="请输入真实姓名"
/>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input
v-model="userForm.password"
type="password"
:placeholder="isEdit ? '留空则不修改密码' : '请输入密码'"
show-password
/>
</el-form-item>
<el-form-item label="头像" prop="avatar">
<el-upload
class="avatar-uploader"
:action="uploadAction"
:headers="uploadHeaders"
:show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload"
>
<img v-if="userForm.avatar" :src="getImageUrl(userForm.avatar)" class="avatar"/>
<el-icon v-else class="avatar-uploader-icon">
<Plus/>
</el-icon>
</el-upload>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleSubmit" :loading="submitting">
{{ isEdit ? '更新' : '创建' }}
</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup>
import {ref, reactive, onMounted} from 'vue'
import {ref, reactive, onMounted, computed} from 'vue'
import {ElMessage, ElMessageBox} from 'element-plus'
import {
Search,
@@ -204,6 +265,8 @@ import {
} from '@element-plus/icons-vue'
import api from '@/utils/api'
import {maskPhoneNumber} from '@/utils/public_method'
import {useUserStore} from "@/stores/user";
import {getImageUrl} from "@/utils/config";
// 响应式数据
const loading = ref(false)
@@ -232,15 +295,18 @@ const pagination = reactive({
// 创建直营
const createDirectSaler = async () => {
try {
console.log("创建直营数据:",directSaler)
await api.directSale.createDirectSale(directSaler.value)
ElMessage.success('创建直营成功')
getDirectSaleList()
} catch (error) {
console.log(error)
ElMessage.error('创建直营失败')
}
// try {
// console.log("创建直营数据:",directSaler)
// await api.directSale.createDirectSale(directSaler.value)
// ElMessage.success('创建直营成功')
// getDirectSaleList()
// } catch (error) {
// console.log(error)
// ElMessage.error('创建直营失败')
// }
isEdit.value = false
resetUserForm()
dialogVisible.value = true
}
// 获取直营列表
@@ -260,19 +326,19 @@ const getDirectSaleList = async () => {
pagination.total = response.data.data.pagination.total
} catch (error) {
directSaleList.value = [{
id: 1,
name: '张三',
phone: '13800000000',
beans_count: 1000,
level: 'normal',
created_at: '2023-01-01 00:00:00'
},{
id: 2,
name: '李四',
phone: '13900000000',
beans_count: 2000,
level: 'vip',
created_at: '2023-01-02 00:00:00'
id: 1,
name: '张三',
phone: '13800000000',
beans_count: 1000,
level: 'normal',
created_at: '2023-01-01 00:00:00'
}, {
id: 2,
name: '李四',
phone: '13900000000',
beans_count: 2000,
level: 'vip',
created_at: '2023-01-02 00:00:00'
}]
console.log(error)
ElMessage.error('获取直营列表失败')
@@ -335,7 +401,7 @@ const handleWithdraw = async (row) => {
const response = await api.directSale.withdraw(row.id)
ElMessage.success('提现操作成功')
// 刷新列表和统计数据
getDirectSaleList()
getDirectSaleStats()
@@ -373,6 +439,111 @@ const getLevelText = (level) => {
return levelMap[level] || '普通'
}
// 直营用户
const userStore = useUserStore()
const dialogVisible = ref(false)
const isEdit = ref(false)
const submitting = ref(false)
const userFormRef = ref()
const userForm = reactive({
username: '',
phone: '',
password: '',
avatar: '',
invite: '',
real_name: ''
})
const userRules = computed(() => ({
password: [
{required: !isEdit.value, message: '请输入密码', trigger: 'blur'},
{min: 6, message: '密码长度不能少于6位', trigger: 'blur'}
],
real_name: [
{required: true, message: '请输入真实姓名', trigger: 'blur'},
{min: 2, max: 10, message: '姓名长度在 2 到 10 个字符', trigger: 'blur'}
],
phone: [
{required: !isEdit.value, message: '请输入电话', trigger: 'blur'},
{pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号格式', trigger: 'blur'}
],
}))
// 头像上传
const uploadAction = '/api/upload/image'
const uploadHeaders = computed(() => {
const token = userStore.token || localStorage.getItem('admin_token')
if (!token) {
console.warn('上传时未找到认证令牌')
return {}
}
return {
Authorization: `Bearer ${token}`
}
})
// 头像上传前验证
const beforeAvatarUpload = (file) => {
const isJPG = file.type === 'image/jpeg' || file.type === 'image/png'
const isLt2M = file.size / 1024 / 1024 < 2
if (!isJPG) {
ElMessage.error('头像只能是 JPG/PNG 格式!')
}
if (!isLt2M) {
ElMessage.error('头像大小不能超过 2MB!')
}
return isJPG && isLt2M
}
// 头像上传成功
const handleAvatarSuccess = (response) => {
if (response.success) {
userForm.avatar = response.data.url
ElMessage.success('头像上传成功')
} else {
ElMessage.error('头像上传失败')
}
}
const handleSubmit = () => {
userFormRef.value.validate((valid) => {
if (valid) {
submitting.value = true
userForm.username = userForm.phone
if (!isEdit.value) {
// 新增
api.directSale.addUser(userForm).then((res) => {
console.log(res)
if (res.data.success) {
ElMessage.success('用户创建成功')
}
})
} else {
// TODO 编辑
}
dialogVisible.value = false
getDirectSaleList()
}
})
}
// 清空内容
const resetUserForm = () => {
Object.assign(userForm, {
username: '',
phone: '',
password: '',
avatar: '',
invite: '',
real_name: ''
})
}
// 关闭对话框
const handleDialogClose = () => {
resetUserForm()
dialogVisible.value = false
}
// 组件挂载时获取数据
onMounted(() => {
getDirectSaleList()
@@ -466,4 +637,28 @@ onMounted(() => {
justify-content: center;
margin-top: 20px;
}
/* 头像上传 */
.avatar-uploader {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: border-color 0.3s;
}
.avatar-uploader:hover {
border-color: #409eff;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 100px;
height: 100px;
line-height: 100px;
text-align: center;
display: block;
}
</style>