Browse Source

add new

master
panda 9 months ago
parent
commit
2a04e29ae7
  1. 28
      src/api/admin/index.ts
  2. 13
      src/components/admin/MainWrapper.vue
  3. 33
      src/components/blogs/HomePage.vue
  4. 137
      src/components/blogs/ceshi.vue
  5. 48
      src/router/admin.ts
  6. 131
      src/stores/index.ts
  7. 221
      src/views/admin/LabelManageView.vue
  8. 221
      src/views/admin/TypeManageView.vue
  9. 26
      src/views/admin/blogmange/BlogFormView.vue
  10. 151
      src/views/admin/blogmange/BlogManageView.vue

28
src/api/admin/index.ts

@ -1,4 +1,16 @@
// 语录管理
export interface blogInterface {
key: string,
blogtitle: string,
create_at: Date,
readnum: number,
readminite: number,
wordcount: number,
img: string,
blogcontent: string,
typename: string,
labelnames: string
}
export interface classticInterface {
key: string,
id?: number,
@ -14,3 +26,17 @@ export interface comLinkInterface {
linkurl: string,
descr: string
}
export interface typeInterface {
key: string,
id?: number,
typename: string,
descr: string
}
export interface labelInterface {
key: string,
id?: number,
labelname: string,
descr: string
}

13
src/components/admin/MainWrapper.vue

@ -100,27 +100,34 @@ const items = reactive([
},
{
key: '7',
icon: () => h(iconComponents.TypeOutLined),
label: '标签管理',
title: '标签管理',
url: '/admin/labelmanage'
},
{
key: '8',
icon: () => h(iconComponents.CommentOutLined),
label: '评论管理',
title: '评论管理',
url: '/admin/commentmanage'
},
{
key: '8',
key: '9',
icon: () => h(iconComponents.PhotoOutLined),
label: '相册管理',
title: '相册管理',
url: '/admin/imagemanage'
},
{
key: '9',
key: '10',
icon: () => h(iconComponents.FileOutLined),
label: '文件管理',
title: '文件管理',
url: '/admin/filemanage'
},
{
key: '10',
key: '11',
icon: () => h(iconComponents.SystemOutLined),
label: '系统设置',
title: '系统设置',

33
src/components/blogs/HomePage.vue

@ -2,7 +2,8 @@
<Simplebar @scroll="handleScroll">
<!-- 头部导航菜单 -->
<div class="headerMenu" v-if="show_menu">
<a-menu v-model:selectedKeys="current" mode="horizontal" :items="items" style="border-bottom: none;" />
<a-menu v-model:selectedKeys="current" mode="horizontal" :items="items" style="border-bottom: none;"
@click="jumpMenu" />
<a-input-search v-model:value="value" placeholder="search" style="width: 200px" @search="onSearch" />
</div>
<div class="author" v-if="show_author">{{ author }}</div>
@ -114,7 +115,7 @@ import { onMounted, watch } from 'vue';
import { CaretRightOutlined } from '@ant-design/icons-vue';
import 'APlayer/dist/APlayer.min.css';
import APlayer from 'APlayer';
import {get} from "@/tools/request"
import { get } from "@/tools/request"
import { createEcharts } from "@/hooks/intex"
import { useRouter, useRoute } from 'vue-router';
import iconComponents from "@/assets/index";
@ -123,7 +124,7 @@ import type { comLinkInterface } from '@/api/admin/index';
const router = useRouter()
const route = useRoute()
const author=ref("SunFree.")
const author = ref("SunFree.")
/**
* 隐藏参数
*/
@ -138,14 +139,14 @@ const { show_menu, show_carousel, show_author, show_anchornDown } = toRefs(idSho
const mainCss = reactive({
marginTop: "0px"
})
type MenuProps = any;
const current = ref<string[]>(['home']);
const items = ref<MenuProps['items']>([
{
key: 'home',
icon: () => h(HomeOutlined),
label: h('a', { href: '/' }, '首页'),
label: '首页',
title: '首页',
url: "/home"
},
{
@ -153,12 +154,14 @@ const items = ref<MenuProps['items']>([
icon: () => h(HighlightOutlined),
label: h('a', { href: "/blog" }, '博客'),
title: '博客',
url: "/blog"
},
{
key: 'diary',
icon: () => h(ProfileOutlined),
label: h('a', { href: "/diary" }, '日记'),
title: '日记',
url: "/diary"
},
{
key: 'album',
@ -189,14 +192,24 @@ const items = ref<MenuProps['items']>([
icon: () => h(UsergroupDeleteOutlined),
label: h('a', { href: "/chart" }, '收支图'),
title: '收支图',
url: "/chart"
},
{
key: 'aboutme',
icon: () => h(UsergroupDeleteOutlined),
label: h('a', { href: "/aboutme" }, '关于sunfree'),
title: '关于sunfree',
url: "/aboutme"
},
]);
const jumpMenu = ({ key }:{key:string}) => {
// `item` `key` `url`
const selectedItem = items.value.find((i:any) => i.key === key);
if (selectedItem && selectedItem.url) {
router.push(selectedItem.url);
}
};
const updateCarouselVisibility = (routeName: any) => {
handleScrollEnabled.value = false;
if (scrollbar.value) {
@ -255,8 +268,8 @@ const downScroll = () => {
* 左侧栏
*/
//
const classticlist=ref<classticInterface[]>([])
const classticList=async ()=>{
const classticlist = ref<classticInterface[]>([])
const classticList = async () => {
try {
await get("/classtics/list").then(response => {
if (response) {
@ -280,7 +293,7 @@ const comLinkClick = (url: string) => {
} else {
router.push(url); // 使 Vue Router push
}
}
}
const comlinklist = ref<comLinkInterface[]>([])
const comLinkList = async () => {
try {
@ -586,10 +599,12 @@ watch(
border-style: hidden;
transform: translateX(-50%);
}
.anchorDown span{
.anchorDown span {
font-size: 35px;
color: aliceblue;
}
.mainContainer {
display: flex;
justify-content: center;

137
src/components/blogs/ceshi.vue

@ -1,58 +1,95 @@
<template>
<a-form
:model="formState"
name="basic"
:label-col="{ span: 8 }"
:wrapper-col="{ span: 16 }"
autocomplete="off"
@finish="onFinish"
@finishFailed="onFinishFailed"
>
<a-form-item
label="Username"
name="username"
:rules="[{ required: true, message: 'Please input your username!' }]"
>
<a-input v-model:value="formState.username" />
</a-form-item>
<a-table :columns="columns" :data-source="data">
<template #headerCell="{ column }">
<template v-if="column.key === 'name'">
<span>
<!-- <smile-outlined /> -->
Name
</span>
</template>
</template>
<a-form-item
label="Password"
name="password"
:rules="[{ required: true, message: 'Please input your password!' }]"
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'name'">
{{ record.name }}
</template>
<template v-else-if="column.key === 'tags'">
<span>
<a-tag
v-for="tag in record.tags"
:key="tag"
:color="tag === 'loser' ? 'volcano' : tag.length > 5 ? 'geekblue' : 'green'"
>
<a-input-password v-model:value="formState.password" />
</a-form-item>
<a-form-item name="remember" :wrapper-col="{ offset: 8, span: 16 }">
<a-checkbox v-model:checked="formState.remember">Remember me</a-checkbox>
</a-form-item>
<a-form-item :wrapper-col="{ offset: 8, span: 16 }">
<a-button type="primary" html-type="submit">Submit</a-button>
</a-form-item>
</a-form>
{{ tag.toUpperCase() }}
</a-tag>
</span>
</template>
<template v-else-if="column.key === 'action'">
<span>
<a>Invite {{ record.name }}</a>
<a-divider type="vertical" />
<a>Delete</a>
<a-divider type="vertical" />
<a class="ant-dropdown-link">
More actions
<down-outlined />
</a>
</span>
</template>
</template>
</a-table>
</template>
<script lang="ts" setup>
import { reactive } from 'vue';
interface FormState {
username: string;
password: string;
remember: boolean;
}
const formState = reactive<FormState>({
username: '',
password: '',
remember: true,
});
const onFinish = (values: any) => {
console.log('Success:', values);
};
import { SmileOutlined, DownOutlined } from '@ant-design/icons-vue';
const columns = [
{
name: 'Name',
dataIndex: 'name',
key: 'name',
},
{
title: 'Age',
dataIndex: 'age',
key: 'age',
},
{
title: 'Address',
dataIndex: 'address',
key: 'address',
},
{
title: 'Tags',
key: 'tags',
dataIndex: 'tags',
},
{
title: 'Action',
key: 'action',
},
];
const onFinishFailed = (errorInfo: any) => {
console.log('Failed:', errorInfo);
};
const data = [
{
key: '1',
name: 'John Brown',
age: 32,
address: 'New York No. 1 Lake Park',
tags: ['nice', 'developer'],
},
{
key: '2',
name: 'Jim Green',
age: 42,
address: 'London No. 1 Lake Park',
tags: ['loser'],
},
{
key: '3',
name: 'Joe Black',
age: 32,
address: 'Sidney No. 1 Lake Park',
tags: ['cool', 'teacher'],
},
];
</script>

48
src/router/admin.ts

@ -1,20 +1,20 @@
import type { RouteRecordRaw } from 'vue-router'
const adminRoute:Array<RouteRecordRaw>=[
const adminRoute: Array<RouteRecordRaw> = [
{
path:"/admin",
redirect:"/admin/dashboard",
name:'admin',
component:()=> import("@/components/admin/MainWrapper.vue"),
children:[
path: "/admin",
redirect: "/admin/dashboard",
name: 'admin',
component: () => import("@/components/admin/MainWrapper.vue"),
children: [
{
path:"dashboard",
name:"dashboard",
component:()=>import("@/views/admin/DashBoardView.vue")
path: "dashboard",
name: "dashboard",
component: () => import("@/views/admin/DashBoardView.vue")
},
{
path:"blogmanage",
name:"blogmanage",
component:()=>import("@/views/admin/blogmange/BlogManageView.vue")
path: "blogmanage",
name: "blogmanage",
component: () => import("@/views/admin/blogmange/BlogManageView.vue")
},
{
path: "blogmanage/add",
@ -25,17 +25,27 @@ const adminRoute:Array<RouteRecordRaw>=[
path: "blogmanage/update/:id",
component: () => import("@/views/admin/blogmange/BlogFormView.vue"),
meta: { requiresAuth: true },
props:true
props: true
},
{
path:"classticmanage",
name:"classticmanage",
component:()=>import("@/views/admin/ClassticManageView.vue")
path: "classticmanage",
name: "classticmanage",
component: () => import("@/views/admin/ClassticManageView.vue")
},
{
path:"commonlinkmanage",
name:"commonlinkmanage",
component:()=>import("@/views/admin/CommonLinkManageView.vue")
path: "commonlinkmanage",
name: "commonlinkmanage",
component: () => import("@/views/admin/CommonLinkManageView.vue")
},
{
path: "typemanage",
name: "typemanage",
component: () => import("@/views/admin/TypeManageView.vue")
},
{
path: "labelmanage",
name: "labelmanage",
component: () => import("@/views/admin/LabelManageView.vue")
}
]

131
src/stores/index.ts

@ -1,12 +1,19 @@
import { reactive, ref } from 'vue'
import { defineStore } from 'pinia'
import { get } from "@/tools/request"
import dayjs from 'dayjs';
import type { blogInterface } from '@/api/admin';
export const mainWrapperStore=defineStore("mainWrapper",()=>{
})
export const blogStore = defineStore("blog", () => {
const delControl = reactive({
open: false,
ids: ""
})
return { delControl }
})
export const classticStore = defineStore("classtic", () => {
const addControl = reactive({
open: false,
@ -47,19 +54,46 @@ export const comLinkStore = defineStore("comLink", () => {
})
return { addControl, delControl,editControl }
})
export const typeStore = defineStore("type", () => {
const addControl = reactive({
open: false,
title: "",
ids: ""
})
const delControl = reactive({
open: false,
ids: ""
})
const editControl = reactive({
open: false,
ids: "",
title:""
})
return { addControl, delControl,editControl }
})
export const labelStore = defineStore("label", () => {
const addControl = reactive({
open: false,
title: "",
ids: ""
})
const delControl = reactive({
open: false,
ids: ""
})
const editControl = reactive({
open: false,
ids: "",
title:""
})
return { addControl, delControl,editControl }
})
// 博客列表
const bloglist = ref<blogInterface[]>([])
export const useAuthStore = defineStore("auth", () => {
const tokenValue = ref("")
function setToken(token: string) {
@ -71,82 +105,5 @@ export const useAuthStore = defineStore("auth", () => {
return { setToken, removeToken }
})
// 博客列表接口
export const blogContentStore = defineStore("blog", () => {
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(),
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.wordcount,
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")
}
}
return { blogList, bloglist }
})
// 博客查询接口
export const blogSearchStore = defineStore('blogsearch', () => {
const searchValue = reactive({
blogtitle: '',
typename: '',
start_date: '',
end_date: ''
});
const onChange = (date: string, dateString: string[]) => {
if (date && dateString.length === 2) {
searchValue.start_date = dateString[0];
searchValue.end_date = dateString[1];
} else {
searchValue.start_date = '';
searchValue.end_date = '';
}
console.log(dateString[0]);
};
const blogSearch = async () => {
try {
const response = await get("/blogs/list/search", {
blogtitle: searchValue.blogtitle,
typename: searchValue.typename,
start_date: searchValue.start_date,
end_date: searchValue.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,
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);
}
};
return { searchValue, onChange, blogSearch };
});

221
src/views/admin/LabelManageView.vue

@ -0,0 +1,221 @@
<template>
<div class="content">
<div class="search">
<a-space>
<a-input v-model:value="searchlist.labelname" placeholder="标签名称" />
</a-space>
<a-space style="margin-left: 16px;">
<a-button @click="search">查询</a-button>
<a-button type="primary" ghost @click="addModal">新增</a-button>
<a-modal v-model:open="addControl.open" :title="addControl.title" cancelText="取消" okText="确定" @ok="add">
<a-form ref="formRef" :model="addList" name="basic" :label-col="{ span: 4, offset: 2 }"
:wrapper-col="{ span: 16 }">
<a-form-item label="标签名称" name="labelname" :rules="[{ required: true, message: '请输入标签名称!' }]">
<a-input v-model:value="addList.labelname" />
</a-form-item>
<a-form-item label="备注" name="descr" :rules="[{ required: true, message: '请输入备注!' }]">
<a-input v-model:value="addList.descr" />
</a-form-item>
</a-form>
</a-modal>
</a-space>
</div>
<div class="table">
<a-table bordered :data-source="labellist" :columns="columns">
<template #bodyCell="{ column, record }">
<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="delControl.open" title="提示" ok-text="确认" cancel-text="取消"
@ok="del">
<p>确认删除吗</p>
</a-modal>
</div>
<a-button size="small" type="primary" ghost @click="editModal(record.id)">编辑</a-button>
<a-modal v-model:open="editControl.open" :title="editControl.title" cancelText="取消"
okText="确定" @ok="edit">
<a-form ref="formRef" :model="editList" name="basic" :label-col="{ span: 4, offset: 2 }"
:wrapper-col="{ span: 16 }">
<a-form-item label="标签名称" name="labelname"
:rules="[{ required: true, message: '请修改标签名称!' }]">
<a-input v-model:value="editList.labelname" />
</a-form-item>
<a-form-item label="备注" name="descr"
:rules="[{ required: true, message: '请修改备注!' }]">
<a-input v-model:value="editList.descr" />
</a-form-item>
</a-form>
</a-modal>
</a-space>
</template>
</template>
</a-table>
</div>
</div>
</template>
<script setup lang='ts'>
import { onMounted, reactive, ref } from 'vue';
import { labelStore } from "@/stores/index"
import type { labelInterface } from "@/api/admin/index"
import { get, post, remove, put } from '@/tools/request';
const { delControl, addControl, editControl } = labelStore()
const labellist = ref<labelInterface[]>([])
const searchlist = reactive({
labelname: ""
})
const addList = ref({
labelname: "",
descr: ""
})
const editList = ref({
labelname: "",
descr: ""
})
const labelList = async () => {
try {
await get("/labels/list").then(response => {
if (response) {
labellist.value = response.data.data.map((item: any, index: any) => ({
key: (index + 1).toString(),
id: item.id,
labelname: item.labelname,
descr: item.descr
}));
} else {
console.log("the interface request data does not exist!")
}
})
} catch (error) {
console.error("Failed to fetch data", error);
}
}
const search = async () => {
try {
await get(
"/labels/list/search",
{ labelname: searchlist.labelname }
).then(response => {
if (response) {
labellist.value = response.data.data.map((items: any, index: any) => ({
key: (index + 1).toString(),
id: items.id,
labelname: items.labelname,
descr: items.descr
}))
} else {
console.log("the interface request data does not exist!")
}
})
} catch (error) {
console.log("interface request exception")
}
}
const addModal = () => {
addControl.title = "新增"
addControl.open = true;
};
const formRef = ref();
const add = async () => {
try {
await post(
"/labels/add",
addList.value
)
labelList()
addControl.open = false
formRef.value.resetFields();
} catch (error) {
console.log("interface request exception")
}
}
const delModal = (id: any) => {
delControl.ids = id
delControl.open = true
};
//
const del = async (id: any) => {
id = delControl.ids
try {
if (id) {
await remove(
`/labels/delete/${id}`
)
labelList()
} else {
console.log("id do not exist!")
}
} catch (error) {
console.log("interface request exception")
}
delControl.open = false
}
const editModal = (id: any) => {
editControl.ids = id
editControl.title = "编辑"
editControl.open = true
get(
`/labels/list/search/${id}`
).then(response => {
editList.value = response.data.data
})
}
const edit = async (id: any) => {
id = editControl.ids
try {
if (id) {
await put(
`/labels/update/${id}`,
editList.value
)
editControl.open = false
formRef.value.resetFields()
labelList()
} else {
console.log("id do not exist!")
}
} catch (error) {
console.log("interface request exception")
}
}
//
onMounted(async () => {
labelList()
});
const columns = [
{
title: '序号',
dataIndex: 'key',
width: '5%',
},
{
title: '标签名称',
dataIndex: 'labelname',
width: '20%',
},
{
title: '备注',
dataIndex: 'descr',
},
{
title: '操作',
dataIndex: 'operation',
},
];
</script>
<style scoped>
.content {
padding: 24px 24px 0 24px;
}
.search {
margin: 0 0 24px 0;
}
</style>

221
src/views/admin/TypeManageView.vue

@ -0,0 +1,221 @@
<template>
<div class="content">
<div class="search">
<a-space>
<a-input v-model:value="searchlist.typename" placeholder="类型名称" />
</a-space>
<a-space style="margin-left: 16px;">
<a-button @click="search">查询</a-button>
<a-button type="primary" ghost @click="addModal">新增</a-button>
<a-modal v-model:open="addControl.open" :title="addControl.title" cancelText="取消" okText="确定" @ok="add">
<a-form ref="formRef" :model="addList" name="basic" :label-col="{ span: 4, offset: 2 }"
:wrapper-col="{ span: 16 }">
<a-form-item label="类型名称" name="typename" :rules="[{ required: true, message: '请输入类型名称!' }]">
<a-input v-model:value="addList.typename" />
</a-form-item>
<a-form-item label="备注" name="descr" :rules="[{ required: true, message: '请输入备注!' }]">
<a-input v-model:value="addList.descr" />
</a-form-item>
</a-form>
</a-modal>
</a-space>
</div>
<div class="table">
<a-table bordered :data-source="typelist" :columns="columns">
<template #bodyCell="{ column, record }">
<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="delControl.open" title="提示" ok-text="确认" cancel-text="取消"
@ok="del">
<p>确认删除吗</p>
</a-modal>
</div>
<a-button size="small" type="primary" ghost @click="editModal(record.id)">编辑</a-button>
<a-modal v-model:open="editControl.open" :title="editControl.title" cancelText="取消"
okText="确定" @ok="edit">
<a-form ref="formRef" :model="editList" name="basic" :label-col="{ span: 4, offset: 2 }"
:wrapper-col="{ span: 16 }">
<a-form-item label="类型名称" name="typename"
:rules="[{ required: true, message: '请修改类型名称!' }]">
<a-input v-model:value="editList.typename" />
</a-form-item>
<a-form-item label="备注" name="descr"
:rules="[{ required: true, message: '请修改备注!' }]">
<a-input v-model:value="editList.descr" />
</a-form-item>
</a-form>
</a-modal>
</a-space>
</template>
</template>
</a-table>
</div>
</div>
</template>
<script setup lang='ts'>
import { onMounted, reactive, ref } from 'vue';
import { typeStore } from "@/stores/index"
import type { typeInterface } from "@/api/admin/index"
import { get, post, remove, put } from '@/tools/request';
const { delControl, addControl, editControl } = typeStore()
const typelist = ref<typeInterface[]>([])
const searchlist = reactive({
typename: ""
})
const addList = ref({
typename: "",
descr: ""
})
const editList = ref({
typename: "",
descr: ""
})
const typeList = async () => {
try {
await get("/types/list").then(response => {
if (response) {
typelist.value = response.data.data.map((item: any, index: any) => ({
key: (index + 1).toString(),
id: item.id,
typename: item.typename,
descr: item.descr
}));
} else {
console.log("the interface request data does not exist!")
}
})
} catch (error) {
console.error("Failed to fetch data", error);
}
}
const search = async () => {
try {
await get(
"/types/list/search",
{ typename: searchlist.typename }
).then(response => {
if (response) {
typelist.value = response.data.data.map((items: any, index: any) => ({
key: (index + 1).toString(),
id: items.id,
typename: items.typename,
descr: items.descr
}))
} else {
console.log("the interface request data does not exist!")
}
})
} catch (error) {
console.log("interface request exception")
}
}
const addModal = () => {
addControl.title = "新增"
addControl.open = true;
};
const formRef = ref();
const add = async () => {
try {
await post(
"/types/add",
addList.value
)
typeList()
addControl.open = false
formRef.value.resetFields();
} catch (error) {
console.log("interface request exception")
}
}
const delModal = (id: any) => {
delControl.ids = id
delControl.open = true
};
//
const del = async (id: any) => {
id = delControl.ids
try {
if (id) {
await remove(
`/types/delete/${id}`
)
typeList()
} else {
console.log("id do not exist!")
}
} catch (error) {
console.log("interface request exception")
}
delControl.open = false
}
const editModal = (id: any) => {
editControl.ids = id
editControl.title = "编辑"
editControl.open = true
get(
`/types/list/search/${id}`
).then(response => {
editList.value = response.data.data
})
}
const edit = async (id: any) => {
id = editControl.ids
try {
if (id) {
await put(
`/types/update/${id}`,
editList.value
)
editControl.open = false
formRef.value.resetFields()
typeList()
} else {
console.log("id do not exist!")
}
} catch (error) {
console.log("interface request exception")
}
}
//
onMounted(async () => {
typeList()
});
const columns = [
{
title: '序号',
dataIndex: 'key',
width: '5%',
},
{
title: '类型名称',
dataIndex: 'typename',
width: '20%',
},
{
title: '备注',
dataIndex: 'descr',
},
{
title: '操作',
dataIndex: 'operation',
},
];
</script>
<style scoped>
.content {
padding: 24px 24px 0 24px;
}
.search {
margin: 0 0 24px 0;
}
</style>

26
src/views/admin/blogmange/BlogFormView.vue

@ -11,6 +11,15 @@
typeItem.typename }}</a-select-option>
</a-select>
</a-form-item>
<a-form-item name="labelname" label="标签名称" class="items">
<a-select v-model:value="formState['labelname']" mode="multiple" placeholder="请选择标签">
<a-select-option value="red">Red</a-select-option>
<a-select-option value="green">Green</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="文图地址" name="textimg" class="items">
<a-input v-model:value="formState.imglink" placeholder="请输入文图地址"/>
</a-form-item>
</a-flex>
<v-md-editor v-model="content" height="900px"></v-md-editor>
<a-form-item label="博客备注" name="descr" class="desrpad">
@ -34,13 +43,16 @@ import type { UnwrapRef } from 'vue';
import type { Rule } from 'ant-design-vue/es/form';
import { post, get, put } from '@/tools/request';
import { useRouter } from 'vue-router'
const router = useRouter()
interface FormState {
id?: number;
blogtitle: string;
typeid: number;
blogcontent: string;
labelname: string[];
descr: string;
imglink: string
}
const formRef = ref();
@ -48,7 +60,9 @@ const formState: UnwrapRef<FormState> = reactive({
blogtitle: '',
typeid: 1,
blogcontent: "",
labelname: [],
descr: '',
imglink: ""
});
const rules: Record<string, Rule[]> = {
blogtitle: [
@ -61,11 +75,11 @@ const rules: Record<string, Rule[]> = {
],
};
const content = ref();
interface TypeStateData{
id:number,
key:string,
typename:string,
descr:string
interface TypeStateData {
id: number,
key: string,
typename: string,
descr: string
}
const typedata = ref<TypeStateData[]>([])
onMounted(async () => {
@ -112,7 +126,7 @@ const resetForm = () => {
}
.items {
width: calc(75vw/2);
width: calc(75vw/4);
}
#content {

151
src/views/admin/blogmange/BlogManageView.vue

@ -2,25 +2,31 @@
<div class="content">
<div class="search">
<a-space>
<a-input v-model:value="blogSearch.searchValue.blogtitle" placeholder="博客标题" />
<a-input v-model:value="blogSearch.searchValue.typename" placeholder="分类名称" />
<a-range-picker :locale="locale" show-time @change="blogSearch.onChange" />
<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="blogSearch.blogSearch">查询</a-button>
<a-button @click="search">查询</a-button>
<a-button type="primary" ghost @click="blogAdd">新增</a-button>
</a-space>
</div>
<div class="table">
<a-table bordered :data-source="blogContent.bloglist" :columns="columns">
<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="showModal(record.key, record.id)">删除</a-button>
<a-modal v-model:open="open" title="提示" @ok="ackDelete(record)" ok-text="确认" cancel-text="取消" @cancel="unDelete">
<a-button size="small" danger @click="showModal(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>
@ -41,33 +47,106 @@ import locale from 'ant-design-vue/es/date-picker/locale/zh_CN';
import dayjs from 'dayjs';
import { useRouter } from "vue-router"
import { message } from 'ant-design-vue';
import { blogContentStore,blogSearchStore } from '@/stores';
import type { blogInterface } from "@/api/admin/index"
import { get } from "@/tools/request"
import { blogStore } from '@/stores';
dayjs.locale('zh-cn');
const router = useRouter()
const blogContent=blogContentStore()
const blogSearch=blogSearchStore()
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 open = ref<boolean>(false);
const toDelete = reactive<{ key: string, id: number }>({
key: '',
id: 0
});
const showModal = (key: string, id: number) => {
open.value = true;
toDelete.key = key;
toDelete.id = id;
const showModal = (id: any) => {
delControl.open = true;
delControl.ids = id;
};
//
const blogAdd = function () {
router.push('/admin/blogmanage/add')
}
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(),
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.wordcount,
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")
}
//
onMounted(async () => {
blogContent.blogList()
});
}
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) => {
@ -82,13 +161,13 @@ onMounted(async () => {
// };
//
const ackUpdate =async (record: { key: string, id: number }) => {
const ackUpdate = async (record: { key: string, id: number }) => {
router.push(`/admin/blogmanage/update/${record.id}`);
};
const ackWatch=async (record: { key: string, id: number }) => {
const ackWatch = async (record: { key: string, id: number }) => {
router.push(`/admin/blogmanage/watch`);
}
const unDelete=async ()=>{
const unDelete = async () => {
message.warn("取消删除")
}
const columns = [
@ -106,6 +185,16 @@ const columns = [
title: '博客分类',
dataIndex: 'typename',
},
{
title: '博客标签',
dataIndex: 'labelnames',
key: "labels"
},
{
title: '总字数',
dataIndex: 'wordcount',
key: "wordcount"
},
{
title: '发布时间',
dataIndex: 'create_at',
@ -119,6 +208,10 @@ const columns = [
dataIndex: 'operation',
},
];
onMounted(async () => {
blogList()
});
</script>
<style scoped>

Loading…
Cancel
Save