gemercheung 7 bulan lalu
induk
melakukan
5ab976a596

+ 2 - 1
.gitignore

@@ -1,3 +1,4 @@
 node_modules
 dist
-.vscode
+.vscode
+.idea

+ 3 - 1
packages/backend/src/modules/article/article.entity.ts

@@ -33,7 +33,9 @@ export class Article {
   remark: string;
 
   @OneToOne(() => Category, {
-    cascade: true, onDelete: 'CASCADE', createForeignKeyConstraints: false
+    cascade: true,
+    onDelete: 'CASCADE',
+    createForeignKeyConstraints: false,
   })
   @JoinColumn()
   category: Category;

+ 3 - 3
packages/backend/src/modules/category/category.controller.ts

@@ -12,7 +12,7 @@ import {
 } from '@nestjs/common';
 import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
 import { CategoryService } from './category.service';
-import { CreateCategoryDto, GetCategoryDto, UpdateCategoryDto } from './dto';
+import { CreateCategoryDto, GetAllCategoryDto, GetCategoryDto, UpdateCategoryDto } from './dto';
 
 @Controller('category')
 @ApiTags('category')
@@ -27,8 +27,8 @@ export class CategoryController {
   }
 
   @Get()
-  getAllCategories(@Query() getCategoryDto: GetCategoryDto) {
-    return this.categoryService.findAll(getCategoryDto);
+  getAllCategories(@Query() getAllCategoryDto: GetAllCategoryDto) {
+    return this.categoryService.findAll(getAllCategoryDto);
   }
   @Get('page')
   findPagination(@Query() queryDto: GetCategoryDto) {

+ 5 - 16
packages/backend/src/modules/category/category.entity.ts

@@ -31,11 +31,15 @@ export class Category {
   remark: string;
 
   @OneToOne(() => User, {
-    cascade: true,
+    createForeignKeyConstraints: false,
+    onDelete: 'CASCADE',
   })
   @JoinColumn()
   user: User;
 
+  @Column({ nullable: true })
+  userId: number;
+
   @ManyToOne(() => Category, (category) => category.children, {
     createForeignKeyConstraints: false,
   })
@@ -51,19 +55,4 @@ export class Category {
 
   @UpdateDateColumn()
   updateTime: Date;
-
-
-
-  // @UpdateDateColumn()
-  // updateTime: Date;
-  // @ManyToMany(() => User, (user) => user.roles, {
-  //   createForeignKeyConstraints: false,
-  // })
-  // users: User[];
-
-  // @ManyToMany(() => Permission, (permission) => permission.roles, {
-  //   createForeignKeyConstraints: false,
-  // })
-  // @JoinTable()
-  // permissions: Permission[];
 }

+ 5 - 24
packages/backend/src/modules/category/category.service.ts

@@ -2,7 +2,7 @@ import { BadRequestException, Injectable } from '@nestjs/common';
 import { Category } from './category.entity';
 import { InjectRepository } from '@nestjs/typeorm';
 import { Like, Repository } from 'typeorm';
-import { CreateCategoryDto, GetCategoryDto, UpdateCategoryDto } from './dto';
+import { CreateCategoryDto, GetAllCategoryDto, GetCategoryDto, UpdateCategoryDto } from './dto';
 @Injectable()
 export class CategoryService {
   constructor(
@@ -15,28 +15,8 @@ export class CategoryService {
     return this.categoryRepo.save(category);
   }
 
-  async findAll(query: GetCategoryDto) {
-    const pageSize = query.pageSize || 10;
-    const pageNo = query.pageNo || 1;
-    const [categories, total] = await this.categoryRepo.findAndCount({
-      where: {
-        title: Like(`%${query.title || ''}%`),
-        enable: query.enable || undefined,
-      },
-      order: {
-        createTime: 'ASC',
-      },
-      take: pageSize,
-      skip: (pageNo - 1) * pageSize,
-    });
-    const pageData = categories.map((item) => {
-      const newItem = {
-        ...item,
-      };
-      return newItem;
-    });
-
-    return { pageData, total };
+  async findAll(query: GetAllCategoryDto) {
+    return this.categoryRepo.find({ where: query });
   }
 
   async findPagination(query: GetCategoryDto) {
@@ -50,7 +30,7 @@ export class CategoryService {
       relations: { parent: true, user: true },
       order: {
         // title: 'ASC',
-        updateTime: 'ASC',
+        createTime: 'DESC',
       },
       take: pageSize,
       skip: (pageNo - 1) * pageSize,
@@ -70,6 +50,7 @@ export class CategoryService {
     const category = await this.categoryRepo.findOne({ where: { id } });
     if (!category) throw new BadRequestException('权限不存在或者已删除');
     const updateCategory = this.categoryRepo.merge(category, updateCategoryDto);
+    console.log('updateCategory', updateCategory);
     await this.categoryRepo.save(updateCategory);
     return true;
   }

+ 17 - 1
packages/backend/src/modules/category/dto.ts

@@ -12,6 +12,10 @@ import {
 } from 'class-validator';
 
 export class CreateCategoryDto {
+  @ApiProperty({ required: true })
+  @IsNumber()
+  userId: number;
+
   @ApiProperty()
   @IsString()
   @IsNotEmpty({ message: '标题不能为空' })
@@ -29,6 +33,11 @@ export class CreateCategoryDto {
   @IsNumber()
   @IsOptional()
   parentId?: number;
+
+  @ApiProperty({ nullable: true, required: false })
+  @IsString()
+  @IsOptional()
+  remark?: string;
 }
 
 export class GetCategoryDto {
@@ -49,4 +58,11 @@ export class GetCategoryDto {
   enable?: boolean;
 }
 
-export class UpdateCategoryDto extends PartialType(CreateCategoryDto) {}
+export class GetAllCategoryDto {
+  @ApiProperty({ required: false })
+  @IsOptional()
+  enable?: boolean;
+}
+
+export class UpdateCategoryDto extends PartialType(CreateCategoryDto) {
+}

+ 0 - 42
packages/frontend/src/views/category/add.vue

@@ -1,42 +0,0 @@
-<template>
-  <CommonPage show-footer>
-    <template #action>
-      <NButton type="primary" @click="router.push('article/add')">
-        <i class="i-material-symbols:add mr-4 text-18" />
-        创建新文章
-      </NButton>
-    </template>
-
-    <!-- <n-space size="large"> -->
-    <div style="min-height: 500px;">
-      <div id="markdown-container" />
-    </div>
-    <!-- </n-space> -->
-  </CommonPage>
-</template>
-
-<script setup>
-import { router } from '@/router'
-import Cherry from 'cherry-markdown'
-import { NButton } from 'naive-ui'
-import { onMounted } from 'vue'
-import 'cherry-markdown/dist/cherry-markdown.css'
-
-const articleValue = ref('')
-
-onMounted(() => {
-  const cherryInstance = new Cherry({
-    id: 'markdown-container',
-    value: articleValue.value,
-    editor: {
-      theme: 'default',
-      height: '100%',
-      defaultModel: '',
-    },
-  })
-
-  console.log('cherryInstance', cherryInstance)
-})
-
-function handleAdd() {}
-</script>

+ 1 - 4
packages/frontend/src/views/category/api.js

@@ -5,9 +5,6 @@ export default {
   read: (params = {}) => request.get('/category/page', { params }),
   update: data => request.patch(`/category/${data.id}`, data),
   delete: id => request.delete(`/category/${id}`),
+  getAll: data => request.get('/category?enable=1', data),
 
-  getAllPermissionTree: () => request.get('/permission/tree'),
-  getAllUsers: (params = {}) => request.get('/user', { params }),
-  addRoleUsers: (roleId, data) => request.patch(`/role/users/add/${roleId}`, data),
-  removeRoleUsers: (roleId, data) => request.patch(`/role/users/remove/${roleId}`, data),
 }

+ 41 - 69
packages/frontend/src/views/category/index.vue

@@ -1,79 +1,42 @@
 <template>
   <CommonPage>
     <template #action>
-      <NButton type="primary" @click="router.push('article/add')">
+      <NButton type="primary" @click="handleAdd()">
         <i class="i-material-symbols:add mr-4 text-18" />
-        新增文章
+        新增
       </NButton>
     </template>
 
-    <MeCrud
-      ref="$table"
-      v-model:query-items="queryItems"
-      :scroll-x="1200"
-      :columns="columns"
-      :get-data="api.read"
-    >
+    <MeCrud ref="$table" v-model:query-items="queryItems" :scroll-x="1200" :columns="columns" :get-data="api.read">
       <MeQueryItem label="分类名称" :label-width="80">
         <n-input v-model:value="queryItems.title" type="text" placeholder="请输入分类名称" clearable>
           <template #password-visible-icon />
         </n-input>
       </MeQueryItem>
       <MeQueryItem label="状态" :label-width="50">
-        <n-select
-          v-model:value="queryItems.enable"
-          clearable
-          :options="[
-            { label: '启用', value: 1 },
-            { label: '停用', value: 0 },
-          ]"
-        />
+        <n-select v-model:value="queryItems.enable" clearable :options="[
+          { label: '启用', value: 1 },
+          { label: '停用', value: 0 },
+        ]" />
       </MeQueryItem>
     </MeCrud>
 
     <MeModal ref="modalRef" width="520px">
-      <n-form
-        ref="modalFormRef"
-        label-placement="left"
-        label-align="left"
-        :label-width="80"
-        :model="modalForm"
-      >
-        <n-form-item
-          label="角色名"
-          path="name"
-          :rule="{
-            required: true,
-            message: '请输入角色名',
-            trigger: ['input', 'blur'],
-          }"
-        >
-          <n-input v-model:value="modalForm.name" />
+      <n-form ref="modalFormRef" label-placement="left" label-align="left" :label-width="80" :model="modalForm">
+        <n-form-item label="分类名" path="title" :rule="{
+          required: true,
+          message: '请输入分类名',
+          trigger: ['input', 'blur'],
+        }">
+          <n-input v-model:value="modalForm.title" />
         </n-form-item>
-        <n-form-item
-          label="角色编码"
-          path="code"
-          :rule="{
-            required: true,
-            message: '请输入角色编码',
-            trigger: ['input', 'blur'],
-          }"
-        >
-          <n-input v-model:value="modalForm.code" :disabled="modalAction !== 'add'" />
+        <n-form-item label="上层分类" path="parentId">
+          <n-select v-model:value="modalForm.parentId" :options="allCategory" clearable filterable tag />
         </n-form-item>
-        <n-form-item label="权限" path="permissionIds">
-          <n-tree
-            key-field="id"
-            label-field="name"
-            :selectable="false"
-            :data="permissionTree"
-            :checked-keys="modalForm.permissionIds"
-            :on-update:checked-keys="(keys) => (modalForm.permissionIds = keys)"
-
-            default-expand-all checkable check-on-click
-            class="cus-scroll max-h-200 w-full"
-          />
+        <n-form-item label="备注" path="remark">
+          <n-input v-model:value="modalForm.remark" />
         </n-form-item>
+
         <n-form-item label="状态" path="enable">
           <NSwitch v-model:value="modalForm.enable">
             <template #checked>
@@ -92,37 +55,47 @@
 <script setup>
 import { MeCrud, MeModal, MeQueryItem } from '@/components'
 import { useCrud } from '@/composables'
+import { useUserStore } from '@/store/index.js'
+import { formatDateTime } from '@/utils'
 import { NButton, NSwitch } from 'naive-ui'
+import { onMounted, watchEffect } from 'vue'
 import api from './api'
 
-defineOptions({ name: 'RoleMgt' })
+defineOptions({ name: 'Category' })
 
 const router = useRouter()
-
+const { userId } = useUserStore()
 const $table = ref(null)
 /** QueryBar筛选参数(可选) */
 const queryItems = ref({})
 
-onMounted(() => {
-  $table.value?.handleSearch()
-})
-
 const { modalRef, modalFormRef, modalAction, modalForm, handleAdd, handleDelete, handleEdit }
   = useCrud({
-    name: '文章',
+    name: '分类',
     doCreate: api.create,
     doDelete: api.delete,
     doUpdate: api.update,
     initForm: { enable: true },
     refresh: (_, keepCurrentPage) => $table.value?.handleSearch(keepCurrentPage),
   })
-
+onMounted(() => {
+  $table.value?.handleSearch()
+})
+watchEffect(() => {
+  if (userId) {
+    modalForm.value.userId = userId
+  }
+})
 const columns = [
   { title: '分类名称', key: 'title' },
   { title: '上级分类', key: 'parent.title' },
   { title: '备注', key: 'remark' },
   { title: '创建人', key: 'user.username' },
-  { title: '创建时间', key: 'createTime' },
+  {
+    title: '创建时间',
+    key: 'createTime',
+    render: row => h('span', formatDateTime(row.createTime)),
+  },
   {
     title: '状态',
     key: 'enable',
@@ -192,13 +165,12 @@ async function handleEnable(row) {
     row.enableLoading = false
     $message.success('操作成功')
     $table.value?.handleSearch()
-  }
-  catch (error) {
+  } catch (error) {
     console.error(error)
     row.enableLoading = false
   }
 }
 
-const permissionTree = ref([])
-api.getAllPermissionTree().then(({ data = [] }) => (permissionTree.value = data))
+const allCategory = ref([])
+api.getAll().then(({ data = [] }) => (allCategory.value = data.map(item => ({ label: item.title, value: item.id }))))
 </script>