feat: 🚀 文章分类

This commit is contained in:
2025-04-11 10:54:56 +08:00
parent 473aa04ea4
commit bbf953f47a
10 changed files with 156 additions and 63 deletions

View File

@@ -5,6 +5,10 @@ const ARTICLE_CATEGORY = `/article/category`;
export const getArticleClassListApi = (params: any) => {
return http.get<any>(`${ARTICLE_CATEGORY}/index`, params);
};
//文章分类下拉框
export const getArticleClassApi = () => {
return http.get<any>(`/article/categorys`);
};
//文章分类新增
export const getArticleClassAddSaveApi = (params: any) => {
return http.post<any>(`${ARTICLE_CATEGORY}/save`, params);
@@ -15,12 +19,13 @@ export const getArticleClassDelApi = (params: any) => {
};
//文章分类更新(用于编辑后)
export const getArticleClassEditUpApi = (params: any) => {
const { id, name, sort, is_show, seo_title, seo_keywords, seo_desc } = params;
const { id, name, sort, is_show, pid, seo_title, seo_keywords, seo_desc } = params;
return http.put<any>(`/article/category/update/${id}`, {
name,
sort,
is_show,
pid,
seo_title,
seo_keywords,
seo_desc
@@ -30,3 +35,7 @@ export const getArticleClassEditUpApi = (params: any) => {
export const getArticleClassDetailsApi = (params: any) => {
return http.get<any>(`${ARTICLE_CATEGORY}/read/${params}`);
};
export const getArticleClassSortApi = (params: any) => {
const { id, sort } = params;
return http.post<any>(`${ARTICLE_CATEGORY}/sort/${id}`, { sort });
};

View File

@@ -15,7 +15,7 @@
:accept="fileType.join(',')"
>
<!-- disabled -->
<el-input v-model="videoShowUrl" style="width: 414px" @click.stop @input="handleInput" disabled>
<el-input v-model="videoShowUrl" style="width: 414px" @click.stop @input="handleInput">
<template #prepend
><el-icon :size="20" style="cursor: pointer"><FolderAdd /></el-icon
></template>
@@ -45,7 +45,7 @@ interface UploadFileProps {
fileType?: any[]; //视频类型限制 ==> 非必传(默认为[".mp4", ".avi", ".mov"]
borderRadius?: string; // 组件边框圆角 ==> 非必传(默认为 8px
}
const videoShowUrl = ref(null);
const videoShowUrl = ref<any>(null);
// 接受父组件参数
const props = withDefaults(defineProps<UploadFileProps>(), {
videoUrl: "",
@@ -98,6 +98,7 @@ const handleHttpUpload = async (options: UploadRequestOptions) => {
};
const handleInput = () => {
emit("update:videoUrl", videoShowUrl.value);
console.log("会触发吗");
};

View File

@@ -20,7 +20,7 @@
<el-tab-pane label="问答详细" name="third">
<div style="width: 1280px; margin: 0 auto">
<WangEditor v-model:value="dataStore.value" />
<WangEditor v-model:value="dataStore.editRuleForm.answer" />
</div>
</el-tab-pane>
</el-tabs>
@@ -40,7 +40,7 @@ const $route = useRoute();
const activeName = ref("basicInfo");
//数据集合
const dataStore = reactive<any>({
value: "",
// value: "",
editRuleForm: cloneDeep(EDIT_RULE_FORM),
editFormData: cloneDeep(EDIT_FORM_DATA),
rules: RULES
@@ -58,12 +58,14 @@ const getQAListDetails = async () => {
const { data } = result;
//这里是传给基本信息组件的表单数据
dataStore.editRuleForm = cloneDeep(data);
dataStore.value = data.answer;
}
};
getQAListDetails();
//更新
const getQAListEditUp = async () => {
// dataStore.editRuleForm.answer = dataStore.value;
const result: any = await getQAListEditUpApi(dataStore.editRuleForm);
if (result?.code === 0) {
useMsg("success", result?.msg);
@@ -72,6 +74,7 @@ const getQAListEditUp = async () => {
};
//新增 getQAListSaveApi
const getQAListSave = async () => {
// dataStore.editRuleForm.answer = dataStore.value;
const result: any = await getQAListSaveApi(dataStore.editRuleForm);
if (result?.code === 0) {
useMsg("success", result?.msg);
@@ -88,6 +91,10 @@ const handleReset = () => {
const resetFields = () => {
if (!formRef.value!.ruleFormRef) return;
formRef!.value!.ruleFormRef.resetFields();
for (let key in dataStore.editRuleForm) {
dataStore.editRuleForm[key] = "";
}
// dataStore.value = "";
};
const handleSubmit = () => {

View File

@@ -46,34 +46,20 @@ export const EDIT_FORM_DATA: FormItem[] = [
value: 0
}
]
},
{
prop: "pid",
placeholder: "请选择",
type: "treeSelect",
label: "所属分类: ",
options: []
}
// {
// prop: "seo_title",
// placeholder: "请输入",
// type: "input",
// label: "SEO标题: "
// },
// {
// prop: "seo_keywords",
// placeholder: "请输入",
// type: "input",
// label: "SEO关键词: "
// },
// {
// prop: "seo_desc",
// placeholder: "请输入",
// type: "input",
// label: "SEO描述: "
// }
];
export const EDIT_RULE_FORM = {
is_show: 1,
seo_desc: "",
seo_keywords: "",
seo_title: "",
sort: 1,
name: ""
name: "",
pid: 0
};
// editRuleForm: {},
//editFormData: [],

View File

@@ -1,4 +1,5 @@
export const RULES = {
name: [{ required: true, message: "文章分类名称不能为空 ! ", trigger: "blur" }],
sort: [{ required: true, message: "文章分类排序不能为空 ! ", trigger: "blur" }]
sort: [{ required: true, message: "文章分类排序不能为空 ! ", trigger: "blur" }],
pid: [{ required: true, message: "所属分类不能为空 ! ", trigger: "blur" }]
};

View File

@@ -26,6 +26,6 @@ export const FORM_DATA: FormItem[] = [
];
export const RULE_FORM = {
page: 1,
size: 50
// page: 1,
// size: 50
};

View File

@@ -32,7 +32,5 @@ export const COLUMNS = [
render: (scope: RenderScope<any>): VNode | string | any => {
return YES_OR_NO[scope.row.is_show];
}
},
{ prop: "operation", label: "操作", fixed: "right", width: 300 }
}
];

View File

@@ -4,14 +4,32 @@
<div style="padding-bottom: 16px">
<el-button type="primary" @click="handleAdd"> 添加 </el-button>
</div>
<ProTable
ref="proTableRef"
:formData="dataStore.formData"
:columns="dataStore.columns"
:request-api="getArticleClassListApi"
:init-param="dataStore.initParam"
<div class="card table-main">
<SearchForm :search="search" :reset="reset" :formData="dataStore.formData" :search-param="dataStore.ruleForm" />
<el-table
:data="dataStore.tableData"
style="width: 100%; margin-bottom: 20px; font-size: 14px"
row-key="id"
border
default-expand-all
>
<template #operation="scope">
<el-table-column prop="id" label="id" />
<el-table-column prop="name" label="分类名称" />
<el-table-column prop="sort" label="分类排序">
<template #default="{ row }">
<div @click.stop="">
<el-input v-model="row.sort" @blur="handleBlur(row)" @input="handleInput(row)" />
</div>
</template>
</el-table-column>
<el-table-column prop="is_show" label="是否显示">
<template #default="{ row }">
{{ row.is_show === 1 ? "✔️" : "❌" }}
</template>
</el-table-column>
<!-- <template #default="scope"> -->
<el-table-column label="操作" :width="240">
<template #default="scope">
<el-button
size="small"
v-for="(item, index) in dataStore.btns"
@@ -21,7 +39,10 @@
>{{ item.name }}</el-button
>
</template>
</ProTable>
</el-table-column>
</el-table>
</div>
<el-drawer
v-model="dataStore.visible"
:show-close="true"
@@ -40,6 +61,7 @@
:formData="dataStore.editFormData"
:rules="dataStore.rules"
ref="formRef"
@handleSelectChangeEmits="handleSelectChangeEmits"
/>
</div>
<template #footer>
@@ -54,7 +76,8 @@
<script setup lang="ts" name="articleClassListIndex">
import rulesForm from "@/components/rulesForm/index.vue";
import ProTable from "@/components/ProTable/index.vue";
import { integerRexg } from "@/utils/regexp/index";
// import ProTable from "@/components/ProTable/index.vue";
import { messageBox } from "@/utils/messageBox";
import { useMsg } from "@/hooks/useMsg";
//列表接口
@@ -63,14 +86,15 @@ import {
getArticleClassAddSaveApi,
getArticleClassDelApi,
getArticleClassEditUpApi,
getArticleClassDetailsApi
getArticleClassDetailsApi,
getArticleClassApi,
getArticleClassSortApi
} from "@/api/modules/articleClass";
//深拷贝方法
import { cloneDeep } from "lodash-es";
//表格和搜索條件
import { RULE_FORM, FORM_DATA, COLUMNS, EDIT_FORM_DATA, EDIT_RULE_FORM, RULES, BTNS } from "./constant/index";
// 获取 ProTable 元素,调用其获取刷新数据方法(还能获取到当前查询参数,方便导出携带参数)
const proTableRef = ref<any>(null);
const formRef: any = ref(null);
const $router = useRouter();
// 数据源
@@ -85,9 +109,71 @@ const dataStore = reactive<any>({
formData: FORM_DATA, //搜索配置项
visible: false,
btns: BTNS,
tableData: [],
selectRow: {} //当前选择的row
});
const getArticleClassSort = async (row: any) => {
const result = await getArticleClassSortApi(row);
if (result?.code === 0) {
useMsg("success", result?.msg);
getArticleClassList();
}
};
//排序input框失焦
const handleBlur = (row: any) => {
getArticleClassSort(row);
};
//
const handleInput = (row: any) => {
row.sort = integerRexg(row.sort);
};
const search = () => {
getArticleClassList();
};
const reset = () => {
for (let key in dataStore.ruleForm) {
dataStore.ruleForm[key] = "";
}
getArticleClassList();
};
const addLabelValue = (arr: any) => {
return arr.map((item: any) => {
// 为当前对象添加 label 和 value 属性
const newItem = { ...item };
newItem.label = newItem.name;
newItem.value = newItem.id;
// 如果有子对象,递归调用 addLabelValue 处理子对象
if (newItem.children && Array.isArray(newItem.children)) {
newItem.children = addLabelValue(newItem.children);
}
return newItem;
});
};
const handleSelectChangeEmits = (params: any) => {
const { id } = params;
dataStore.editRuleForm.pid = id;
};
const getArticleClass = async () => {
const result = await getArticleClassApi();
if (result?.code === 0) {
dataStore.editFormData[3].options = addLabelValue(result?.data);
dataStore.editFormData[3].options.unshift({ value: 0, label: "无" });
console.log(result?.data);
}
};
getArticleClass();
const getArticleClassList = async () => {
const result = await getArticleClassListApi(dataStore.ruleForm);
if (result?.code === 0) {
dataStore.tableData = result?.data;
}
};
getArticleClassList();
//新增文章接口
const getArticleClassAddSave = async () => {
const result = await getArticleClassAddSaveApi(dataStore.editRuleForm);
@@ -96,18 +182,20 @@ const getArticleClassAddSave = async () => {
useMsg("success", msg);
dataStore.visible = false;
dataStore.editRuleForm = cloneDeep(EDIT_RULE_FORM);
proTableRef?.value?.getTableList();
getArticleClassList();
}
};
//文章编辑
const getArticleClassUpEdit = async () => {
console.log("编辑");
const result = await getArticleClassEditUpApi(dataStore.editRuleForm);
const { msg, code } = result;
if (code === 0) {
useMsg("success", msg);
dataStore.visible = false;
proTableRef?.value?.getTableList();
dataStore.editRuleForm = cloneDeep(EDIT_RULE_FORM);
getArticleClassList();
}
};
//删除文章
@@ -117,7 +205,7 @@ const getArticleClassDel = (row: any) => {
const { msg, code } = result;
if (code === 0) {
useMsg("success", msg);
proTableRef?.value?.getTableList();
getArticleClassList();
}
});
};
@@ -141,12 +229,16 @@ const resetFields = () => {
};
//抽屉重置
const handleResetClick = () => {
if (dataStore.title == "添加文章分类") {
resetFields();
} else {
getArticleClassDetails(dataStore.selectRow);
}
};
//添加
const handleAdd = () => {
dataStore.title = "添加文章分类";
dataStore.visible = true;
};
//弹窗关闭钩子

View File

@@ -1,7 +1,7 @@
export const RULES = {
title: [{ required: true, message: "Banner名称不能为空 ! ", trigger: "blur" }],
type: [{ required: true, message: "前台显示不能为空 ! ", trigger: "change" }],
image: [{ required: true, message: "Banner图片不能为空 ! ", trigger: "change" }],
// image: [{ required: true, message: "Banner图片不能为空 ! ", trigger: "change" }],
banner_id: [{ required: true, message: "Banner分类不能为空 ! ", trigger: "change" }],
sort: [{ required: true, message: "排序不能为空 ! ", trigger: "change" }]
};

View File

@@ -4,7 +4,6 @@ const YES_OR_NO: any = {
0: "❌"
};
export const COLUMNS = [
{ type: "selection", fixed: "left", width: 40 },
{
align: "center",
fixed: true,