From 2a04e29ae744310ae805b7dfbd1bb3eb617c9dc5 Mon Sep 17 00:00:00 2001
From: panda <7934952@qq.com>
Date: Tue, 2 Jul 2024 17:13:47 +0800
Subject: [PATCH] add new

---
 src/api/admin/index.ts                       |  28 ++-
 src/components/admin/MainWrapper.vue         |  13 +-
 src/components/blogs/HomePage.vue            |  37 +++-
 src/components/blogs/ceshi.vue               | 139 +++++++-----
 src/router/admin.ts                          |  66 +++---
 src/stores/index.ts                          | 131 ++++-------
 src/views/admin/LabelManageView.vue          | 221 +++++++++++++++++++
 src/views/admin/TypeManageView.vue           | 221 +++++++++++++++++++
 src/views/admin/blogmange/BlogFormView.vue   |  26 ++-
 src/views/admin/blogmange/BlogManageView.vue | 151 ++++++++++---
 10 files changed, 817 insertions(+), 216 deletions(-)
 create mode 100644 src/views/admin/LabelManageView.vue
 create mode 100644 src/views/admin/TypeManageView.vue

diff --git a/src/api/admin/index.ts b/src/api/admin/index.ts
index a67f7fc..038e017 100644
--- a/src/api/admin/index.ts
+++ b/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,
@@ -13,4 +25,18 @@ export interface comLinkInterface {
   linktext: string,
   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
 }
\ No newline at end of file
diff --git a/src/components/admin/MainWrapper.vue b/src/components/admin/MainWrapper.vue
index ed6ea69..b9ff55e 100644
--- a/src/components/admin/MainWrapper.vue
+++ b/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: '系统设置',
diff --git a/src/components/blogs/HomePage.vue b/src/components/blogs/HomePage.vue
index 17b1ae7..e97f281 100644
--- a/src/components/blogs/HomePage.vue
+++ b/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) {
@@ -276,11 +289,11 @@ const classticList=async ()=>{
 }
 const comLinkClick = (url: string) => {
     if (url.startsWith('http://') || url.startsWith('https://')) {
-      window.open(url, "_blank");  // 使用 window.location.href 打开外部链接
+        window.open(url, "_blank");  // 使用 window.location.href 打开外部链接
     } else {
-      router.push(url);  // 否则使用 Vue Router 的 push 方法导航
+        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;
diff --git a/src/components/blogs/ceshi.vue b/src/components/blogs/ceshi.vue
index d5c37b0..e997e5f 100644
--- a/src/components/blogs/ceshi.vue
+++ b/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!' }]"
-    >
-      <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>
+    <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'"
+          >
+            {{ 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>
 
diff --git a/src/router/admin.ts b/src/router/admin.ts
index 60a3fe1..c6c3237 100644
--- a/src/router/admin.ts
+++ b/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:"dashboard",
-                name:"dashboard",
-                component:()=>import("@/views/admin/DashBoardView.vue")
+        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:"blogmanage",
-                name:"blogmanage",
-                component:()=>import("@/views/admin/blogmange/BlogManageView.vue")
+                path: "blogmanage",
+                name: "blogmanage",
+                component: () => import("@/views/admin/blogmange/BlogManageView.vue")
             },
             {
                 path: "blogmanage/add",
@@ -22,28 +22,38 @@ const adminRoute:Array<RouteRecordRaw>=[
                 meta: { requiresAuth: true }
             },
             {
-            path: "blogmanage/update/:id",
-            component: () => import("@/views/admin/blogmange/BlogFormView.vue"),
-            meta: { requiresAuth: true },
-            props:true
+                path: "blogmanage/update/:id",
+                component: () => import("@/views/admin/blogmange/BlogFormView.vue"),
+                meta: { requiresAuth: 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")
             }
-            
+
         ]
     },
-    { 
-      path: "/login",
-      name: "login",
-      component: () => import("@/components/admin/SignIn.vue"),
+    {
+        path: "/login",
+        name: "login",
+        component: () => import("@/components/admin/SignIn.vue"),
     },
 ]
 export default adminRoute
\ No newline at end of file
diff --git a/src/stores/index.ts b/src/stores/index.ts
index 05304eb..84b1ec4 100644
--- a/src/stores/index.ts
+++ b/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 };
-});
 
diff --git a/src/views/admin/LabelManageView.vue b/src/views/admin/LabelManageView.vue
new file mode 100644
index 0000000..8c7fe92
--- /dev/null
+++ b/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>
\ No newline at end of file
diff --git a/src/views/admin/TypeManageView.vue b/src/views/admin/TypeManageView.vue
new file mode 100644
index 0000000..e20b342
--- /dev/null
+++ b/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>
\ No newline at end of file
diff --git a/src/views/admin/blogmange/BlogFormView.vue b/src/views/admin/blogmange/BlogFormView.vue
index 807fab0..08a2e17 100644
--- a/src/views/admin/blogmange/BlogFormView.vue
+++ b/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 {
diff --git a/src/views/admin/blogmange/BlogManageView.vue b/src/views/admin/blogmange/BlogManageView.vue
index 44a1809..f2f9755 100644
--- a/src/views/admin/blogmange/BlogManageView.vue
+++ b/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>