Files
HAOVP/frontend/video-frontend-admin/src/views/content/category.vue
T

272 lines
6.2 KiB
Vue

<template>
<div class="category-page">
<el-card shadow="never">
<template #header>
<div class="card-header">
<span>分类管理</span>
<el-button
type="primary"
@click="handleAdd"
>
<el-icon><Plus /></el-icon>添加分类
</el-button>
</div>
</template>
<el-table
v-loading="loading"
:data="categories"
row-key="id"
default-expand-all
>
<el-table-column
prop="name"
label="分类名称"
/>
<el-table-column
prop="sort"
label="排序"
width="100"
/>
<el-table-column
label="操作"
width="200"
>
<template #default="{ row }">
<el-button
type="primary"
text
@click="handleEdit(row)"
>
编辑
</el-button>
<el-button
type="primary"
text
@click="handleAddChild(row)"
>
添加子分类
</el-button>
<el-button
type="danger"
text
@click="handleDelete(row)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<el-dialog
v-model="dialogVisible"
:title="dialogTitle"
width="400px"
>
<el-form
:model="form"
label-width="80px"
>
<el-form-item
label="分类名称"
required
>
<el-input
v-model="form.name"
placeholder="请输入分类名称"
/>
</el-form-item>
<el-form-item label="父级分类">
<el-tree-select
v-model="form.parentId"
:data="categoryTree"
:props="{ label: 'name', children: 'children' }"
node-key="id"
check-strictly
clearable
placeholder="选择父级分类(可选)"
/>
</el-form-item>
<el-form-item label="排序">
<el-input-number
v-model="form.sort"
:min="0"
/>
</el-form-item>
<el-form-item label="图标">
<el-input
v-model="form.icon"
placeholder="图标URL"
/>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false">
取消
</el-button>
<el-button
type="primary"
:loading="submitting"
@click="handleSubmit"
>
确定
</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, computed, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { categoryApi, type Category } from '@/api/category.ts'
const loading = ref(false)
const categories = ref<Category[]>([])
const dialogVisible = ref(false)
const dialogTitle = ref('添加分类')
const submitting = ref(false)
const form = reactive({
id: undefined as number | undefined,
name: '',
code: '',
parentId: 0,
level: 1,
sort: 0,
icon: '',
status: 1
})
const createCategoryCode = (name: string) => {
const slug = name
.trim()
.toLowerCase()
.replace(/[^a-z0-9\u4e00-\u9fa5]+/g, '-')
.replace(/^-+|-+$/g, '')
.slice(0, 20)
return `cat-${slug || 'item'}-${Date.now().toString().slice(-6)}`
}
const categoryTree = computed(() => {
const buildTree = (list: Category[], parentId: number = 0): Category[] => {
return list.filter(item => item.parentId === parentId).map(item => ({
...item,
children: buildTree(list, item.id)
}))
}
return buildTree(categories.value)
})
const loadCategories = async () => {
loading.value = true
try {
categories.value = await categoryApi.getList()
} catch (error) {
ElMessage.error('加载失败')
} finally {
loading.value = false
}
}
const resetForm = () => {
form.id = undefined
form.name = ''
form.code = ''
form.parentId = 0
form.level = 1
form.sort = 0
form.icon = ''
form.status = 1
}
const handleAdd = () => {
resetForm()
dialogTitle.value = '添加分类'
dialogVisible.value = true
}
const handleAddChild = (row: Category) => {
resetForm()
form.parentId = row.id
dialogTitle.value = '添加子分类'
dialogVisible.value = true
}
const handleEdit = (row: Category) => {
form.id = row.id
form.name = row.name
form.code = row.code || ''
form.parentId = row.parentId
form.level = row.level || 1
form.sort = row.sort
form.icon = row.icon || ''
form.status = row.status ?? 1
dialogTitle.value = '编辑分类'
dialogVisible.value = true
}
const handleDelete = async (row: Category) => {
try {
await ElMessageBox.confirm('确定要删除该分类吗?', '提示', { type: 'warning' })
await categoryApi.delete(row.id)
ElMessage.success('删除成功')
loadCategories()
} catch {}
}
const handleSubmit = async () => {
if (!form.name.trim()) {
ElMessage.warning('请输入分类名称')
return
}
submitting.value = true
try {
if (form.id) {
await categoryApi.update({
id: form.id,
name: form.name,
code: form.code || createCategoryCode(form.name),
parentId: form.parentId,
level: form.level,
sort: form.sort,
icon: form.icon,
status: form.status
})
ElMessage.success('更新成功')
} else {
await categoryApi.create({
name: form.name,
code: createCategoryCode(form.name),
parentId: form.parentId,
level: form.parentId === 0 ? 1 : undefined,
sort: form.sort,
icon: form.icon,
status: 1
})
ElMessage.success('添加成功')
}
dialogVisible.value = false
loadCategories()
} catch (error) {
ElMessage.error('操作失败')
} finally {
submitting.value = false
}
}
onMounted(() => loadCategories())
</script>
<style scoped lang="scss">
.category-page {
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
}
</style>