Kaynağa Gözat

📦 通用列表与先贤列传

imengyu 1 gün önce
ebeveyn
işleme
97216b7210

+ 10 - 0
src/api/introduction/BulidingContent.ts

@@ -0,0 +1,10 @@
+import { CommonContentApi } from '../CommonContent';
+
+export class BulidingContentApi extends CommonContentApi {
+
+  constructor() {
+    super(undefined, 3, "闽南文化-建筑文化", 252);
+  }
+}
+
+export default new BulidingContentApi();

+ 10 - 0
src/api/introduction/CharacterContent.ts

@@ -0,0 +1,10 @@
+import { CommonContentApi } from '../CommonContent';
+
+export class CharacterContentApi extends CommonContentApi {
+
+  constructor() {
+    super(undefined, 7, "闽南文化-历史人物", 244);
+  }
+}
+
+export default new CharacterContentApi();

+ 10 - 0
src/api/introduction/CustomContent.ts

@@ -0,0 +1,10 @@
+import { CommonContentApi } from '../CommonContent';
+
+export class CustomContentApi extends CommonContentApi {
+
+  constructor() {
+    super(undefined, 4, "闽南文化-民间习俗");
+  }
+}
+
+export default new CustomContentApi();

+ 10 - 0
src/api/introduction/FeatureContent.ts

@@ -0,0 +1,10 @@
+import { CommonContentApi } from '../CommonContent';
+
+export class FeatureContentApi extends CommonContentApi {
+
+  constructor() {
+    super(undefined, 3, "闽南文化-艺术特色");
+  }
+}
+
+export default new FeatureContentApi();

+ 10 - 0
src/api/introduction/HistoryContent.ts

@@ -0,0 +1,10 @@
+import { CommonContentApi } from '../CommonContent';
+
+export class HistoryContentApi extends CommonContentApi {
+
+  constructor() {
+    super(undefined, 14, "闽南文化-历史和地理背景", 233);
+  }
+}
+
+export default new HistoryContentApi();

+ 10 - 0
src/api/introduction/IndexContent.ts

@@ -0,0 +1,10 @@
+import { CommonContentApi } from '../CommonContent';
+
+export class IndexContentApi extends CommonContentApi {
+
+  constructor() {
+    super(undefined, 3, "闽南文化概况", 288);
+  }
+}
+
+export default new IndexContentApi();

+ 10 - 0
src/api/introduction/LanguageContent.ts

@@ -0,0 +1,10 @@
+import { CommonContentApi } from '../CommonContent';
+
+export class LanguageContentApi extends CommonContentApi {
+
+  constructor() {
+    super(undefined, 5, "闽南文化-闽南方言", 235);
+  }
+}
+
+export default new LanguageContentApi();

+ 10 - 0
src/api/introduction/PolicyContent.ts

@@ -0,0 +1,10 @@
+import { CommonContentApi } from '../CommonContent';
+
+export class PolicyContentApi extends CommonContentApi {
+
+  constructor() {
+    super(undefined, 13, "政策法规");
+  }
+}
+
+export default new PolicyContentApi();

+ 10 - 0
src/api/introduction/SeaContent.ts

@@ -0,0 +1,10 @@
+import { CommonContentApi } from '../CommonContent';
+
+export class SeaContentApi extends CommonContentApi {
+
+  constructor() {
+    super(undefined, 3, "闽南文化-海洋文化", 252);
+  }
+}
+
+export default new SeaContentApi();

+ 10 - 0
src/api/introduction/VictualsContent.ts

@@ -0,0 +1,10 @@
+import { CommonContentApi } from '../CommonContent';
+
+export class VictualsContentApi extends CommonContentApi {
+
+  constructor() {
+    super(undefined, 3, "闽南文化-饮食文化", 253);
+  }
+}
+
+export default new VictualsContentApi();

+ 5 - 0
src/common/composeabe/LoadQuerys.ts

