Selaa lähdekoodia

知识库和我的页面

快乐的梦鱼 2 kuukautta sitten
vanhempi
commit
1d852268da

+ 1 - 1
src/App.vue

@@ -35,7 +35,7 @@ onLaunch(async () => {
 configTheme((theme) => {
   theme.colorConfigs.default.primary = '#00ca76';
   theme.colorConfigs.pressed.primary = '#00814b';
-  theme.colorConfigs.background.primary = '#b4ffe0';
+  theme.colorConfigs.background.primary = '#dcfff0';
   return theme;
 });
 </script>

+ 5 - 5
src/components/basic/Cell.vue

@@ -34,7 +34,7 @@
               />
             </slot>
           </FlexRow>
-          <FlexCol :style="leftViewStyle">
+          <FlexCol :innerStyle="leftViewStyle">
             <slot name="title">
               <Text v-if="title" :innerStyle="{ ...titleStyle, ...textStyle} ">{{ title }}</Text>
             </slot>
@@ -250,10 +250,10 @@ const themeColorVars = computed(() => theme.resolveThemeColors({
   CellBorderColor: 'border.cell',
 }));
 
-const leftViewStyle = {
-  marginLeft: 10,
-  marginRight: 10,
-};
+const leftViewStyle = computed(() => ({
+  marginLeft: theme.resolveThemeSize('CellLeftPaddingHorizontal', 15),
+  marginRight: theme.resolveThemeSize('CellLeftPaddingHorizontal', 15),
+}));
 const titleStyle = computed(() => ({
   overflow: 'hidden',
   textOverflow: 'ellipsis',

+ 52 - 18
src/components/display/Tag.vue

@@ -52,10 +52,10 @@ export interface TagProps {
    */
   type?: TagTypes,
   /**
-   * 设置 plain 属性设置为空心样式。
-   * @default false
+   * 设置 plain 属性设置为空心样式。设置 light 属性设置为浅色样式。
+   * @default 'default'
    */
-  plain?: boolean,
+  scheme?: 'plain'|'light'|'default',
   /**
    * 形状 通过 square 设置方形,通过 round 设置圆形, mark设置标记样式(半圆角)。
    * @default 'round'
@@ -107,7 +107,7 @@ const themeContext = useTheme();
 const props = withDefaults(defineProps<TagProps>(), {
   shape: () => propGetThemeVar('TagShape', 'round'),
   type: () => propGetThemeVar('TagType', 'default'),
-  plain: () => propGetThemeVar('TagPlain', false),
+  scheme: () => propGetThemeVar('TagScheme', 'default'),
   size: () => propGetThemeVar('TagSize', 'medium'),
   borderRadius: () => propGetThemeVar('TagBorderRadius', 20),
   textColor: () => propGetThemeVar('TagTextColor'),
@@ -155,6 +155,26 @@ const themeStyles = themeContext.useThemeStyles({
     borderColor: DynamicColor('TagPlainDangerBorderColor', 'danger'),
     color: DynamicColor('TagPlainDangerColor', 'danger'),
   },
+  lightTagDefault: {
+    backgroundColor: DynamicColor('TagLightDefaultBackgroundColor', 'background.button'),
+    color: DynamicColor('TagLightDefaultColor', 'text.content'),
+  },
+  lightTagPrimary: {
+    backgroundColor: DynamicColor('TagLightPrimaryBackgroundColor', 'background.primary'),
+    color: DynamicColor('TagLightPrimaryColor', 'primary'),
+  },
+  lightTagSuccess: {    
+    color: DynamicColor('TagLightSuccessColor', 'success'),
+    backgroundColor: DynamicColor('TagLightSuccessBackgroundColor', 'background.success'),
+  },
+  lightTagWarning: {
+    backgroundColor: DynamicColor('TagLightWarningBackgroundColor', 'background.warning'),
+    color: DynamicColor('TagLightWarningColor', 'warning'),
+  },
+  lightTagDanger: {
+    backgroundColor: DynamicColor('TagLightDangerBackgroundColor', 'background.danger'),
+    color: DynamicColor('TagLightDangerColor', 'danger'),
+  },
   tagDefault: {
     backgroundColor: DynamicColor('TagDefaultBackgroundColor', 'button'),
     color: DynamicColor('TagDefaultColor', 'black'),
@@ -204,19 +224,31 @@ const style = computed(() => {
         borderBottomRightRadius: borderRadius,
       },
     }),
-    ...selectStyleType<ViewStyle, TagTypes>(props.type, 'default', props.plain ? {
-      default: themeStyles.plainTagDefault.value,
-      primary: themeStyles.plainTagPrimary.value,
-      success: themeStyles.plainTagSuccess.value,
-      warning: themeStyles.plainTagWarning.value,
-      danger: themeStyles.plainTagDanger.value,
-    } : {
-      default: themeStyles.tagDefault.value,
-      primary: themeStyles.tagPrimary.value,
-      success: themeStyles.tagSuccess.value,
-      warning: themeStyles.tagWarning.value,
-      danger: themeStyles.tagDanger.value,
-    }),
+    ...selectStyleType<ViewStyle, TagTypes>(props.type, 'default', 
+      selectStyleType(props.scheme, 'default', {
+        default: {
+          default: themeStyles.tagDefault.value,
+          primary: themeStyles.tagPrimary.value,
+          success: themeStyles.tagSuccess.value,
+          warning: themeStyles.tagWarning.value,
+          danger: themeStyles.tagDanger.value,
+        },
+        plain: {
+          default: themeStyles.plainTagDefault.value,
+          primary: themeStyles.plainTagPrimary.value,
+          success: themeStyles.plainTagSuccess.value,
+          warning: themeStyles.plainTagWarning.value,
+          danger: themeStyles.plainTagDanger.value,
+        },
+        light: {
+          default: themeStyles.lightTagDefault.value,
+          primary: themeStyles.lightTagPrimary.value,
+          success: themeStyles.lightTagSuccess.value,
+          warning: themeStyles.lightTagWarning.value,
+          danger: themeStyles.lightTagDanger.value,
+        },
+      }),
+    ),
     ...selectStyleType<ViewStyle, TagSizes>(props.size, 'medium', {
       mini: themeStyles.tagSizeMini.value,
       small: themeStyles.tagSizeSmall.value,
@@ -227,9 +259,11 @@ const style = computed(() => {
     
   } as ViewStyle;
   if (color !== undefined) {
-    if (props.plain) {
+    if (props.scheme === 'plain') {
       style.borderColor = color;
       style.color = color;
+    } else if (props.scheme === 'light') {
+      style.color = color;
     } else {
       style.backgroundColor = color;
     }

+ 2 - 2
src/components/nav/NavBar.vue

@@ -82,7 +82,7 @@ export type NavBarButtonTypes = 'back'|'menu'|'search'|'setting'|'custom';
 export interface NavBarProps {
   /**
    * 标题栏高度
-   * @default 80
+   * @default '44px'
    */
   height?: number|string;
   /**
@@ -165,7 +165,7 @@ const theme = useTheme();
 const props = withDefaults(defineProps<NavBarProps>(), {
   titleScroll: true,
   align: () => propGetThemeVar('NavBarAlign', 'center'),
-  height: () => propGetThemeVar('NavBarHeight', 80),
+  height: () => propGetThemeVar('NavBarHeight', '44px'),
   showLeftButton: true,
   showRightButton: true,
   rightPillSpaceForce: 50,

+ 1 - 0
src/components/nav/TabBarItem.vue

@@ -1,6 +1,7 @@
 <template>
   <Touchable
     center
+    position="relative"
     direction="column"
     :innerStyle="{
       ...innerStyle,

+ 15 - 6
src/pages/home/index.vue

@@ -15,20 +15,21 @@
         id="map"
         class="w-100 height-400 radius-base overflow-hidden"
         :markers="mapLoader.content.value || []"
-        :enable-zoom="false"
-        :enable-scroll="false"
-        :scale="15"
+        :scale="10"
+        :longitude="AppCofig.defaultLonLat[0]"
+        :latitude="AppCofig.defaultLonLat[1]"
       />
     </Box>
     <Box title="优秀线上村史馆" icon="/static/images/home/icon-ancient-gate.png">
       <SimplePageContentLoader :loader="recommendLoader">
-        <FlexRow justify="space-between" align="center" wrap :gap="15">
+        <FlexRow justify="space-between" align="center" wrap :gap="25">
           <Touchable 
             v-for="(item, i) in recommendLoader.content.value"
             :key="i"
             flex="0 0 48%"
             align="center"
             direction="column"
+            :gap="20"
           > 
             <Image 
               :src="item.thumbnail || item.image" 
@@ -45,7 +46,7 @@
     </Box>
     <Box title="发现" icon="/static/images/home/icon-compass.png" showMore @moreClicked="$emit('goDiscover')">  
       <SimplePageContentLoader :loader="discoverLoader">
-        <FlexCol :gap="15">
+        <FlexCol :gap="25">
           <Touchable 
             v-for="(item, i) in discoverLoader.content.value"
             :key="i"
@@ -53,7 +54,7 @@
             align="center"
             direction="row"
           > 
-            <FlexCol flex="1">
+            <FlexCol flex="1" :gap="20">
               <Text :text="item.title" fontConfig="h5" />
               <Text :text="item.desc" fontConfig="subText" />
             </FlexCol>
@@ -102,24 +103,32 @@ const mapLoader = useSimpleDataLoader(async () => {
       title: '传统村落',
       longitude: Number(118.11441371826822),
       latitude: Number(24.51019917828817),
+      width: 30,
+      height: 30,
       iconPath: testImage(),
     },
     {
       title: '传统村落',
       longitude: Number(118.18573604529888),
       latitude: Number(24.485581319259357),
+      width: 30,
+      height: 30,
       iconPath: testImage(),
     },
     {
       title: '传统村落',
       longitude: Number(118.1242512731751),
       latitude: Number(24.417297514622685),
+      width: 30,
+      height: 30,
       iconPath: testImage(),
     },
     {
       title: '传统村落',
       longitude: Number(118.23861292755578),
       latitude: Number(24.559407658427826),
+      width: 30,
+      height: 30,
       iconPath: testImage(),
     },
   ]

+ 99 - 0
src/pages/home/store/index.vue

@@ -0,0 +1,99 @@
+<template>
+  <FlexCol :gap="20" :padding="20">
+    <SearchBar placeholder="输入关键词搜索" />
+    <FlexCol :radius="15" overflow="hidden">
+      <ImageSwiper 
+        :height="200"
+        :images="[
+          'https://mn.wenlvti.net/app_static/minnan/images/home/BackgroundBanner5.jpg',
+          'https://mn.wenlvti.net/app_static/minnan/images/home/BackgroundBanner4.jpg',
+          'https://mn.wenlvti.net/app_static/minnan/images/home/BackgroundBanner3.jpg',
+        ]"
+      />
+    </FlexCol>
+    <Box title="主题导览" icon="/static/images/home/icon-compass.png">
+      <ProvideVar :vars="{
+        GridItemIconSize: 70,
+        GridItemBackgroundColor: 'transparent',
+        GridItemPaddingHorizontal: 0,
+      }">
+        <Grid :borderGrid="false" :mainAxisCount="3">
+          <GridItem title="全部" icon="/static/images/icons/icon-all.png" touchable />
+          <GridItem title="拍摄标准" icon="/static/images/icons/icon-camera.png" touchable />
+          <GridItem title="命名规则" icon="/static/images/icons/icon-rules.png" touchable />
+          <GridItem title="文本规范" icon="/static/images/icons/icon-mark.png" touchable />
+          <GridItem title="隐私授权" icon="/static/images/icons/icon-pac.png" touchable />
+          <GridItem title="错误案例" icon="/static/images/icons/icon-route.png" touchable />
+        </Grid>
+      </ProvideVar>
+    </Box>
+    <Box title="最新" icon="/static/images/home/icon-shining.png" showMore @moreClicked="$emit('goDiscover')">  
+      <SimplePageContentLoader :loader="discoverLoader">
+        <FlexCol :gap="20">
+          <Touchable 
+            v-for="(item, i) in discoverLoader.content.value"
+            :key="i"
+            justify="space-between"
+            align="center"
+            direction="row"
+          > 
+            <FlexCol flex="1" :gap="10">
+              <Text :text="item.title" fontConfig="h5" />
+              <Text :text="item.desc" fontConfig="subText" />
+              <FlexRow :gap="10">
+                <Tag v-for="tag in item.tags" :key="tag" :text="tag" size="small" type="primary" scheme="light" />
+              </FlexRow>
+            </FlexCol>
+            <Width :width="25" />
+            <Image 
+              :src="item.thumbnail || item.image" 
+              :width="120" 
+              :height="120" 
+              :radius="15" 
+              mode="aspectFill" 
+              round
+            />
+          </Touchable>
+        </FlexCol>
+      </SimplePageContentLoader>
+    </Box>
+    <Loadmore status="nomore" />
+    <Height :height="150" />
+  </FlexCol>
+</template>
+
+<script setup lang="ts">
+import Box from '@/common/components/parts/Box.vue';
+import ImageSwiper from '@/common/components/parts/ImageSwiper.vue';
+import SimplePageContentLoader from '@/common/components/SimplePageContentLoader.vue';
+import { useSimpleDataLoader } from '@/common/composeabe/SimpleDataLoader';
+import AppCofig from '@/common/config/AppCofig';
+import Image from '@/components/basic/Image.vue';
+import Text from '@/components/basic/Text.vue';
+import Loadmore from '@/components/display/loading/Loadmore.vue';
+import Tag from '@/components/display/Tag.vue';
+import Touchable from '@/components/feedback/Touchable.vue';
+import SearchBar from '@/components/form/SearchBar.vue';
+import FlexCol from '@/components/layout/FlexCol.vue';
+import FlexRow from '@/components/layout/FlexRow.vue';
+import Grid from '@/components/layout/grid/Grid.vue';
+import GridItem from '@/components/layout/grid/GridItem.vue';
+import Height from '@/components/layout/space/Height.vue';
+import Width from '@/components/layout/space/Width.vue';
+import ProvideVar from '@/components/theme/ProvideVar.vue';
+import { RandomUtils } from '@imengyu/imengyu-utils';
+
+function testImage() {
+  return 'https://mncdn.wenlvti.net/app_static/minnan/images/home/ImageTest' + RandomUtils.genRandom(1, 5) +'.jpg';
+}
+
+const discoverLoader = useSimpleDataLoader(async () => {
+  return new Array(12).fill(0).map((_, i) => ({ 
+    title: '茶艺传承作坊' + i, 
+    desc: '多馆联展,沉浸式交互体验。',
+    tags: ['拍摄标准', '命名规则','拍摄标准', '命名规则'],
+    image: testImage(),
+    thumbnail: testImage(),
+  }));
+});
+</script>

+ 5 - 2
src/pages/index.vue

@@ -11,7 +11,8 @@
     <HomeIndex v-if="tabIndex === 0" @goDiscover="tabIndex = 1" />
     <DiscoverIndex v-else-if="tabIndex === 1" />
     <DigIndex v-else-if="tabIndex === 2" />
-    <UserIndex v-else-if="tabIndex === 4" />
+    <StoreIndex v-else-if="tabIndex === 3" />
+    <UserIndex v-else-if="tabIndex === 4" @goSubmit="tabIndex = 2" />
     <TabBar
       v-model:selectedTabIndex="tabIndex"
       fixed
@@ -19,7 +20,7 @@
     >
       <TabBarItem icon="/static/images/tabs/home.png" activeIcon="/static/images/tabs/home-active.png" text="首页" />
       <TabBarItem icon="/static/images/tabs/discover.png" activeIcon="/static/images/tabs/discover-active.png" text="发现" />
-      <TabBarItem icon="/static/images/tabs/dig.png" hump :humpHeight="[ 60, 60 ]" :humpSpace="[20,20]" :iconSize="140" />
+      <TabBarItem icon="/static/images/tabs/dig.png" hump :humpHeight="[ 10, 10 ]" :humpSpace="[20,20]" :iconSize="140" />
       <TabBarItem icon="/static/images/tabs/store.png" activeIcon="/static/images/tabs/store-active.png" text="知识库" />
       <TabBarItem icon="/static/images/tabs/user.png" activeIcon="/static/images/tabs/user-active.png" text="我的" />
     </TabBar>
@@ -36,6 +37,7 @@ import DigIndex from './dig/index.vue';
 import UserIndex from './user/index.vue';
 import HomeIndex from './home/index.vue';
 import DiscoverIndex from './home/discover/index.vue';
+import StoreIndex from './home/store/index.vue';
 
 const title = computed(() => {
   switch (tabIndex.value) {
@@ -61,5 +63,6 @@ const tabIndex = ref(0);
   background-size: 100% auto;
   background-repeat: no-repeat;
   background-image: url('@/static/images/BackgroundMask.jpg');
+  overflow-x: hidden;
 }
 </style>

+ 20 - 14
src/pages/user/index.vue

@@ -1,6 +1,13 @@
 <template>
   <FlexCol :padding="[40,30,50,30]">
-    <FlexRow align="center">
+    <Touchable 
+      direction="column"
+      justify="center" 
+      align="center"  
+      touchable 
+      :gap="25"
+      @click="goUserProfile"
+    >
       <Image 
         :src="userInfo?.avatar || UserHead"
         mode="aspectFill" 
@@ -9,20 +16,16 @@
         height="100rpx"
         round
       />
-      <Width :width="20" />
-      <Touchable v-if="userInfo" direction="column" touchable @click="navTo('/pages/user/update/profile')" :flex="1">
-        <H4>{{ userInfo.nickname }}</H4>
-        <text class="extra"><text class="label">守护编号</text><text>{{ userInfo.id }}</text><text class="label point-label">积分</text><text>{{ userInfo.totalCheckins }}</text></text>
-      </Touchable>
-      <Touchable v-else direction="column" touchable @click="navTo('/pages/user/login')" :flex="1">
-        <H4 class="nickname">请登录</H4>
-      </Touchable>
-      <Width :width="20" />
-      <Icon icon="arrow-right" />
-    </FlexRow>
+      <H4>{{ userInfo?.nickname || '请登录' }}</H4>
+      <H4>{{ userInfo?.mobile }}</H4>
+    </Touchable>
     <Height :height="50" />
-    <CellGroup v-if="userInfo">
-      <Cell icon="https://mn.wenlvti.net/uploads/20250313/cbc47d0b9cad7891e6154359952858c6.png" title="退出登录" showArrow touchable @click="doLogout" />
+    <CellGroup round>
+      <Cell icon="/static/images/user/icon-edit.png" title="我的投稿" showArrow touchable @click="$emit('goSubmit')" />
+      <Cell icon="/static/images/user/icon-profile.png" title="编辑资料" showArrow touchable @click="goUserProfile" />
+      <Cell icon="/static/images/user/icon-function.png" title="关于我们" showArrow touchable />
+      <Cell icon="/static/images/user/icon-chat.png" title="商务合作" showArrow touchable />
+      <Cell v-if="userInfo" icon="/static/images/user/icon-quit.png" title="退出登录" showArrow touchable @click="doLogout" />
     </CellGroup>
   </FlexCol>
 </template>
@@ -47,6 +50,9 @@ import FlexCol from '@/components/layout/FlexCol.vue';
 const authStore = useAuthStore();
 const userInfo = computed(() => authStore.userInfo);
 
+function goUserProfile() {
+  userInfo.value ? navTo('/pages/user/update/profile') : navTo('/pages/user/login');
+}
 function doLogout() {
   confirm({
     content: '您确定要退出登录吗?',

+ 5 - 2
src/pages/user/update/profile.vue

@@ -16,6 +16,7 @@
             class="avatar-image" 
             mode="aspectFill"
           ></image>
+          <text class="avatar-hint">点击可修改头像</text>
         </view>
       </view>
 
@@ -188,8 +189,10 @@ const submitForm = async () => {
 
 .avatar-container {
   position: relative;
-  display: inline-block;
-  margin-bottom: 8px;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  margin-bottom: 18px;
 }
 
 .avatar-image {

src/static/images/icons/icon-.png → src/static/images/icons/icon-rules.png


BIN
src/static/images/user/icon-quit.png