feat: 替换用户管理模块的模拟数据为真实接口,并优化额度设置功能
This commit is contained in:
parent
7c64f0c76a
commit
2ff5421c27
74
menu_init.sql
Normal file
74
menu_init.sql
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
-- 完整菜单初始化SQL
|
||||||
|
-- 创建时间: 2025-11-20
|
||||||
|
-- 说明: 包含所有新增的菜单项和权限分配
|
||||||
|
|
||||||
|
-- ========================================
|
||||||
|
-- 1. 工作台菜单
|
||||||
|
-- ========================================
|
||||||
|
INSERT INTO menu (id, name, menu_type, icon, path, "order", parent_id, is_hidden, component, keepalive, redirect, created_at, updated_at)
|
||||||
|
VALUES
|
||||||
|
(22, '工作台', 'menu', 'carbon:dashboard', '/workbench', 1, 0, 0, '/workbench', 1, NULL, datetime('now'), datetime('now'));
|
||||||
|
|
||||||
|
-- ========================================
|
||||||
|
-- 2. 交易管理菜单
|
||||||
|
-- ========================================
|
||||||
|
-- 插入一级目录:交易管理
|
||||||
|
INSERT INTO menu (id, name, menu_type, icon, path, "order", parent_id, is_hidden, component, keepalive, redirect, created_at, updated_at)
|
||||||
|
VALUES
|
||||||
|
(16, '交易管理', 'catalog', 'carbon:receipt', '/transaction', 3, 0, 0, 'Layout', 0, '/transaction/invoice', datetime('now'), datetime('now'));
|
||||||
|
|
||||||
|
-- 插入二级菜单:开票记录
|
||||||
|
INSERT INTO menu (id, name, menu_type, icon, path, "order", parent_id, is_hidden, component, keepalive, redirect, created_at, updated_at)
|
||||||
|
VALUES
|
||||||
|
(17, '开票记录', 'menu', 'carbon:document', 'invoice', 1, 16, 0, '/transaction/invoice', 0, NULL, datetime('now'), datetime('now'));
|
||||||
|
|
||||||
|
-- ========================================
|
||||||
|
-- 3. 估值管理菜单
|
||||||
|
-- ========================================
|
||||||
|
-- 插入一级目录:估值管理
|
||||||
|
INSERT INTO menu (id, name, menu_type, icon, path, "order", parent_id, is_hidden, component, keepalive, redirect, created_at, updated_at)
|
||||||
|
VALUES
|
||||||
|
(18, '估值管理', 'catalog', 'carbon:calculator', '/valuation', 4, 0, 0, 'Layout', 0, '/valuation/audit', datetime('now'), datetime('now'));
|
||||||
|
|
||||||
|
-- 插入二级菜单:审核列表
|
||||||
|
INSERT INTO menu (id, name, menu_type, icon, path, "order", parent_id, is_hidden, component, keepalive, redirect, created_at, updated_at)
|
||||||
|
VALUES
|
||||||
|
(19, '审核列表', 'menu', 'carbon:task-approved', 'audit', 1, 18, 0, '/valuation/audit', 0, NULL, datetime('now'), datetime('now'));
|
||||||
|
|
||||||
|
-- ========================================
|
||||||
|
-- 4. 用户管理菜单
|
||||||
|
-- ========================================
|
||||||
|
-- 插入一级目录:用户管理
|
||||||
|
INSERT INTO menu (id, name, menu_type, icon, path, "order", parent_id, is_hidden, component, keepalive, redirect, created_at, updated_at)
|
||||||
|
VALUES
|
||||||
|
(20, '用户管理', 'catalog', 'carbon:user-multiple', '/user-management', 5, 0, 0, 'Layout', 0, '/user-management/user-list', datetime('now'), datetime('now'));
|
||||||
|
|
||||||
|
-- 插入二级菜单:用户列表
|
||||||
|
INSERT INTO menu (id, name, menu_type, icon, path, "order", parent_id, is_hidden, component, keepalive, redirect, created_at, updated_at)
|
||||||
|
VALUES
|
||||||
|
(21, '用户列表', 'menu', 'carbon:user', 'user-list', 1, 20, 0, '/user-management/user-list', 0, NULL, datetime('now'), datetime('now'));
|
||||||
|
|
||||||
|
-- ========================================
|
||||||
|
-- 角色权限分配
|
||||||
|
-- ========================================
|
||||||
|
|
||||||
|
-- 为管理员角色(role_id=1)分配所有菜单权限
|
||||||
|
INSERT INTO role_menu (role_id, menu_id)
|
||||||
|
VALUES
|
||||||
|
(1, 22), -- 工作台
|
||||||
|
(1, 16), -- 交易管理
|
||||||
|
(1, 17), -- 开票记录
|
||||||
|
(1, 18), -- 估值管理
|
||||||
|
(1, 19), -- 审核列表
|
||||||
|
(1, 20), -- 用户管理
|
||||||
|
(1, 21); -- 用户列表
|
||||||
|
|
||||||
|
-- 为普通用户角色(role_id=2)分配基础菜单权限
|
||||||
|
INSERT INTO role_menu (role_id, menu_id)
|
||||||
|
VALUES
|
||||||
|
(2, 22), -- 工作台
|
||||||
|
(2, 16), -- 交易管理
|
||||||
|
(2, 17), -- 开票记录
|
||||||
|
(2, 18), -- 估值管理
|
||||||
|
(2, 19); -- 审核列表
|
||||||
|
-- 注意:普通用户不分配用户管理权限
|
||||||
@ -5,4 +5,4 @@ VITE_PUBLIC_PATH = '/'
|
|||||||
VITE_USE_PROXY = true
|
VITE_USE_PROXY = true
|
||||||
|
|
||||||
# base api
|
# base api
|
||||||
VITE_BASE_API = '/api/v1'
|
VITE_BASE_API = 'http://139.224.70.152:9990/api/v1'
|
||||||
|
|||||||
@ -276,120 +276,6 @@ const mockValuationDetails = valuationRecords.map((record) => ({
|
|||||||
...record,
|
...record,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const mockAppUsers = [
|
|
||||||
{
|
|
||||||
id: 11111111,
|
|
||||||
phone: '15021982682',
|
|
||||||
wechat: 'f1498480844',
|
|
||||||
created_at: '2024-01-15T10:30:00Z',
|
|
||||||
notes: '测试用户1',
|
|
||||||
remaining_count: 1,
|
|
||||||
user_type: '体验用户',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 11111112,
|
|
||||||
phone: '13800138002',
|
|
||||||
wechat: 'wx_limming2024',
|
|
||||||
created_at: '2024-02-20T14:20:00Z',
|
|
||||||
notes: '付费用户',
|
|
||||||
remaining_count: 5,
|
|
||||||
user_type: '付费用户',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 11111113,
|
|
||||||
phone: '13800138003',
|
|
||||||
wechat: null,
|
|
||||||
created_at: '2024-03-10T08:45:00Z',
|
|
||||||
notes: null,
|
|
||||||
remaining_count: 0,
|
|
||||||
user_type: '体验用户',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 11111114,
|
|
||||||
phone: '13800138004',
|
|
||||||
wechat: 'chenjun_vip',
|
|
||||||
created_at: '2024-04-05T11:30:00Z',
|
|
||||||
notes: 'VIP用户',
|
|
||||||
remaining_count: 10,
|
|
||||||
user_type: 'VIP',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 11111115,
|
|
||||||
phone: '13800138005',
|
|
||||||
wechat: 'liuxia888',
|
|
||||||
created_at: '2024-05-12T16:15:00Z',
|
|
||||||
notes: '体验用户',
|
|
||||||
remaining_count: 3,
|
|
||||||
user_type: '体验用户',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 11111116,
|
|
||||||
phone: '13800138006',
|
|
||||||
wechat: null,
|
|
||||||
created_at: '2024-06-18T09:00:00Z',
|
|
||||||
notes: '新注册用户',
|
|
||||||
remaining_count: 2,
|
|
||||||
user_type: '体验用户',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 11111117,
|
|
||||||
phone: '13800138007',
|
|
||||||
wechat: 'zhaolei2024',
|
|
||||||
created_at: '2024-07-22T12:45:00Z',
|
|
||||||
notes: null,
|
|
||||||
remaining_count: 0,
|
|
||||||
user_type: '体验用户',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 11111118,
|
|
||||||
phone: '13800138008',
|
|
||||||
wechat: 'sunmei_user',
|
|
||||||
created_at: '2024-08-30T15:20:00Z',
|
|
||||||
notes: '活跃用户',
|
|
||||||
remaining_count: 7,
|
|
||||||
user_type: 'VIP',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
const defaultInvoiceHeaders = [
|
|
||||||
{
|
|
||||||
company_name: '成都文创科技有限公司',
|
|
||||||
tax_number: '91510100MA7XYZ1234',
|
|
||||||
register_address: '四川省成都市高新区天府三街666号',
|
|
||||||
register_phone: '028-66666666',
|
|
||||||
bank_name: '招商银行成都分行',
|
|
||||||
bank_account: '6225 6666 8888 0000',
|
|
||||||
email: 'finance@scwenchuang.com',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
company_name: '天府文化发展有限公司',
|
|
||||||
tax_number: '91510100678912345K',
|
|
||||||
register_address: '四川省成都市武侯区科华北路88号',
|
|
||||||
register_phone: '028-12345678',
|
|
||||||
bank_name: '中国工商银行成都分行',
|
|
||||||
bank_account: '6212 8888 0000 9999',
|
|
||||||
email: 'invoice@tfculture.com',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
const defaultOperationLogs = [
|
|
||||||
{
|
|
||||||
time: '2025-10-31 18:30:30',
|
|
||||||
operator: 'admin',
|
|
||||||
records: ['剩余估值次数:0 -> 1', '类型:付费估值', '备注:新用户'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
time: '2025-10-31 18:30:30',
|
|
||||||
operator: 'admin',
|
|
||||||
records: ['剩余估值次数:2 -> 1', '类型:付费估值', '备注:退款'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
time: '2025-10-31 18:30:30',
|
|
||||||
operator: 'admin',
|
|
||||||
records: ['用户备注:111111111111 -> 22222222222222222222'],
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
login: (data) => request.post('/base/access_token', data, { noNeedToken: true }),
|
login: (data) => request.post('/base/access_token', data, { noNeedToken: true }),
|
||||||
getUserInfo: () => request.get('/base/userinfo'),
|
getUserInfo: () => request.get('/base/userinfo'),
|
||||||
@ -430,73 +316,10 @@ export default {
|
|||||||
// auditlog
|
// auditlog
|
||||||
getAuditLogList: (params = {}) => request.get('/auditlog/list', { params }),
|
getAuditLogList: (params = {}) => request.get('/auditlog/list', { params }),
|
||||||
// app users (客户端用户管理) - 使用现有的后端接口
|
// app users (客户端用户管理) - 使用现有的后端接口
|
||||||
getAppUserList: (params = {}) => {
|
getAppUserList: (params = {}) => request.get('/app-user-admin/list', { params }),
|
||||||
// 模拟分页和搜索
|
updateAppUserQuota: (data = {}) => request.post('/app-user-admin/quota', data),
|
||||||
let filteredUsers = [...mockAppUsers]
|
getAppUserQuotaLogs: ({ user_id, ...params } = {}) =>
|
||||||
|
request.get(`/app-user-admin/${user_id}/quota-logs`, { params }),
|
||||||
// 手机号搜索
|
|
||||||
if (params.phone) {
|
|
||||||
filteredUsers = filteredUsers.filter(user =>
|
|
||||||
user.phone.includes(params.phone)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 微信号搜索
|
|
||||||
if (params.wechat) {
|
|
||||||
filteredUsers = filteredUsers.filter(user =>
|
|
||||||
user.wechat && user.wechat.includes(params.wechat)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 注册时间筛选(日期范围)
|
|
||||||
if (params.created_at && Array.isArray(params.created_at) && params.created_at.length === 2) {
|
|
||||||
const [startTime, endTime] = params.created_at
|
|
||||||
filteredUsers = filteredUsers.filter(user => {
|
|
||||||
if (!user.created_at) return false
|
|
||||||
const userTime = new Date(user.created_at).getTime()
|
|
||||||
return userTime >= startTime && userTime <= endTime
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分页处理
|
|
||||||
const page = Number(params.page) || 1
|
|
||||||
const pageSize = Number(params.page_size) || 10
|
|
||||||
const startIndex = (page - 1) * pageSize
|
|
||||||
const endIndex = startIndex + pageSize
|
|
||||||
const paginatedUsers = filteredUsers.slice(startIndex, endIndex)
|
|
||||||
|
|
||||||
// 返回 Promise 模拟异步请求
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
setTimeout(() => {
|
|
||||||
resolve({
|
|
||||||
data: paginatedUsers,
|
|
||||||
total: filteredUsers.length,
|
|
||||||
page,
|
|
||||||
page_size: pageSize,
|
|
||||||
})
|
|
||||||
}, 300)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
getAppUserById: (params = {}) =>
|
|
||||||
new Promise((resolve) => {
|
|
||||||
const id = Number(params.id)
|
|
||||||
const user = mockAppUsers.find((item) => item.id === id) || {}
|
|
||||||
setTimeout(() => {
|
|
||||||
resolve({
|
|
||||||
baseInfo: {
|
|
||||||
id: user.id,
|
|
||||||
phone: user.phone,
|
|
||||||
wechat: user.wechat,
|
|
||||||
register_time: user.created_at,
|
|
||||||
notes: user.notes,
|
|
||||||
remaining_count: user.remaining_count,
|
|
||||||
user_type: user.user_type || '体验用户',
|
|
||||||
},
|
|
||||||
invoiceHeaders: defaultInvoiceHeaders,
|
|
||||||
operationLogs: defaultOperationLogs,
|
|
||||||
})
|
|
||||||
}, 300)
|
|
||||||
}),
|
|
||||||
createAppUser: (data = {}) => request.post('/app-user/register', data),
|
createAppUser: (data = {}) => request.post('/app-user/register', data),
|
||||||
updateAppUser: (data = {}) => request.post('/app-user/update', data),
|
updateAppUser: (data = {}) => request.post('/app-user/update', data),
|
||||||
deleteAppUser: (params = {}) => request.delete('/app-user/delete', { params }),
|
deleteAppUser: (params = {}) => request.delete('/app-user/delete', { params }),
|
||||||
|
|||||||
@ -1,12 +1,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, watch } from 'vue'
|
import { computed, ref, watch } from 'vue'
|
||||||
import {
|
import { NModal, NButton, NSelect, NInput, NDivider, NInputNumber } from 'naive-ui'
|
||||||
NModal,
|
|
||||||
NButton,
|
|
||||||
NSelect,
|
|
||||||
NInput,
|
|
||||||
NDivider,
|
|
||||||
} from 'naive-ui'
|
|
||||||
|
|
||||||
// Props
|
// Props
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -25,44 +19,37 @@ const emit = defineEmits(['update:visible', 'save'])
|
|||||||
|
|
||||||
// 本地状态
|
// 本地状态
|
||||||
const limitForm = ref({
|
const limitForm = ref({
|
||||||
remainingCount: 0,
|
targetCount: 0,
|
||||||
type: '免费体验',
|
quotaType: '免费体验',
|
||||||
experienceCount: 1,
|
remark: ''
|
||||||
notes: ''
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// 类型选项
|
// 类型选项
|
||||||
const typeOptions = [
|
const typeOptions = [
|
||||||
{ label: '免费体验', value: '免费体验' },
|
{ label: '免费体验', value: '免费体验' },
|
||||||
{ label: '付费用户', value: '付费用户' },
|
{ label: '付费评估', value: '付费评估' }
|
||||||
{ label: 'VIP用户', value: 'VIP用户' }
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const currentRemaining = computed(() => props.userData?.remaining_count ?? 0)
|
||||||
|
|
||||||
// 监听用户数据变化,初始化表单
|
// 监听用户数据变化,初始化表单
|
||||||
watch(() => props.userData, (newData) => {
|
watch(() => props.userData, (newData) => {
|
||||||
if (newData && Object.keys(newData).length > 0) {
|
if (newData && Object.keys(newData).length > 0) {
|
||||||
limitForm.value = {
|
limitForm.value = {
|
||||||
remainingCount: newData.remaining_count || 0,
|
targetCount: newData.remaining_count || 0,
|
||||||
type: newData.user_type || '免费体验',
|
quotaType: newData.user_type || '免费体验',
|
||||||
experienceCount: newData.experience_count || 1,
|
remark: ''
|
||||||
notes: newData.notes || ''
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, { immediate: true })
|
}, { immediate: true })
|
||||||
|
|
||||||
// 体验次数增减
|
|
||||||
function handleExperienceCountChange(delta) {
|
|
||||||
const newCount = limitForm.value.experienceCount + delta
|
|
||||||
if (newCount >= 0) {
|
|
||||||
limitForm.value.experienceCount = newCount
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保存设置
|
// 保存设置
|
||||||
function handleSave() {
|
function handleSave() {
|
||||||
const data = {
|
const data = {
|
||||||
user_id: props.userData.id,
|
user_id: props.userData.id,
|
||||||
...limitForm.value
|
target_count: Number(limitForm.value.targetCount || 0),
|
||||||
|
op_type: limitForm.value.quotaType,
|
||||||
|
remark: limitForm.value.remark
|
||||||
}
|
}
|
||||||
emit('save', data)
|
emit('save', data)
|
||||||
}
|
}
|
||||||
@ -72,10 +59,9 @@ function handleCancel() {
|
|||||||
emit('update:visible', false)
|
emit('update:visible', false)
|
||||||
// 重置表单
|
// 重置表单
|
||||||
limitForm.value = {
|
limitForm.value = {
|
||||||
remainingCount: 0,
|
targetCount: 0,
|
||||||
type: '免费体验',
|
quotaType: '免费体验',
|
||||||
experienceCount: 1,
|
remark: ''
|
||||||
notes: ''
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@ -96,7 +82,7 @@ function handleCancel() {
|
|||||||
<!-- 剩余估值次数 -->
|
<!-- 剩余估值次数 -->
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<span class="label">剩余估值次数:</span>
|
<span class="label">剩余估值次数:</span>
|
||||||
<span class="value">{{ limitForm.remainingCount }}</span>
|
<span class="value">{{ currentRemaining }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<NDivider style="margin: 16px 0;" />
|
<NDivider style="margin: 16px 0;" />
|
||||||
@ -105,31 +91,20 @@ function handleCancel() {
|
|||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<span class="label">类型:</span>
|
<span class="label">类型:</span>
|
||||||
<NSelect
|
<NSelect
|
||||||
v-model:value="limitForm.type"
|
v-model:value="limitForm.quotaType"
|
||||||
:options="typeOptions"
|
:options="typeOptions"
|
||||||
style="width: 120px;"
|
style="width: 120px;"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 体验次数 -->
|
<!-- 目标次数 -->
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<span class="label">体验次数:</span>
|
<span class="label">估值次数:</span>
|
||||||
<div class="count-control">
|
<NInputNumber
|
||||||
<NButton
|
v-model:value="limitForm.targetCount"
|
||||||
size="small"
|
:min="0"
|
||||||
@click="handleExperienceCountChange(-1)"
|
style="width: 160px;"
|
||||||
:disabled="limitForm.experienceCount <= 0"
|
/>
|
||||||
>
|
|
||||||
-
|
|
||||||
</NButton>
|
|
||||||
<span class="count-value">{{ limitForm.experienceCount }}</span>
|
|
||||||
<NButton
|
|
||||||
size="small"
|
|
||||||
@click="handleExperienceCountChange(1)"
|
|
||||||
>
|
|
||||||
+
|
|
||||||
</NButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 备注 -->
|
<!-- 备注 -->
|
||||||
@ -137,7 +112,7 @@ function handleCancel() {
|
|||||||
<span class="label">备注:</span>
|
<span class="label">备注:</span>
|
||||||
</div>
|
</div>
|
||||||
<NInput
|
<NInput
|
||||||
v-model:value="limitForm.notes"
|
v-model:value="limitForm.remark"
|
||||||
type="textarea"
|
type="textarea"
|
||||||
placeholder="请输入备注信息"
|
placeholder="请输入备注信息"
|
||||||
:rows="4"
|
:rows="4"
|
||||||
@ -184,19 +159,6 @@ function handleCancel() {
|
|||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
|
|
||||||
.count-control {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.count-value {
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 500;
|
|
||||||
min-width: 20px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-buttons {
|
.action-buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
|
|||||||
@ -45,17 +45,14 @@ const invoiceColumns = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
const logColumns = [
|
const logColumns = [
|
||||||
{ title: '操作时间', key: 'time', width: 160 },
|
{ title: 'ID', key: 'id', width: 80 },
|
||||||
{ title: '操作人', key: 'operator', width: 100 },
|
{ title: '操作人', key: 'operator_name', width: 120 },
|
||||||
|
{ title: '操作类型', key: 'op_type', width: 120, ellipsis: { tooltip: true } },
|
||||||
{
|
{
|
||||||
title: '操作记录',
|
title: '备注',
|
||||||
key: 'records',
|
key: 'remark',
|
||||||
render: (row) =>
|
ellipsis: { tooltip: true },
|
||||||
h(
|
render: (row) => row.remark || '-',
|
||||||
'div',
|
|
||||||
{ class: 'log-record' },
|
|
||||||
row.records?.map((item, idx) => h('div', { key: idx }, item))
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -209,10 +206,6 @@ function handleClose() {
|
|||||||
padding: 24px 0;
|
padding: 24px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.log-record div + div {
|
|
||||||
margin-top: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-buttons {
|
.action-buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|||||||
@ -1,16 +1,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { h, onMounted, ref, resolveDirective, withDirectives } from 'vue'
|
import { h, onMounted, ref, resolveDirective, withDirectives } from 'vue'
|
||||||
import {
|
import { NButton, NForm, NFormItem, NInput, NDatePicker } from 'naive-ui'
|
||||||
NButton,
|
|
||||||
NForm,
|
|
||||||
NFormItem,
|
|
||||||
NInput,
|
|
||||||
NSpace,
|
|
||||||
NSwitch,
|
|
||||||
NTag,
|
|
||||||
NPopconfirm,
|
|
||||||
NDatePicker,
|
|
||||||
} from 'naive-ui'
|
|
||||||
|
|
||||||
import CommonPage from '@/components/page/CommonPage.vue'
|
import CommonPage from '@/components/page/CommonPage.vue'
|
||||||
import QueryBarItem from '@/components/query-bar/QueryBarItem.vue'
|
import QueryBarItem from '@/components/query-bar/QueryBarItem.vue'
|
||||||
@ -142,7 +132,7 @@ const columns = [
|
|||||||
icon: renderIcon('material-symbols:info', { size: 16 }),
|
icon: renderIcon('material-symbols:info', { size: 16 }),
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
[[vPermission, 'get/api/v1/app_user/detail']]
|
[[vPermission, 'get/api/v1/app-user-admin/list']]
|
||||||
),
|
),
|
||||||
withDirectives(
|
withDirectives(
|
||||||
h(
|
h(
|
||||||
@ -158,7 +148,7 @@ const columns = [
|
|||||||
icon: renderIcon('material-symbols:settings', { size: 16 }),
|
icon: renderIcon('material-symbols:settings', { size: 16 }),
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
[[vPermission, 'post/api/v1/app_user/set_limit']]
|
[[vPermission, 'post/api/v1/app-user-admin/quota']]
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -170,23 +160,26 @@ async function handleViewDetail(row) {
|
|||||||
detailModalVisible.value = true
|
detailModalVisible.value = true
|
||||||
detailLoading.value = true
|
detailLoading.value = true
|
||||||
try {
|
try {
|
||||||
const detail = await api.getAppUserById({ id: row.id })
|
const { data: logs = [] } = await api.getAppUserQuotaLogs({
|
||||||
const baseInfoFromServer = detail?.baseInfo || {}
|
user_id: row.id,
|
||||||
|
page: 1,
|
||||||
|
page_size: 50,
|
||||||
|
})
|
||||||
userDetail.value = {
|
userDetail.value = {
|
||||||
baseInfo: {
|
baseInfo: {
|
||||||
...baseInfoFromServer,
|
|
||||||
id: row.id,
|
id: row.id,
|
||||||
phone: row.phone,
|
phone: row.phone,
|
||||||
wechat: row.wechat,
|
wechat: row.wechat,
|
||||||
register_time: row.created_at ? formatDate(row.created_at) : '-',
|
register_time: row.created_at ? formatDate(row.created_at) : '-',
|
||||||
notes: row.notes,
|
notes: row.notes,
|
||||||
remaining_count: row.remaining_count,
|
remaining_count: row.remaining_count,
|
||||||
|
user_type: row.user_type || '-',
|
||||||
},
|
},
|
||||||
invoiceHeaders: detail?.invoiceHeaders || [],
|
invoiceHeaders: [],
|
||||||
operationLogs: detail?.operationLogs || [],
|
operationLogs: logs,
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
$message.error('获取用户详情失败')
|
$message.error(error?.message || '获取用户详情失败')
|
||||||
} finally {
|
} finally {
|
||||||
detailLoading.value = false
|
detailLoading.value = false
|
||||||
}
|
}
|
||||||
@ -201,13 +194,17 @@ function handleSetLimit(row) {
|
|||||||
// 保存次数设置
|
// 保存次数设置
|
||||||
async function handleSaveLimitSetting(data) {
|
async function handleSaveLimitSetting(data) {
|
||||||
try {
|
try {
|
||||||
// 这里调用API保存次数设置
|
await api.updateAppUserQuota({
|
||||||
// await api.setUserLimit(data)
|
user_id: data.user_id,
|
||||||
|
target_count: data.target_count,
|
||||||
|
op_type: data.op_type,
|
||||||
|
remark: data.remark,
|
||||||
|
})
|
||||||
$message.success('次数设置保存成功')
|
$message.success('次数设置保存成功')
|
||||||
limitModalVisible.value = false
|
limitModalVisible.value = false
|
||||||
$table.value?.handleSearch()
|
$table.value?.handleSearch()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
$message.error('保存失败: ' + error.message)
|
$message.error(error?.message || '保存失败')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,4 +5,5 @@ VITE_PUBLIC_PATH = '/'
|
|||||||
VITE_USE_PROXY = true
|
VITE_USE_PROXY = true
|
||||||
|
|
||||||
# base api
|
# base api
|
||||||
VITE_BASE_API = 'https://value.cdcee.net/api/v1'
|
VITE_BASE_API = 'http://139.224.70.152:9990/api/v1'
|
||||||
|
# VITE_BASE_API = 'https://value.cdcee.net/api/v1'
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user