@@ -1,6 +1,11 @@
 import { onLoad } from "@dcloudio/uni-app";
 import { nextTick, ref, type Ref } from "vue";
 
+/**
+ * 用于在页面加载时获取并处理页面参数的组合式函数。
+ * @param defaults - 页面参数的默认值对象,其类型为泛型 T,T 需继承自 Record<string, any>。
+ * @param afterLoad - 可选的回调函数,在页面加载完成且参数处理完毕后执行,接收处理后的参数对象作为参数。
+ */
 export function useLoadQuerys<T extends Record<string, any>>(
   defaults: T, 
   afterLoad?: (querys: T) => void

+ 10 - 6
src/common/scss/define/colors.scss

@@ -1,12 +1,19 @@
 $colors: (
   primary: #d9492e,
+ 
+  text: #333232,
+  text-content: #3d2c08,
+  text-content-second: #817b67, 
   primary-text: #D9492E,
   primary-second-text: rgba(217, 73, 46, 0.6),
   title-text: #432A04,
   second-text: #e6927e,
+  
   light-blue: #0059ff,
   light-primary: #d9492e35,
   light-light-primary: #d9492e15,
+
+
   success: #09ad32,
   warning: #FFD666,
   error: #ec4545,
@@ -24,20 +31,17 @@ $colors: (
   base: #f6f2e7,
   custom: #4A5061,
   link: #0273F1,
-  light-light: #f5f1f1,
-  light: #F3F4F5,
+  light: #fbfaf5,
   dark: #F1F1F1,
-  dark-dark: #dfdfdf,
   muted: #858585,
-  text: #333232,
   second: #666464,
   third: #999696,
   forth: #CCC8C8,
-  place: #CCC8C8,
+  place: #ece7da,
   mask-white: rgba(255, 255, 255, 0.6),
   mask-black: rgba(0, 0, 0, 0.6),
-  page: #FAFAFA,
   disabled: #CCC8C8,
+ 
   none: transparent,
   transparent: transparent,
 );

+ 4 - 1
src/common/utils/ConvertRgeistry.ts

@@ -39,11 +39,14 @@ export function registryConvert() {
     key: 'SplitCommaArray',
     targetType: 'splitCommaArray',
     converter: (source, key, type) => {
-      if (typeof source === 'string') 
+      if (typeof source === 'string') {
+        if (source === '') 
+          return { success: true, result: [] }
         return {
           success: true,
           result: source?.split(',') || [],
         }
+      }
       return {
         success: false,
         convertFailMessage: `[${key}] 不是字符串类型`,

+ 27 - 2
src/pages.json

@@ -19,6 +19,12 @@
       }
     },
     {
+      "path": "pages/introduction/character",
+      "style": {
+        "navigationBarTitleText": "先贤列传"
+      }
+    },
+    {
       "path": "pages/travel",
       "style": {
         "navigationBarTitleText": "闽南文化生态保护-文旅",
@@ -53,6 +59,25 @@
       }
     },
     {
+      "path": "pages/inhert/inheritor/list",
+      "style": {
+        "navigationBarTitleText": "人物列表"
+      }
+    },
+    {
+      "path": "pages/inhert/inheritor/details",
+      "style": {
+        "navigationBarTitleText": "人物详情"
+      }
+    },
+    {
+      "path": "pages/article/common/list",
+      "style": {
+        "navigationBarTitleText": "通用列表页",
+        "navigationStyle": "custom"
+      }
+    },
+    {
       "path": "pages/article/details",
       "style": {
         "navigationBarTitleText": "新闻详情",
@@ -109,9 +134,9 @@
     }
   ],
   "globalStyle": {
-    "navigationBarTextStyle": "white",
+    "navigationBarTextStyle": "black",
     "navigationBarTitleText": "uni-app",
-    "navigationBarBackgroundColor": "#d9492e",
+    "navigationBarBackgroundColor": "#f6f2e7",
     "backgroundColor": "#f6f2e7"
   },
   "uniIdRouter": {},

+ 189 - 0
src/pages/article/common/CommonListPage.vue

@@ -0,0 +1,189 @@
+<template>
+  <!-- 通用列表页 -->
+  <view class="d-flex flex-column bg-base">
+    <!-- 搜索 -->
+    <view v-if="showSearch" class="d-flex flex-col p-2">
+      <uni-search-bar 
+        
+        v-model="searchValue"
+        radius="100" 
+        bgColor="#fff" 
+        :placeholder="`输入关键词搜索${title}`" 
+        clearButton="auto" 
+        cancelButton="none"
+        @confirm="doSearch"
+      />
+    </view>
+    <!-- 下拉框 -->
+    <view 
+      v-if="dropDownNames && dropDownNames.length > 0" 
+      class="d-flex flex-row justify-around p-2 pt-0"
+    >
+      <SimpleDropDownPicker 
+        v-for="(drop, k) in dropDownNames" :key="k" 
+        :modelValue="dropDownValues[k] || drop.defaultSelectedValue"
+        :columns="drop.options" 
+        @update:modelValue="(v) => handleChangeDropDownValue(k, v)"
+      />
+    </view>
+    <!-- 列表 -->
+    <view class="d-flex flex-row flex-wrap justify-between p-3 pt-0">
+      <view
+        v-for="item in listLoader.list.value"
+        :key="item.id"
+        :class="[
+          itemType.endsWith('-2') ? 'width-1-2' : 'w-100'
+        ]"
+      >
+        <Box2LineLargeImageUserShadow 
+          v-if="itemType.startsWith('image-large')"
+          classNames="ml-2 mb-3"
+          titleColor="title-text"
+          :image="item.image"
+          :title="item.title"
+          :desc="item.desc"
+          @click="goDetails(item.id)"
+        />
+        <Box2LineImageRightShadow 
+          v-else-if="itemType.startsWith('article-common')"
+          classNames="ml-2 mb-3"
+          titleColor="title-text"
+          :image="item.image"
+          :title="item.title"
+          :desc="item.desc"
+          :wideImage="true"
+          @click="goDetails(item.id)"
+        />
+        <Box2LineImageRightShadow 
+          v-else-if="itemType.startsWith('article-character')"
+          classNames="ml-2 mb-3"
+          titleColor="title-text"
+          :image="item.image"
+          :title="item.title"
+          :tags="item.keywords"
+          :desc="item.desc"
+          @click="goDetails(item.id)"
+        />
+
+      </view>
+    </view>
+    <SimplePageListLoader :loader="listLoader" />
+  </view>
+</template>
+
+<script setup lang="ts">
+import { onMounted, ref, type PropType } from 'vue';
+import { useSimplePageListLoader } from '@/common/composeabe/SimplePageListLoader';
+import { navTo } from '@/common/utils/PageAction';
+import SimplePageListLoader from '@/common/components/SimplePageListLoader.vue';
+import Box2LineLargeImageUserShadow from '@/pages/parts/Box2LineLargeImageUserShadow.vue';
+import Box2LineImageRightShadow from '@/pages/parts/Box2LineImageRightShadow.vue';
+import SimpleDropDownPicker, { type SimpleDropDownPickerItem } from '@/common/components/SimpleDropDownPicker.vue';
+
+export interface DropDownNames {
+  options: SimpleDropDownPickerItem[],
+  defaultSelectedValue: number|string,
+}
+export interface CommonListItem extends Record<string, any>  {
+  id: number,
+  image: string,
+  title: string,
+}
+
+const props = defineProps({
+  /** 
+   * 标题
+   */
+  title: {
+    type: String,
+    default: '通用列表页',
+  },
+  /**
+   * 是否显示搜索框
+   */
+  showSearch: {
+    type: Boolean,
+    default: true,
+  },
+  /**
+   * 下拉框选项控制
+   */
+  dropDownNames: {
+    type: Object as PropType<DropDownNames[]>,
+    default: null,
+  },
+  /**
+   * 列表项类型
+   */
+  itemType: {
+    type: String as PropType<'image-large-2'|'image-large'|'article-common'|'article-character'>,
+    default: 'article-common',
+  },
+  /**
+   * 分页大小
+   */
+  pageSize: {
+    type: Number,
+    default: 8,
+  },
+  /**
+   * 加载数据函数
+   * @param page 页码,从1开始
+   * @param pageSize 分页大小
+   * @param searchText 搜索文本
+   * @param dropDownValues 下拉框值
+   */
+  load: {
+    type: Function as PropType<(
+      page: number, 
+      pageSize: number,
+      searchText: string,
+      dropDownValues: number[],
+    ) => Promise<CommonListItem[]>>,
+    required: true,
+  },
+  /**
+   * 点击详情跳转页面路径
+   */
+  detailsPage: {
+    type: String,
+    default: '/pages/article/details'
+  },
+  /**
+   * 详情跳转页面参数
+   */
+  detailsParams: {
+    type: Object as PropType<Record<string, any>>,
+    default: () => ({})
+  }
+})
+
+const dropDownValues = ref<any>([]);
+const searchValue = ref('');
+const listLoader = useSimplePageListLoader(props.pageSize, async (page, pageSize) => await props.load(
+  page, pageSize, 
+  searchValue.value,
+  dropDownValues.value,
+));
+
+function handleChangeDropDownValue(index: number, value: number) {
+  dropDownValues.value[index] = value;
+  listLoader.loadData(undefined, true);
+}
+function doSearch() {
+  listLoader.loadData(undefined, true);
+}
+function goDetails(id: number) {
+  navTo(props.detailsPage, { 
+    ...props.detailsParams,
+    id
+  })
+}
+
+onMounted(() => {
+  uni.setNavigationBarTitle({
+    title: props.title,
+  })
+  listLoader.loadData(undefined, true);
+});
+</script>

+ 36 - 0
src/pages/article/common/list.vue

@@ -0,0 +1,36 @@
+<template>
+  <CommonListPage 
+    :load="loadData"
+    :itemType="querys.itemType as any || undefined"
+    :detailsPage="querys.detailsPage || undefined"
+  />
+</template>
+
+<script setup lang="ts">
+import { useLoadQuerys } from '@/common/composeabe/LoadQuerys';
+import CommonListPage from './CommonListPage.vue';
+import CommonContent, { GetContentListParams } from '@/api/CommonContent';
+
+const { querys } = useLoadQuerys({
+  mainBodyColumnId: 0,
+  modelId: 0,
+  itemType: '',
+  detailsPage: '',
+});
+
+async function loadData(
+  page: number, 
+  pageSize: number,
+  searchText: string,
+  dropDownValues: number[]
+) {
+
+  const res = await CommonContent.getContentList(new GetContentListParams().setSelfValues({
+    mainBodyColumnId: querys.value.mainBodyColumnId || undefined,
+    modelId: querys.value.modelId || undefined,
+    keywords: searchText,
+  }), page, pageSize);
+
+  return res.list;
+}
+</script>

+ 3 - 7
src/pages/article/details.vue

@@ -32,10 +32,10 @@
 <script setup lang="ts">
 import type { GetContentDetailItem } from "@/api/CommonContent";
 import { useSimplePageContentLoader } from "@/common/composeabe/SimplePageContentLoader";
-import { onLoad } from "@dcloudio/uni-app";
+import { DataDateUtils } from "@imengyu/js-request-transform";
+import { useLoadQuerys } from "@/common/composeabe/LoadQuerys";
 import NewsIndexContent from "@/api/news/NewsIndexContent";
 import commonParserStyle from "@/common/style/commonParserStyle";
-import { DataDateUtils } from "@imengyu/js-request-transform";
 
 const loader = useSimplePageContentLoader<
   GetContentDetailItem, 
@@ -48,11 +48,7 @@ const loader = useSimplePageContentLoader<
   return res;
 });
 
