chore(web): 收口前几轮后台改动(品牌 / 媒资上传 / 轮播图 / 类型管理 / 操作日志 / App 用户)
为什么:这些改动在前几轮就已完成并在 :3005 验证过,但一直留在工作区没有入库。 下一步 3-4 的四个页面依赖其中的公共样式入口(src/styles/business/index.css)与 api/admin 的公共类型(PageResult 等),如果不先收口,新页面的提交就会夹带旧改动, 既说不清 diff 边界,也让 index.css 这类多轮共用的文件长期处于半提交状态。 本提交只做归档,不改行为: - 品牌与接口基址改成 FruitShorts / 短剧服务(.env.*、README、vite 代理) - 去掉前端 mock 数据目录(src/data、src/permissions、stores/auth),改为走真实接口 - 新增 api/admin 下的接口封装与 src/utils/uploader.ts(媒资分片直传) - 新增/改造:轮播图管理、类型管理、操作日志、App 用户管理、后台布局与公共样式
This commit is contained in:
1 parent
40546bfd01
commit
44c2c46a68
59 files changed
+4082
-982
No files matched your search
@@ -1,71 +1,202 @@
|
||||
import { computed, reactive, ref } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { roleData } from '../../../data/roles'
|
||||
import { demoAdminUsers } from '../data/adminUsers'
|
||||
import { onMounted, reactive, ref } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import {
|
||||
createAdminUserApi,
|
||||
deleteAdminUserApi,
|
||||
pageAdminUsersApi,
|
||||
resetAdminUserPasswordApi,
|
||||
updateAdminUserApi,
|
||||
updateAdminUserStatusApi
|
||||
} from '@/api/admin/user'
|
||||
import { listRolesApi } from '@/api/admin/role'
|
||||
|
||||
export function useAdminUsers() {
|
||||
const roles = ref([])
|
||||
const users = ref([])
|
||||
const total = ref(0)
|
||||
const loading = ref(false)
|
||||
|
||||
const keyword = ref('')
|
||||
const roleFilter = ref('')
|
||||
const roleFilter = ref(undefined)
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(10)
|
||||
|
||||
const dialogVisible = ref(false)
|
||||
const form = reactive({ username: '', name: '', role: '', ipWhitelist: '' })
|
||||
const users = ref(demoAdminUsers.map((user) => ({ ...user })))
|
||||
const filtered = computed(() =>
|
||||
users.value.filter((user) => {
|
||||
const query = keyword.value.trim().toLowerCase()
|
||||
const matchesKeyword =
|
||||
!query || `${user.id} ${user.username} ${user.name}`.toLowerCase().includes(query)
|
||||
return matchesKeyword && (!roleFilter.value || user.role === roleFilter.value)
|
||||
})
|
||||
)
|
||||
const paginated = computed(() =>
|
||||
filtered.value.slice(
|
||||
(currentPage.value - 1) * pageSize.value,
|
||||
currentPage.value * pageSize.value
|
||||
)
|
||||
)
|
||||
const saving = ref(false)
|
||||
const editingId = ref(null)
|
||||
const form = reactive({
|
||||
username: '',
|
||||
password: '',
|
||||
name: '',
|
||||
roleId: undefined,
|
||||
ipWhitelist: '',
|
||||
status: 1
|
||||
})
|
||||
|
||||
async function loadRoles() {
|
||||
const res = await listRolesApi()
|
||||
roles.value = res.data || []
|
||||
}
|
||||
|
||||
async function load() {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await pageAdminUsersApi({
|
||||
pageIndex: currentPage.value,
|
||||
pageSize: pageSize.value,
|
||||
username: keyword.value.trim() || undefined,
|
||||
roleId: roleFilter.value
|
||||
})
|
||||
users.value = res.data?.list || []
|
||||
total.value = res.data?.total || 0
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function queryUsers() {
|
||||
currentPage.value = 1
|
||||
}
|
||||
function toggleStatus(user) {
|
||||
user.status = user.status === '启用' ? '停用' : '启用'
|
||||
}
|
||||
function addUser() {
|
||||
if (!form.username.trim() || !form.name.trim() || !form.role)
|
||||
return ElMessage.warning('请填写用户名、姓名并选择权限角色')
|
||||
const role = roleData.find((item) => item.name === form.role)
|
||||
users.value.unshift({
|
||||
id: Math.max(0, ...users.value.map((user) => user.id)) + 1,
|
||||
username: form.username.trim(),
|
||||
name: form.name.trim(),
|
||||
roleId: role?.id || 0,
|
||||
role: form.role,
|
||||
ipWhitelist: form.ipWhitelist.trim() || '不限',
|
||||
status: '启用',
|
||||
twoFactor: '未开启',
|
||||
createdAt: new Date().toLocaleString('sv-SE'),
|
||||
lastLogin: '—'
|
||||
})
|
||||
Object.assign(form, { username: '', name: '', role: '', ipWhitelist: '' })
|
||||
dialogVisible.value = false
|
||||
currentPage.value = 1
|
||||
ElMessage.success('管理员已添加')
|
||||
load()
|
||||
}
|
||||
|
||||
function handleSizeChange() {
|
||||
currentPage.value = 1
|
||||
load()
|
||||
}
|
||||
|
||||
function openCreate() {
|
||||
editingId.value = null
|
||||
Object.assign(form, {
|
||||
username: '',
|
||||
password: '',
|
||||
name: '',
|
||||
roleId: undefined,
|
||||
ipWhitelist: '',
|
||||
status: 1
|
||||
})
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
function openEdit(row) {
|
||||
editingId.value = row.id
|
||||
Object.assign(form, {
|
||||
username: row.username,
|
||||
password: '',
|
||||
name: row.name,
|
||||
roleId: row.roleId || undefined,
|
||||
ipWhitelist: row.ipWhitelist === '不限' ? '' : row.ipWhitelist,
|
||||
status: row.status
|
||||
})
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
async function saveUser() {
|
||||
if (!form.name.trim()) return ElMessage.warning('请填写姓名')
|
||||
if (!form.roleId) return ElMessage.warning('请选择权限角色')
|
||||
if (!editingId.value) {
|
||||
if (!form.username.trim()) return ElMessage.warning('请填写登录账号')
|
||||
if (!form.password || form.password.length < 6) {
|
||||
return ElMessage.warning('初始密码不能少于 6 位')
|
||||
}
|
||||
}
|
||||
const payload = {
|
||||
name: form.name.trim(),
|
||||
roleId: form.roleId,
|
||||
ipWhitelist: form.ipWhitelist.trim(),
|
||||
status: form.status
|
||||
}
|
||||
saving.value = true
|
||||
try {
|
||||
if (editingId.value) {
|
||||
await updateAdminUserApi(editingId.value, payload)
|
||||
ElMessage.success('管理员已更新')
|
||||
} else {
|
||||
await createAdminUserApi({
|
||||
...payload,
|
||||
username: form.username.trim(),
|
||||
password: form.password
|
||||
})
|
||||
ElMessage.success('管理员已添加')
|
||||
currentPage.value = 1
|
||||
}
|
||||
dialogVisible.value = false
|
||||
await load()
|
||||
} finally {
|
||||
saving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function toggleStatus(row) {
|
||||
const next = row.status === 1 ? 0 : 1
|
||||
await updateAdminUserStatusApi(row.id, next)
|
||||
ElMessage.success(next === 1 ? '账号已启用' : '账号已停用')
|
||||
await load()
|
||||
}
|
||||
|
||||
async function removeUser(row) {
|
||||
try {
|
||||
await ElMessageBox.confirm(`确定删除管理员「${row.name}」吗?`, '删除确认', {
|
||||
confirmButtonText: '确认删除',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
confirmButtonClass: 'el-button--danger'
|
||||
})
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
await deleteAdminUserApi(row.id)
|
||||
ElMessage.success('管理员已删除')
|
||||
if (users.value.length === 1 && currentPage.value > 1) currentPage.value -= 1
|
||||
await load()
|
||||
}
|
||||
|
||||
async function resetPassword(row) {
|
||||
let password = ''
|
||||
try {
|
||||
const { value } = await ElMessageBox.prompt(
|
||||
`为「${row.username}」设置新密码(至少 6 位)`,
|
||||
'重置密码',
|
||||
{
|
||||
confirmButtonText: '确认重置',
|
||||
cancelButtonText: '取消',
|
||||
inputPlaceholder: '请输入新密码',
|
||||
inputValidator: (val) => (val && val.length >= 6 ? true : '密码不能少于 6 位')
|
||||
}
|
||||
)
|
||||
password = value
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
await resetAdminUserPasswordApi(row.id, password)
|
||||
ElMessage.success('密码已重置')
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await loadRoles()
|
||||
await load()
|
||||
})
|
||||
|
||||
return {
|
||||
roles,
|
||||
keyword,
|
||||
roleFilter,
|
||||
currentPage,
|
||||
pageSize,
|
||||
loading,
|
||||
total,
|
||||
dialogVisible,
|
||||
saving,
|
||||
editingId,
|
||||
form,
|
||||
users,
|
||||
filtered,
|
||||
paginated,
|
||||
load,
|
||||
queryUsers,
|
||||
handleSizeChange,
|
||||
openCreate,
|
||||
openEdit,
|
||||
saveUser,
|
||||
toggleStatus,
|
||||
addUser
|
||||
removeUser,
|
||||
resetPassword
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user