You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
387 lines
13 KiB
387 lines
13 KiB
<template>
|
|
<div class="content">
|
|
<div class="search">
|
|
<a-space>
|
|
<a-input v-model:value="searchlist.blogtitle" placeholder="博客标题" />
|
|
<a-input v-model:value="searchlist.typename" placeholder="分类名称" />
|
|
<a-range-picker :locale="locale" show-time @change="onChange" />
|
|
</a-space>
|
|
<a-space style="margin-left: 16px;">
|
|
<a-button @click="search">查询</a-button>
|
|
<a-button type="primary" ghost @click="addModal">新增</a-button>
|
|
</a-space>
|
|
</div>
|
|
<div class="modal">
|
|
<a-modal v-model:open="formControl.open" title="Basic Modal" width="100%" wrap-class-name="full-modal"
|
|
@ok="onSubmit" ok-text="确认" cancel-text="取消">
|
|
<a-form ref="formRef" :model="formState" :rules="rules">
|
|
<a-flex gap="large" justify="space-between">
|
|
<a-form-item label="博客标题" name="blogtitle">
|
|
<a-input v-model:value="formState.blogtitle" placeholder="请输入博客标题" class="items" />
|
|
</a-form-item>
|
|
<a-form-item label="博客类型" name="typeid">
|
|
<a-select v-model:value="formState.typeid" placeholder="请选择博客类型" class="items">
|
|
<a-select-option v-for="typeItem in typelist" :key="typeItem.key"
|
|
:value="typeItem.id">{{
|
|
typeItem.typename }}</a-select-option>
|
|
</a-select>
|
|
</a-form-item>
|
|
<a-form-item name="labelname" label="标签名称" class="items">
|
|
<a-select v-model:value="formState.labelnames" mode="multiple" placeholder="请选择标签">
|
|
<a-select-option :value="label.id" v-for="label in labellist">{{ label.labelname
|
|
}}</a-select-option>
|
|
</a-select>
|
|
</a-form-item>
|
|
<a-form-item label="文图地址" name="imglink" class="items">
|
|
<a-input v-model:value="formState.imglink" placeholder="请输入文图地址" />
|
|
</a-form-item>
|
|
</a-flex>
|
|
<v-md-editor v-model="formState.blogcontent" height="800px"
|
|
left-toolbar="undo redo clear | h bold italic strikethrough quote | ul ol table hr | link image code | save | tip | emoji"
|
|
></v-md-editor>
|
|
<a-form-item label="博客备注" name="descr" class="desrpad">
|
|
<a-textarea v-model:value="formState.descr" />
|
|
</a-form-item>
|
|
</a-form>
|
|
</a-modal>
|
|
</div>
|
|
<div class="table">
|
|
<a-table bordered :data-source="bloglist" :columns="columns">
|
|
<template #bodyCell="{ column, record }">
|
|
<template v-if="column.key === 'labels'">
|
|
<span>
|
|
<a-tag v-for="label in labelfilter(record.labelnames)" :key="label" color="cyan">
|
|
{{ label }}
|
|
</a-tag>
|
|
</span>
|
|
</template>
|
|
<template v-if="column.dataIndex === 'operation'">
|
|
<a-space>
|
|
<div>
|
|
<a-button size="small" danger @click="delModal(record.id)">删除</a-button>
|
|
<a-modal v-model:open="open" title="提示" @ok="ackDelete(record)" ok-text="确认"
|
|
cancel-text="取消" @cancel="unDelete">
|
|
<p>确认删除吗?</p>
|
|
</a-modal>
|
|
</div>
|
|
<a-button size="small" type="primary" ghost @click="editModal(record.id)">{{ record.id
|
|
}}编辑</a-button>
|
|
<a-button size="small" type="primary" ghost @click="ackWatch(record)">预览</a-button>
|
|
</a-space>
|
|
</template>
|
|
</template>
|
|
</a-table>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang='ts'>
|
|
import { ref, reactive, onMounted, toRefs } from 'vue';
|
|
import 'dayjs/locale/zh-cn';
|
|
import locale from 'ant-design-vue/es/date-picker/locale/zh_CN';
|
|
import dayjs from 'dayjs';
|
|
import type { Rule } from 'ant-design-vue/es/form';
|
|
import { useRouter } from "vue-router"
|
|
import { message } from 'ant-design-vue';
|
|
import type { blogInterface } from "@/api/admin/index"
|
|
import { get, post, put } from "@/tools/request"
|
|
import { blogStore } from '@/stores';
|
|
import type { labelInterface, typeInterface } from "@/api/admin/index"
|
|
dayjs.locale('zh-cn');
|
|
const router = useRouter()
|
|
const { delControl } = blogStore()
|
|
// 查询
|
|
const searchlist = reactive({
|
|
blogtitle: "",
|
|
typename: "",
|
|
start_date: '',
|
|
end_date: ''
|
|
})
|
|
const onChange = (date: string, dateString: string[]) => {
|
|
if (date && dateString.length === 2) {
|
|
searchlist.start_date = dateString[0];
|
|
searchlist.end_date = dateString[1];
|
|
} else {
|
|
searchlist.start_date = '';
|
|
searchlist.end_date = '';
|
|
}
|
|
console.log(dateString[0]);
|
|
};
|
|
|
|
const search = async () => {
|
|
try {
|
|
const response = await get("/blogs/list/search", {
|
|
blogtitle: searchlist.blogtitle,
|
|
typename: searchlist.typename,
|
|
start_date: searchlist.start_date,
|
|
end_date: searchlist.end_date
|
|
});
|
|
if (response && response.data) {
|
|
bloglist.value = response.data.data.map((items: any, index: any) => ({
|
|
key: (index + 1).toString(),
|
|
blogtitle: items.blogtitle,
|
|
typename: items.typename,
|
|
blogcontent: items.blogcontent,
|
|
wordcount: items.wordcount,
|
|
labelnames: items.labelnames,
|
|
create_at: dayjs(items.create_at).format('YYYY-MM-DD HH:mm:ss'),
|
|
update_at: dayjs(items.update_at).format('YYYY-MM-DD HH:mm:ss'),
|
|
descr: items.descr
|
|
}));
|
|
console.log(response)
|
|
} else {
|
|
console.log("request has no data");
|
|
}
|
|
} catch (error) {
|
|
console.error("request is exception", error);
|
|
}
|
|
};
|
|
|
|
const formState = ref({
|
|
id: '',
|
|
blogtitle: '',
|
|
typeid: null,
|
|
blogcontent: "",
|
|
labelnames: [],
|
|
descr: '',
|
|
imglink: ""
|
|
});
|
|
const labellist = ref<labelInterface[]>([])
|
|
const labelList = async () => {
|
|
try {
|
|
await get(
|
|
"labels/list"
|
|
).then(response => {
|
|
if (response) {
|
|
labellist.value = response.data.data.map((items: any) => ({
|
|
id: items.id,
|
|
labelname: items.labelname,
|
|
descr: items.descr
|
|
|
|
}))
|
|
} else {
|
|
console.log("the interface request data does not exist!")
|
|
}
|
|
|
|
})
|
|
} catch (error) {
|
|
console.error("Failed to fetch data", error);
|
|
}
|
|
}
|
|
const typelist = ref<typeInterface[]>([])
|
|
const typeList = async () => {
|
|
try {
|
|
await get("/types/list").then(response => {
|
|
if (response) {
|
|
typelist.value = response.data.data.map((items: any) => ({
|
|
...items
|
|
}))
|
|
} else {
|
|
console.log("the interface request data does not exist!")
|
|
}
|
|
|
|
})
|
|
} catch (error) {
|
|
console.error("Failed to fetch data", error);
|
|
}
|
|
}
|
|
|
|
const rules: Record<string, Rule[]> = {
|
|
blogtitle: [
|
|
{ required: true, message: '请输入博客标题', trigger: 'change' },
|
|
{ min: 4, max: 20, message: '博客标题允许4-20个字符', trigger: 'blur' },
|
|
],
|
|
descr: [
|
|
{ required: false },
|
|
{ max: 255, message: '博客备注不得超过255个字符', trigger: 'change' },
|
|
],
|
|
};
|
|
|
|
const formControl=ref({
|
|
open:false,
|
|
ids:null
|
|
})
|
|
|
|
const formRef = ref();
|
|
const addModal = () => {
|
|
formControl.value.open = true
|
|
console.log(formControl.value.ids)
|
|
}
|
|
|
|
const editModal = (id: any) => {
|
|
formControl.value.ids = id
|
|
formControl.value.open = true
|
|
get(
|
|
`/blogs/list/search/${id}`
|
|
).then(response=>{
|
|
formState.value=response.data.data
|
|
|
|
})
|
|
console.log(formControl.value.ids)
|
|
}
|
|
const onSubmit = () => {
|
|
formRef.value
|
|
.validate()
|
|
.then(async () => {
|
|
const labels = formState.value.labelnames.map(labelId => {
|
|
const label = labellist.value.find((label: any) => label.id === labelId);
|
|
return label ? { "id": label.id, "labelname": label.labelname, "descr": label.descr } : null;
|
|
});
|
|
const formdata = {
|
|
blog: {
|
|
blogtitle: formState.value.blogtitle,
|
|
typeid: formState.value.typeid,
|
|
imglink: formState.value.imglink,
|
|
blogcontent: formState.value.blogcontent,
|
|
descr: formState.value.descr
|
|
},
|
|
labels: labels
|
|
}
|
|
if (formControl.value.ids) {
|
|
await put(`/blogs/update/${formControl.value.ids}`, formdata)
|
|
formControl.value.open=false,
|
|
blogList()
|
|
} else {
|
|
await post('/blogs/add', formdata);
|
|
formControl.value.open=false,
|
|
blogList()
|
|
}
|
|
})
|
|
};
|
|
|
|
const open = ref<boolean>(false);
|
|
|
|
const delModal = (id: any) => {
|
|
delControl.open = true;
|
|
delControl.ids = id;
|
|
};
|
|
|
|
const bloglist = ref<blogInterface[]>([])
|
|
const blogList = async () => {
|
|
try {
|
|
const response = await get("/blogs/list");
|
|
if (response) {
|
|
bloglist.value = response.data.data.map((items: any, index: any) => ({
|
|
key: (index + 1).toString(),
|
|
id: items.id,
|
|
blogtitle: items.blogtitle,
|
|
create_at: dayjs(items.create_at).format('YYYY-MM-DD HH:mm:ss'),
|
|
update_at: dayjs(items.update_at).format('YYYY-MM-DD HH:mm:ss'),
|
|
readnum: items.readnum,
|
|
readminite: items.readminite,
|
|
wordcount: items.blogcontent.length,
|
|
img: items.img,
|
|
blogcontent: items.blogcontent,
|
|
typename: items.typename,
|
|
labelnames: items.labelnames
|
|
}))
|
|
} else {
|
|
console.log("bloglist is not exits")
|
|
}
|
|
} catch (error) {
|
|
console.log("bloglist is error")
|
|
}
|
|
|
|
}
|
|
const labelfilter = (labelnames: any) => {
|
|
let labels = []
|
|
if (labelnames) {
|
|
try {
|
|
labels = JSON.parse(labelnames)
|
|
} catch (error) {
|
|
console.error('Invalid JSON string:', labelnames);
|
|
}
|
|
}
|
|
return Array.isArray(labels) ? labels.filter(label => label && label.trim() !== '') : [];
|
|
}
|
|
// 博客删除
|
|
// const ackDelete = async (record:{key:string,id:number}) => {
|
|
// remove(`/blogs/delete/${toDelete.id}`).then((response) => {
|
|
// if (response.status === 200) {
|
|
// dataSource.value = dataSource.value.filter(item => item.key !== record.key);
|
|
// open.value = false;
|
|
// }
|
|
// message.info("删除成功")
|
|
// }).catch(error => {
|
|
// console.error('There was an error deleting the blog!', error);
|
|
// })
|
|
// };
|
|
// 博客修改
|
|
|
|
const ackUpdate = async (id: any) => {
|
|
router.push(`/admin/blogmanage/update/${id}`);
|
|
};
|
|
const ackWatch = async (record: { key: string, id: number }) => {
|
|
router.push(`/admin/blogmanage/watch`);
|
|
}
|
|
const unDelete = async () => {
|
|
message.warn("取消删除")
|
|
}
|
|
const columns = [
|
|
{
|
|
title: '序号',
|
|
dataIndex: 'key',
|
|
width: '5%',
|
|
},
|
|
{
|
|
title: '博客标题',
|
|
dataIndex: 'blogtitle',
|
|
width: '20%',
|
|
},
|
|
{
|
|
title: '博客分类',
|
|
dataIndex: 'typename',
|
|
},
|
|
{
|
|
title: '博客标签',
|
|
dataIndex: 'labelnames',
|
|
key: "labels"
|
|
},
|
|
{
|
|
title: '总字数',
|
|
dataIndex: 'wordcount',
|
|
key: "wordcount"
|
|
},
|
|
{
|
|
title: '发布时间',
|
|
dataIndex: 'create_at',
|
|
},
|
|
{
|
|
title: '修改时间',
|
|
dataIndex: 'update_at',
|
|
},
|
|
{
|
|
title: '操作',
|
|
dataIndex: 'operation',
|
|
},
|
|
];
|
|
|
|
onMounted(async () => {
|
|
blogList()
|
|
typeList()
|
|
labelList()
|
|
});
|
|
</script>
|
|
|
|
<style scoped>
|
|
.content {
|
|
padding: 24px 24px 0 24px;
|
|
}
|
|
|
|
.search {
|
|
margin: 0 0 24px 0;
|
|
}
|
|
|
|
.vditor {
|
|
width: 100%;
|
|
border: 1px solid #ccc;
|
|
}
|
|
|
|
.items {
|
|
width: calc(75vw/4);
|
|
}
|
|
|
|
.desrpad {
|
|
padding: 24px 0 0 0;
|
|
}
|
|
</style>
|