-onLoad((options) => {
-  loader.loadData({
-    id: Number(options?.id),
-  })
-});
+useLoadQuerys({ id : 0, }, (p) => loader.loadData(p));
 </script>
 
 <style lang="scss" scoped>

+ 2 - 1
src/pages/home.vue

@@ -25,6 +25,7 @@
             v-for="(tab, k) in subTabs1" 
             :key="k"
             class="d-flex flex-column align-center width-1-5 mt-2"
+            @click="tab.onClick"
           >
             <image class="width-100" :src="tab.icon" mode="widthFix" />
             <text class="color-second-text mt-2">{{ tab.name }}</text>
@@ -142,7 +143,7 @@ import { navTo } from '@/common/utils/PageAction';
 const subTabs1 = [
   { name: '闽南语', icon: MainBoxIcon1 },
   { name: '古早味', icon: MainBoxIcon2 },
-  { name: '先贤列传', icon: MainBoxIcon3 },
+  { name: '先贤列传', icon: MainBoxIcon3, onClick: () => navTo('/pages/introduction/character') },
   { name: '民俗活动', icon: MainBoxIcon4 },
 ]
 const subTabs2 = [

+ 2 - 5
src/pages/inhert/artifact/details.vue

@@ -103,6 +103,7 @@ import SimplePageContentLoader from "@/common/components/SimplePageContentLoader
 import ImageWrapper from "@/common/components/ImageWrapper.vue";
 import HomeTitle from "@/pages/parts/HomeTitle.vue";
 import commonParserStyle from "@/common/style/commonParserStyle";
+import { useLoadQuerys } from "@/common/composeabe/LoadQuerys";
 
 const loader = useSimplePageContentLoader<
   GetContentDetailItem, 
@@ -113,11 +114,7 @@ const loader = useSimplePageContentLoader<
   return await UnmoveableContent.getContentDetail(params.id);
 });
 
