Quellcode durchsuchen

feat: 文章详情完成

IlhamTahir vor 11 Monaten
Ursprung
Commit
1dfddbf1da

+ 1 - 1
pet-manual/index.vue

@@ -1,6 +1,6 @@
 <script setup lang="ts">
 import carousalApi from '@/api/carousal'
-import CardList from '@/pages/pet-manual/components/CardList.vue'
+import CardList from '../src/components/CardList.vue'
 // const searchValue = ref('')
 import bg from '@/static/image/feed-plan/bg.png'
 import circle from '@/static/image/feed-plan/circle.png'

+ 6 - 0
src/api/article.ts

@@ -0,0 +1,6 @@
+import type { Article } from '@/model/pet-manual'
+import httpClient from '@/api/httpClient'
+
+export async function getArticle(id: string) {
+  return httpClient.get<Article>(`/articles/${id}`)
+}

+ 4 - 0
src/api/feeding-plan.ts

@@ -8,3 +8,7 @@ export async function createFeedingPlan(createFeedingPlanRequest: CreateFeedingP
 export async function getFeedingPlan(id: string) {
   return httpClient.get<FeedingPlan>(`/feeding-plans/${id}`)
 }
+
+export async function updateFeedingPlan(id: string, createFeedingPlanRequest: CreateFeedingPlanRequest) {
+  return httpClient.put<FeedingPlan>(`/feeding-plans/${id}`, createFeedingPlanRequest)
+}

+ 1 - 0
src/components.d.ts

@@ -10,6 +10,7 @@ declare module 'vue' {
     AddFeedingPlan: typeof import('./components/AddFeedingPlan.vue')['default']
     BButton: typeof import('./components/BButton.vue')['default']
     BSlider: typeof import('./components/BSlider.vue')['default']
+    CardList: typeof import('./components/CardList.vue')['default']
     Cell: typeof import('./components/Cell.vue')['default']
     CellGroup: typeof import('./components/CellGroup.vue')['default']
     FeedForm: typeof import('./components/FeedForm.vue')['default']

+ 7 - 0
src/pages/pet-manual/components/CardList.vue → src/components/CardList.vue

@@ -34,12 +34,19 @@ function handleLoadMore() {
   }
   emit('loadMore')
 }
+
+function goToArticle(id: string) {
+  uni.navigateTo({
+    url: `/pages/article/detail?id=${id}`,
+  })
+}
 </script>
 
 <template>
   <view class="flex flex-col gap-4 px-4">
     <view
       v-for="(item, index) in props.cardList" :key="index" class="bg-[white] rounded-md shadow-lg flex w-full h-[120px] overflow-hidden"
+      @tap="() => goToArticle(item.id)"
     >
       <image class="w-[120px] h-[120px] rounded-l-md shrink-0" :src="item?.imageUrl || titleBg" />
       <view class="p-4 flex flex-col">

+ 3 - 4
src/model/pet-manual.ts

@@ -1,4 +1,4 @@
-import type { Paging } from '@/model/base'
+import type { BaseModel, Paging } from '@/model/base'
 import type { CreatePetRequest } from '@/model/pet'
 
 export interface CreateCarousalsRequest {
@@ -20,14 +20,13 @@ export interface ArticleParams extends Paging {
   categoryId: string
 }
 
-export interface Article {
-  id: string
+export interface Article extends BaseModel {
   content: string
   status: string
   title: string
   description: string
-  updatedTime?: string
   imageUrl?: string
+  category: Category
 }
 
 export interface Recommends {

+ 5 - 5
src/pages.json

@@ -7,6 +7,11 @@
   },
   "entryPagePath": "pages/home/index",
   "pages": [
+    {
+      "path": "pages/article/detail",
+      "type": "page",
+      "style": {}
+    },
     {
       "path": "pages/feed-plan/index",
       "type": "page",
@@ -86,11 +91,6 @@
       "path": "pages/userInfo/index",
       "type": "page",
       "style": {}
-    },
-    {
-      "path": "pages/pet-manual/components/CardList",
-      "type": "page",
-      "style": {}
     }
   ],
   "globalStyle": {

+ 46 - 0
src/pages/article/detail.vue

@@ -0,0 +1,46 @@
+<script setup lang="ts">
+import type { Article } from '@/model/pet-manual'
+import { getArticle } from '@/api/article'
+
+const article = ref<Article | null>()
+
+const id = ref('')
+
+onLoad((options) => {
+  id.value = options!.id as string
+})
+
+onMounted(() => {
+  fetchData()
+})
+
+async function fetchData() {
+  article.value = await getArticle(id.value)
+  await uni.setNavigationBarTitle({
+    title: article.value.category.name,
+  })
+}
+
+const fixedContent = computed(() => {
+  if (!article.value) {
+    return ''
+  }
+  return article.value.content.replace(/<img/g, '<img class="w-full"')
+})
+</script>
+
+<template>
+  <view v-if="article" class="w-full h-screen p-4 bg-[#F5F6F7]">
+    <view class="mb-2 text-xl font-semibold">
+      {{ article.title }}
+    </view>
+    <view class="flex text-xs text-[#999] mb-6">
+      <view>{{ article.createdTime }}</view>
+    </view>
+    <rich-text :nodes="fixedContent" />
+  </view>
+</template>
+
+<style scoped>
+
+</style>

+ 1 - 1
src/pages/pet-manual/index.vue

@@ -2,7 +2,7 @@
 import type { Paging } from '@/model/base'
 import type { Article, ArticleParams, Category, CreateCarousalsRequest, Recommends } from '@/model/pet-manual'
 import carousalApi from '@/api/carousal'
-import CardList from '@/pages/pet-manual/components/CardList.vue'
+import CardList from '@/components/CardList.vue'
 import circle from '@/static/image/feed-plan/circle.png'
 import message from '@/static/image/feed-plan/message.png'
 import ToolApi from '@/utils'

+ 11 - 3
src/stores/feeding-plan.ts

@@ -1,6 +1,6 @@
 import type { FeedingPlanProduct } from '@/model/feeding-plan'
 import type { Product } from '@/model/product'
-import { createFeedingPlan } from '@/api/feeding-plan'
+import { createFeedingPlan, updateFeedingPlan } from '@/api/feeding-plan'
 import { createPet } from '@/api/pet'
 import {
   type CreateFeedingPlanRequest,
@@ -221,6 +221,8 @@ export const useFeedingPlanStore = defineStore('feeding-plan', () => {
     })
   }
 
+  const isEdit = ref(false)
+
   /**
    * 修改指定 productId 的 percentage
    * @param productId 产品的id
@@ -246,6 +248,7 @@ export const useFeedingPlanStore = defineStore('feeding-plan', () => {
       arrangeDailyConsumeWeight()
     }
   }
+  const savedFeedingPlan = ref<FeedingPlan | null>(null)
 
   const confirm = async () => {
     if (savedPet.value === null) {
@@ -260,7 +263,13 @@ export const useFeedingPlanStore = defineStore('feeding-plan', () => {
         percentage: item.percentage,
       }
     })
-    await createFeedingPlan(feedingPlan.value)
+
+    if ((isEdit.value && savedFeedingPlan.value)) {
+      await updateFeedingPlan(savedFeedingPlan.value.id, feedingPlan.value)
+    }
+    else {
+      await createFeedingPlan(feedingPlan.value)
+    }
   }
 
   const initPet = (payload: Pet) => {
@@ -282,7 +291,6 @@ export const useFeedingPlanStore = defineStore('feeding-plan', () => {
     feedingPlan.value.targetWeight = calculateIdealWeight()
     rer.value = calculateRER(pet.value.weight)
   }
-  const savedFeedingPlan = ref<FeedingPlan | null>(null)
 
   const initFeedingPlan = (payload: FeedingPlan) => {
     // @ts-expect-error @ts-ignore

+ 3 - 3
src/uni-pages.d.ts

@@ -4,7 +4,8 @@
 // Generated by vite-plugin-uni-pages
 
 interface NavigateToOptions {
-  url: "/pages/feed-plan/index" |
+  url: "/pages/article/detail" |
+       "/pages/feed-plan/index" |
        "/pages/feed-plan-calculator/choose-product" |
        "/pages/feed-plan-calculator/confirm" |
        "/pages/feed-plan-calculator/index" |
@@ -14,8 +15,7 @@ interface NavigateToOptions {
        "/pages/pet-manual/index" |
        "/pages/setting/index" |
        "/pages/start-filing/index" |
-       "/pages/userInfo/index" |
-       "/pages/pet-manual/components/CardList";
+       "/pages/userInfo/index";
 }
 interface RedirectToOptions extends NavigateToOptions {}