소스 검색

feat: save

gemercheung 7 달 전
부모
커밋
d557a345d5

+ 5 - 2
packages/backend/src/modules/article/article.controller.ts

@@ -19,7 +19,7 @@ import { CreateArticleDto, GetArticleDto, QueryArticleDto, UpdateArticleDto } fr
 @ApiBearerAuth('JWT')
 @UseGuards(JwtGuard)
 export class ArticleController {
-  constructor(private readonly articleService: ArticleService) {}
+  constructor(private readonly articleService: ArticleService) { }
 
   @Post()
   create(@Body() createArticleDto: CreateArticleDto) {
@@ -30,7 +30,10 @@ export class ArticleController {
   getAll(@Param() getArticleDto: GetArticleDto) {
     return this.articleService.findAll(getArticleDto);
   }
-
+  @Get('detail/:id')
+  getArticle(@Param('id') id: string) {
+    return this.articleService.find(+id);
+  }
   @Get('page')
   findPagination(@Query() queryDto: QueryArticleDto) {
     return this.articleService.findPagination(queryDto);

+ 8 - 2
packages/backend/src/modules/article/article.entity.ts

@@ -40,18 +40,24 @@ export class Article {
   @JoinColumn()
   category: Category;
 
+  @Column({ nullable: true })
+  categoryId: number;
+
   @OneToOne(() => User, {
     cascade: true,
   })
   @JoinColumn()
   user: User;
 
+  @Column({ nullable: true })
+  userId: number;
+
   @CreateDateColumn()
   createTime: Date;
 
   @UpdateDateColumn()
   updateTime: Date;
 
-  @Column({ nullable: true })
-  categoryId: number;
+
+
 }

+ 6 - 22
packages/backend/src/modules/article/article.service.ts

@@ -8,34 +8,14 @@ export class ArticleService {
   constructor(
     @InjectRepository(Article)
     private articleRepo: Repository<Article>,
-  ) {}
+  ) { }
   async create(createArticleDto: CreateArticleDto) {
     const article = this.articleRepo.create(createArticleDto);
     return this.articleRepo.save(article);
   }
 
   async findAll(query: GetArticleDto) {
-    const pageSize = query.pageSize || 10;
-    const pageNo = query.pageNo || 1;
-    const [categories, total] = await this.articleRepo.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 };
+    return this.articleRepo.find({ where: query });
   }
 
   async findPagination(query: QueryArticleDto) {
@@ -65,6 +45,10 @@ export class ArticleService {
     return true;
   }
 
+  async find(id: number) {
+    return await this.articleRepo.findOne({ where: { id } });
+  }
+
   async update(id: number, updateArticleDto: UpdateArticleDto) {
     const article = await this.articleRepo.findOne({ where: { id } });
     if (!article) throw new BadRequestException('权限不存在或者已删除');

+ 5 - 4
packages/frontend/src/views/article/api.js

@@ -5,9 +5,10 @@ export default {
   read: (params = {}) => request.get('/article/page', { params }),
   update: data => request.patch(`/article/${data.id}`, data),
   delete: id => request.delete(`/article/${id}`),
+  getOne: id => request.get(`/article/detail/${id}`),
 
-  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),
+  // 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),
 }

+ 97 - 0
packages/frontend/src/views/article/edit.vue

@@ -0,0 +1,97 @@
+<template>
+  <CommonPage show-footer>
+    <template #action>
+      <NButton type="primary" @click="handleEdit">
+        保存文章
+      </NButton>
+    </template>
+
+    <div class="editor-wrap">
+      <n-form ref="modalFormRef" class="form wh-full" 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="categoryId" :rule="{
+          required: true,
+          type: 'number',
+          trigger: ['change', 'blur'],
+          message: '请输入文章分类',
+        }">
+          <n-select v-model:value="modalForm.categoryId" :options="allCategory" clearable filterable tag
+            style="max-width: 300px;" />
+        </n-form-item>
+
+        <VividEditor v-model="modalForm.content" :dark="isDark">
+          <SlashCommand />
+          <DragHandle />
+        </VividEditor>
+      </n-form>
+    </div>
+  </CommonPage>
+</template>
+
+<script setup>
+import { DragHandle, SlashCommand, VividEditor } from '@4dkankan/vivid'
+import { useUserStore } from '@/store/index.js'
+import { useDark } from '@vueuse/core'
+import { NButton, useThemeVars } from 'naive-ui'
+import { ref } from 'vue'
+import { useRoute, useRouter } from 'vue-router'
+import categoryApi from '../category/api'
+import articleApi from './api'
+import '@4dkankan/vivid/dist/style.css'
+
+const isDark = useDark()
+const vars = useThemeVars()
+const modalFormRef = ref('')
+const { userId } = useUserStore()
+const router = useRouter()
+const route = useRoute()
+const modalForm = ref({
+  title: '',
+  categoryId: null,
+  content: '',
+  userId,
+})
+
+onMounted(async () => {
+  console.log('edit', route.params.id)
+  const { data } = await articleApi.getOne(route.params.id)
+  if (data) {
+    modalForm.value = {
+      ...modalForm.value,
+      ...data,
+      userId,
+    }
+  }
+})
+const allCategory = ref([])
+categoryApi.getAll().then(({ data = [] }) => (allCategory.value = data.map(item => ({ label: item.title, value: item.id }))))
+
+function handleEdit() {
+  modalFormRef.value?.validate((errors) => {
+    if (!errors) {
+      articleApi.update(modalForm.value)
+      $message.success('保存成功!')
+      router.push('/article')
+    }
+    else {
+      $message.error('请填写对应项!')
+      console.log('errors', errors)
+    }
+  })
+}
+</script>
+
+<style>
+.editor-wrap {
+  width: 100%;
+  height: 100%;
+}
+</style>

+ 2 - 5
packages/frontend/src/views/article/index.vue

@@ -148,11 +148,8 @@ function htmlspecialchars(str) {
   return text.length > 150 ? `${text.substring(0, 150)}...` : text
 }
 
-function handleEdit() {
+function handleEdit(row) {
   console.log('222')
-  // router.push('')
+  router.push(`/article/edit/${row.id}`)
 }
-
-const permissionTree = ref([])
-api.getAllPermissionTree().then(({ data = [] }) => (permissionTree.value = data))
 </script>