-onLoad((options) => {
-  loader.loadData({
-    id: Number(options?.id),
-  })
-});
+useLoadQuerys({ id : 0, }, (p) => loader.loadData(p));
 
 function goDetails(item: any) {
   navTo('inherit_artifact_details', { id: item.id })

+ 60 - 0
src/pages/inhert/inheritor/details.vue

@@ -0,0 +1,60 @@
+<template>
+  <view class="d-flex flex-col bg-base">
+    <SimplePageContentLoader :loader="loader">
+      <template v-if="loader.content.value">
+        <view class="d-flex flex-col p-3">
+          <view class="d-flex flex-row justify-between">
+            <view class="d-flex flex-col">
+              <text class="size-lll font-bold color-text-content">{{ loader.content.value.title }}</text>
+              <text class="size-base color-text-content-second mt-2">{{ loader.content.value.birthplace || loader.content.value.desc }}</text>
+              <RoundTags
+                :tags="loader.content.value.tags"
+                :tags2="[
+                  loader.content.value.age as string,
+                  loader.content.value.nation as string
+                ]"
+              />
+            </view>
+            <image 
+              class="width-150 height-150 radius-base flex-shrink-0" 
+              :src="loader.content.value.image" mode="aspectFill"
+            />
+          </view>
+          <view class="d-flex flex-col radius-l bg-light p-25 mt-3">
+            <u-parse :content="loader.content.value.intro" :tagStyle="commonParserStyle"></u-parse>
+            <u-parse :content="loader.content.value.content" :tagStyle="commonParserStyle"></u-parse>
+            <u-parse :content="loader.content.value.value" :tagStyle="commonParserStyle"></u-parse>
+          </view>
+        </view>
+      </template>
+    </SimplePageContentLoader>
+  </view>
+</template>
+<script setup lang="ts">
+import type { GetContentDetailItem } from "@/api/CommonContent";
+import { useSimplePageContentLoader } from "@/common/composeabe/SimplePageContentLoader";
+import { onLoad } from "@dcloudio/uni-app";
+import { navTo } from "@/common/utils/PageAction";
+import UnmoveableContent from "@/api/inheritor/UnmoveableContent";
+import SimplePageContentLoader from "@/common/components/SimplePageContentLoader.vue";
+import ImageWrapper from "@/common/components/ImageWrapper.vue";
+import RoundTags from "@/pages/parts/RoundTags.vue";
+import commonParserStyle from "@/common/style/commonParserStyle";
+import { useLoadQuerys } from "@/common/composeabe/LoadQuerys";
+
+const loader = useSimplePageContentLoader<
+  GetContentDetailItem, 
+  { id: number }
+>(async (params) => {
+  if (!params)
+    throw new Error("!params");
+  return await UnmoveableContent.getContentDetail(params.id);
+});
+
+useLoadQuerys({ id : 0 }, (p) => loader.loadData(p));
+
+</script>
+
+<style lang="scss">
+
+</style>

