增加文章分类管理

修改部分页面样式
This commit is contained in:
jacky 2024-04-09 22:39:15 +08:00
parent 8454d5f4aa
commit 7cad3c1693
10 changed files with 319 additions and 33 deletions

4
.gitignore vendored
View File

@ -1,3 +1,5 @@
node_modules/*
package-lock.json
yarn.lock
yarn.lock
dist/
dist.tar.gz

View File

@ -0,0 +1,63 @@
import service from '@/utils/request'
// @Summary 获取分类树
// @Produce application/json
// @Router /articleCategory/getCategoryTree [post]
export const getCategoryTree = () => {
return service({
url: '/articleCategory/getCategoryTree',
method: 'post',
})
}
// @Summary 新增分类
// @Produce application/json
// @Param menu Object
// @Router /articleCategory/addCategory [post]
export const addCategory = (data) => {
return service({
url: '/articleCategory/addCategory',
method: 'post',
data
})
}
// @Summary 删除分类
// @Produce application/json
// @Param ID int
// @Router /articleCategory/deleteCategory [post]
export const deleteCategory = (data) => {
return service({
url: '/articleCategory/deleteCategory',
method: 'post',
data
})
}
// @Summary 修改分类
// @Produce application/json
// @Param menu Object
// @Router /articleCategory/updateCategory [post]
export const updateCategory = (data) => {
return service({
url: '/articleCategory/updateCategory',
method: 'post',
data
})
}
// @Tags 文章分类
// @Summary 根据id获取分类
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body api.GetById true "根据id获取菜单"
// @Success 200 {string} json "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /articleCategory/getCategoryById [post]
export const getCategoryById = (data) => {
return service({
url: '/articleCategory/getCategoryById',
method: 'post',
data
})
}

BIN
src/assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 749 KiB

View File

@ -0,0 +1,242 @@
<template>
<div>
<div class="gva-table-box">
<div class="gva-btn-list">
<el-button type="primary" icon="plus" @click="clickAdd('0')">新增根分类</el-button>
</div>
<!-- 由于此处菜单跟左侧列表一一对应所以不需要分页 pageSize默认999 -->
<el-table :data="tableData" row-key="ID">
<el-table-column align="left" label="ID" min-width="80" prop="ID"/>
<el-table-column align="left" label="分类名称" min-width="200" prop="categoryName">
<template #default="scope">
<span>{{ scope.row.title }}</span>
</template>
</el-table-column>
<el-table-column align="left" label="是否隐藏" min-width="100" prop="hidden">
<template #default="scope">
<span>{{ scope.row.hidden?"隐藏":"显示" }}</span>
</template>
</el-table-column>
<el-table-column align="left" label="父节点" min-width="90" prop="parentId"/>
<el-table-column align="left" label="排序" min-width="100" prop="sort"/>
<el-table-column align="left" fixed="right" label="操作" width="300">
<template #default="scope">
<el-button type="primary" link icon="plus" @click="clickAdd(scope.row.ID)">添加子类</el-button>
<el-button type="primary" link icon="edit" @click="clickEdit(scope.row.ID)">编辑</el-button>
<el-button type="primary" link icon="delete" @click="clickDelete(scope.row.ID)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<el-dialog v-model="dialogFormVisible" :before-close="handleClose" :title="dialogTitle">
<warning-bar title="新增分类,需要在角色管理内配置权限才可使用" />
<el-form v-if="dialogFormVisible" ref="categoryForm" :inline="true" :model="form" :rules="rules" label-position="top" label-width="85px">
<el-form-item label="分类名称" prop="path" style="width:30%">
<el-input v-model="form.title" autocomplete="off"/>
</el-form-item>
<el-form-item label="是否隐藏" style="width:30%">
<el-select v-model="form.hidden" placeholder="是否在列表隐藏">
<el-option :value="false" label="否" />
<el-option :value="true" label="是" />
</el-select>
</el-form-item>
<el-form-item label="父节点ID" style="width:30%">
<el-cascader v-model="form.parentId" style="width:100%" :disabled="!isEdit" :options="categoryOption" :props="{ checkStrictly: true,label:'title',value:'ID',disabled:'disabled',emitPath:false}" :show-all-levels="false" filterable/>
</el-form-item>
<el-form-item label="排序" prop="sort" style="width:30%">
<el-input v-model.number="form.sort" autocomplete="off"/>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="closeDialog"> </el-button>
<el-button type="primary" @click="enterDialog"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { reactive, ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
getCategoryTree,
addCategory,
updateCategory,
deleteCategory,
getCategoryById
} from '@/api/articleCategory'
import WarningBar from '@/components/warningBar/warningBar.vue'
const rules = reactive({
title: [
{ required: true, message: '请输入分类名称', trigger: 'blur' }
],
})
const tableData = ref([])
//
const getTableData = async() => {
const res = await getCategoryTree()
if (res.code === 0) {
tableData.value = res.data.categoryTree
}
}
getTableData()
const categoryOption = ref([
{
ID: '0',
title: '根分类'
}
])
const setOptions = () => {
categoryOption.value = [
{
ID: '0',
title: '根分类'
}
]
setCategoryOptions(tableData.value, categoryOption.value, false)
}
const setCategoryOptions = (categoryData, optionsData, disabled) => {
categoryData &&
categoryData.forEach(item => {
if (item.children && item.children.length) {
const option = {
title: item.title,
ID: String(item.ID),
disabled: disabled || item.ID === form.value.ID,
children: []
}
setCategoryOptions(
item.children,
option.children,
disabled || item.ID === form.value.ID
)
optionsData.push(option)
} else {
const option = {
title: item.title,
ID: String(item.ID),
disabled: disabled || item.ID === form.value.ID
}
optionsData.push(option)
}
})
}
const form = ref({
ID: 0,
parentId: '',
title: '',
hidden: false,
sort: '',
})
//
const enterDialog = async() => {
categoryForm.value.validate(async valid => {
if (valid) {
let res
if (isEdit.value) {
res = await updateCategory(form.value)
} else {
res = await addCategory(form.value)
}
if (res.code === 0) {
ElMessage({
type: 'success',
message: isEdit.value ? '编辑成功' : '添加成功!'
})
getTableData()
}
initForm()
dialogFormVisible.value = false
}
})
}
//
const categoryForm = ref(null)
const checkFlag = ref(false)
const initForm = () => {
checkFlag.value = false
categoryForm.value.resetFields()
form.value = {
ID: 0,
parentId: '',
title: '',
hidden: false,
sort: '',
}
}
const handleClose = (done) => {
initForm()
done()
}
//
const dialogFormVisible = ref(false)
const closeDialog = () => {
initForm()
dialogFormVisible.value = false
}
//
const clickDelete = (ID) => {
ElMessageBox.confirm('此操作将永久删除分类, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(async() => {
const res = await deleteCategory({ ID })
if (res.code === 0) {
ElMessage({
type: 'success',
message: '删除成功!'
})
if (tableData.value.length === 1 && page.value > 1) {
page.value--
}
getTableData()
}
})
.catch(() => {
ElMessage({
type: 'info',
message: '已取消删除'
})
})
}
// id 0
const isEdit = ref(false)
const dialogTitle = ref('新增分类')
const clickAdd = (id) => {
dialogTitle.value = '新增分类'
form.value.parentId = String(id)
isEdit.value = false
setOptions()
dialogFormVisible.value = true
}
//
const clickEdit = async(id) => {
dialogTitle.value = '编辑分类'
const res = await getCategoryById({ id })
form.value = res.data.category
isEdit.value = true
setOptions()
dialogFormVisible.value = true
}
</script>

View File

@ -16,7 +16,7 @@
<img
alt
class="w-9 h-9 p-1 bg-white rounded-full"
src="@/assets/logo.jpg"
src="@/assets/logo.png"
>
<div
v-if="isSider"

View File

@ -6,10 +6,6 @@
@click="handleReload"
/>
<Screenfull class="search-icon" />
<div
class="gvaIcon gvaIcon-customer-service"
@click="toService"
/>
</div>
</template>
@ -30,9 +26,6 @@ const handleReload = () => {
reload.value = false
}, 500)
}
const toService = () => {
window.open('https://support.qq.com/product/371961')
}
</script>
<style scoped lang="scss">

View File

@ -14,7 +14,7 @@
<div class="flex items-center justify-center">
<img
class="w-24"
src="@/assets/logo.jpg"
src="@/assets/logo.png"
alt
style="margin-bottom: 15px;"
>

View File

@ -71,35 +71,25 @@
>
<ul>
<li class="borderd">
<p class="pb-2.5 text-xl text-gray-600">密保手机</p>
<p class="pb-2.5 text-xl text-gray-600">手机</p>
<p class="pb-2.5 text-lg text-gray-400">
已绑定手机:{{ userStore.userInfo.phone }}
<a
{{ userStore.userInfo.phone }}
<!-- <a
href="javascript:void(0)"
class="float-right text-blue-400"
@click="changePhoneFlag = true"
>立即修改</a>
>立即修改</a> -->
</p>
</li>
<li class="borderd pt-2.5">
<p class="pb-2.5 text-xl text-gray-600">密保邮箱</p>
<p class="pb-2.5 text-xl text-gray-600">邮箱</p>
<p class="pb-2.5 text-lg text-gray-400">
已绑定邮箱{{ userStore.userInfo.email }}
<a
{{ userStore.userInfo.email }}
<!-- <a
href="javascript:void(0)"
class="float-right text-blue-400"
@click="changeEmailFlag = true"
>立即修改</a>
</p>
</li>
<li class="borderd pt-2.5">
<p class="pb-2.5 text-xl text-gray-600">密保问题</p>
<p class="pb-2.5 text-lg text-gray-400">
未设置密保问题
<a
href="javascript:void(0)"
class="float-right text-blue-400"
>去设置</a>
>立即修改</a> -->
</p>
</li>
<li class="borderd pt-2.5">

View File

@ -7,10 +7,6 @@
icon="plus"
@click="addMenu('0')"
>新增根菜单</el-button>
<el-icon
class="cursor-pointer"
@click="toDoc('https://www.bilibili.com/video/BV1kv4y1g7nT/?p=4&vd_source=f2640257c21e3b547a790461ed94875e')"
><VideoCameraFilled /></el-icon>
</div>
<!-- 由于此处菜单跟左侧列表一一对应所以不需要分页 pageSize默认999 -->
@ -662,7 +658,7 @@ const closeDialog = () => {
initForm()
dialogFormVisible.value = false
}
// menu
//
const enterDialog = async() => {
menuForm.value.validate(async valid => {
if (valid) {