+ 64 - 0
src/pages/inhert/inheritor/list.vue

@@ -0,0 +1,64 @@
+<template>
+  <CommonListPage 
+    title="先贤列传"
+    itemType="article-character"
+    detailsPage="/pages/inhert/inheritor/details"
+    :dropdownNames="dropdownNames"
+    :load="loadData" 
+  />
+</template>
+
+<script setup lang="ts">
+import CommonContent, { GetContentListParams } from '@/api/CommonContent';
+import InheritorContent from '@/api/inheritor/InheritorContent';
+import CommonListPage, { type DropDownNames } from '@/pages/article/common/CommonListPage.vue';
+import { onMounted, ref } from 'vue';
+
+const dropdownNames = ref<DropDownNames[]>([]);
+
+async function loadData(
+  page: number, 
+  pageSize: number,
+  searchText: string,
+  dropDownValues: number[]
+) {
+  return (await InheritorContent.getContentList(new GetContentListParams().setSelfValues({
+    ichType: dropDownValues[0] == 0 ? undefined: dropDownValues[0],
+    level: dropDownValues[1] == 0 ? undefined: dropDownValues[1],
+    region: dropDownValues[2] == 0 ? undefined: dropDownValues[2],
+  }), page, pageSize)).list;
+}
+
+onMounted(async () => {
+  dropdownNames.value.push({ 
+    options: [{
+      id: 0, 
+      name: '全部'
+    }].concat((await CommonContent.getCategoryList(4)).map((item) => ({
+      id: item.id,
+      name: item.title,
+    }))),
+    defaultSelectedValue: 0,
+  });
+  dropdownNames.value.push({ 
+    options: [{
+      id: 0, 
+      name: '全部'
+    }].concat((await CommonContent.getCategoryList(2)).map((item) => ({
+      id: item.id,
+      name: item.title,
+    }))),
+    defaultSelectedValue: 0,
+  });
+  dropdownNames.value.push({ 
+    options: [{
+      id: 0, 
+      name: '全部'
+    }].concat((await CommonContent.getCategoryList(1)).map((item) => ({
+      id: item.id,
+      name: item.title,
+    }))),
+    defaultSelectedValue: 0,
+  });
+})
+</script>

+ 33 - 0
src/pages/introduction/character.vue

@@ -0,0 +1,33 @@
+<template>
+  <!-- 文化概况 - 先贤列传 -->
+   <CommonListPage
+    :title="'先贤列传'"
+    :dropDownNames="[]"
+    itemType="article-character"
+    detailsPage="/pages/inhert/inheritor/details"
+    :load="loadData"
+  />
+</template>
+
+<script setup lang="ts">
+import { GetContentListParams } from '@/api/CommonContent';
+import CharacterContentApi from '@/api/introduction/CharacterContent';
+import CommonListPage, { type DropDownNames } from '@/pages/article/common/CommonListPage.vue';
+
+async function loadData(
+  page: number, 
+  pageSize: number,
+  searchText: string,
+  dropDownValues: number[]
+) {
+  return (await CharacterContentApi
+    .getContentList(new GetContentListParams().setSelfValues({
+      keywords: searchText,
+    }), page, pageSize)
+  ).list;
+}
+</script>
+
+<style>
+</style>
+

+ 27 - 6
src/pages/parts/Box2LineImageRightShadow.vue

@@ -1,13 +1,23 @@
 <template>
   <view 
-    class="d-flex flex-row justify-between shadow-s radius-base mt-3 p-2 pt-3 pb-3"
+    class="d-flex flex-row justify-between shadow-s radius-base mb-3 p-2 pt-3 pb-3"
     @click="$emit('click')"
   >
-    <view class="d-flex flex-row">
-      <image class="width-100 height-100 radius-base" :src="image" mode="aspectFill" />
-      <view class="d-flex flex-col ml-3 flex-one">
-        <text class="color-primary">{{ title }}</text>
-        <text class="color-second mt-2">{{ desc }}</text>
+    <view class="d-flex flex-row w-100">
+      <image 
+        :class="[
+          wideImage ? 'width-250' : 'width-150', 
+          'height-150', 
+          'radius-base',
+          'flex-shrink-0'
+        ]"
+        :src="image"
+        mode="aspectFill"
+      />
+      <view class="d-flex flex-col ml-3 flex-one width-500">
+        <text class="color-primary text-lines-1">{{ title }}</text>
+        <text class="color-second text-lines-1 mt-2">{{ desc }}</text>
+        <RoundTags v-if="tags" :tags="tags" />
       </view>
     </view>
     <text class="color-primary-second-text size-ss">{{ right }}</text>
@@ -15,10 +25,21 @@
 </template>
 
 <script setup lang="ts">
+import type { PropType } from 'vue';
+import RoundTags from './RoundTags.vue';
+
 defineProps({
   title: String,
   desc: String,
   right: String,
   image: String,
+  tags: {
+    type: Array as PropType<string[]>,
+    default: null
+  },
+  wideImage: {
+    type: Boolean,
+    default: false,
+  }
 })
 </script>

+ 36 - 0
src/pages/parts/RoundTags.vue

@@ -0,0 +1,36 @@
+<template>
+  <view class="d-flex flex-row flex-wrap mt-2">
+    <view 
+      v-for="(tag, k) in tags"
+      :key="k" 
+      class="bg-place radius-ll p-25 pt-1 mr-2"
+    >
+      <text class="color-text-content-second size-ss">{{ tag }}</text>
+    </view>
+  </view>
+</template>
+
+<script setup lang="ts">
+import { computed, type PropType } from 'vue';
+
+const props = defineProps({
+  tags: {
+    type: Array as PropType<string[]>,
+    default: null,
+  },
+  tags2: {
+    type: Array as PropType<string[]>,
+    default: null,
+  },
+})
+
+const tagss = computed(() => {
+  if (props.tags && props.tags.length > 0) {
+    return props.tags;
+  } else if (props.tags2) {
+    return props.tags2;
+  } else {
+    return [];
+  }
+})
+</script>

+ 2 - 2
src/pages/user/index.vue

@@ -48,7 +48,7 @@
             <image src="https://mn.wenlvti.net/uploads/20250313/042236758da5aaed21c1010e5b9440ce.png" mode="aspectFill"></image>
             <text class="label">我的收藏</text>
             <text class="iconfont icon-arrow-right"></text>
-          </view>
+          </view> -->
           <view class="entry">
             <image src="https://mn.wenlvti.net/uploads/20250313/07f750b4cf4959654c40171fdae91c3a.png" mode="aspectFill"></image>
             <text class="label">投稿</text>
@@ -64,7 +64,7 @@
             <text class="label">加入我们</text>
             <text class="iconfont icon-arrow-right"></text>
           </view>
-          <view class="entry">
+          <!-- <view class="entry">
             <image src="https://mn.wenlvti.net/uploads/20250313/d2e9010323d098aa51e268fc32f14d3d.png" mode="aspectFill"></image>
             <text class="label">我的预约</text>
             <text class="iconfont icon-arrow-right"></text>