Przeglądaj źródła

🎨 按要求修改首页

快乐的梦鱼 3 dni temu
rodzic
commit
b5e20a0384

+ 9 - 1
src/common/components/parts/Box.vue

@@ -1,5 +1,13 @@
 <template>
-  <FlexCol backgroundColor="white" :padding="25" :radius="20" shadow="light">
+  <FlexCol 
+    backgroundColor="rgba(255, 255, 255, 0.8)" 
+    :innerStyle="{
+      backDropFilter: 'blur(10px)',
+    }"
+    :padding="[35,25]" 
+    :radius="30" 
+    shadow="light"
+  >
     <SubTitle :title="title" :showMore="showMore" @moreClicked="emit('moreClicked')">
       <template #left>
         <FlexRow align="center">

+ 1 - 1
src/components/README.md

@@ -6,7 +6,7 @@ NaEasy UI 是一款简单的 UniApp 移动端UI组件库。
 
 ## 版本
 
-当前版本:1.0.9-26031102
+当前版本:1.0.9-26031103
 
 ## 版权说明
 

+ 1 - 1
src/components/basic/CellGroup.vue

@@ -1,5 +1,5 @@
 <template>
-  <FlexCol :flex="1">
+  <FlexCol>
     <text v-if="title" :style="(titleSpeicalStyle as any)">
       {{ title }}
     </text>

+ 12 - 0
src/components/basic/Icon.vue

@@ -43,6 +43,7 @@
     :innerStyle="style"
     :innerClass="innerClass"
     :src="iconData.value"
+    :showFailed="!noError"
     mode="aspectFill"
   />
 </template>
@@ -82,14 +83,25 @@ export interface IconProps {
    * 自定义类名
    */
   innerClass?: string,
+  /**
+   * 是否不显示错误图标
+   */
+  noError?: boolean,
 }
 
 const theme = useTheme();
 const props = withDefaults(defineProps<IconProps>(), {
   size: 45,
+  noError: false,
 });
 const icon = computed(() => props.icon || props.name);
 const iconData = computed(() => {
+  if (IconUtils.iconCount.value === 0) {
+    return {
+      type: 'none',
+      value: '',
+    } as IconItem
+  }
   const data = icon.value ? IconUtils.getIconDataFromMap(icon.value) : undefined;
   if (!data && icon.value && icon.value.startsWith('icon-')) {
     return {

+ 9 - 1
src/components/basic/IconUtils.ts

@@ -1,3 +1,5 @@
+import { ref } from "vue";
+
 export type IconItem = {
   type: 'iconfont'|'image'|'svg'|'none',
   value: string,
@@ -11,6 +13,7 @@ type IconMap = Record<string, IconItem>;
 const iconMap = {} as IconMap;
 
 export const IconUtils = {
+  iconCount: ref(0),
   /**
    * 设置 Icon 组件的图标名称映射。
    * 如果已存在同名数据,则会覆盖之前的。
@@ -51,6 +54,7 @@ export const IconUtils = {
       } 
       iconMap[key] = result;
     }
+    this.iconCount.value = Object.keys(iconMap).length;
   },
   getColoredSvg(svg: string, color: string) {
     return toDataSvg(
@@ -76,7 +80,11 @@ export const IconUtils = {
    * 加载默认图标。可选从本地或者网络加载。
    * @param urlOrJson 图标URL或者JSON字符串
    */
-  loadDefaultIcons(urlOrJson: string) {
+  loadDefaultIcons(urlOrJson: string | Record<string, string>) {
+    if (typeof urlOrJson === 'object') {
+      this.configIconMap(urlOrJson);
+      return;
+    }
     if (urlOrJson.startsWith('http') || urlOrJson.startsWith('https')) {
       uni.request({
         url: urlOrJson,

+ 1 - 1
src/components/basic/Image.vue

@@ -27,7 +27,7 @@
       @error="isErrorState = true; isLoadState = false"
     />
     <view v-if="showFailed && isErrorState && !failedImage" class="inner-view error">
-      <Icon icon="warning" color="text.second" :size="32" />
+      <Icon icon="warning" color="text.second" :size="32" noError />
       <Text v-if="realWidth > 50" color="text.second" :text="src ? '加载失败' : '暂无图片'" :fontSize="22" />
     </view>
     <view v-if="showLoading && isLoadState" class="inner-view loading">

+ 9 - 1
src/components/display/parse/Parse.vue

@@ -1,6 +1,12 @@
 <template>
   <view class="nana-Parse-container" :style="contentStyle">
-    <ParseNodeRender v-for="(node, index) in nodes" :key="index" :node="node" />
+    <ParseNodeRender 
+      v-for="(node, index) in nodes" 
+      :key="index" 
+      :node="node" 
+      @linkTap="emit('linkTap', $event)"
+      @viewTap="emit('viewTap', $event)"
+    />
   </view>
 </template>
 
@@ -29,6 +35,8 @@ export interface ParseProps {
   contentStyle?: any;
 }
 
+const emit = defineEmits(['linkTap', 'viewTap']);
+
 const props = withDefaults(defineProps<ParseProps>(), {
   tagStyle: () => ({}),
   classStyle: () => ({}),

+ 7 - 0
src/components/display/parse/ParseNodeRender.vue

@@ -153,6 +153,7 @@
     :data-tag="node.tag"
     :class="node.attrs?.class || ''"
     :style="style"
+    @click="viewTap(node.attrs?.id)"
   >
     <ParseNodeRender
       v-for="(child, index) in node.children"
@@ -182,6 +183,7 @@ const props = withDefaults(defineProps<{
 }>(), {
 });
 
+const emit = defineEmits(['linkTap', 'viewTap']);
 const tagStyle = inject<Ref<Record<string, string>>>('tagStyle', ref({}));
 const classStyle = inject<Ref<Record<string, string>>>('classStyle', ref({}));
 const praseImages = inject<Ref<string[]>>('praseImages', ref([]));
@@ -252,6 +254,7 @@ const isInline = computed(() => [
 // 链接点击事件
 const linkTap = (e: any) => {
   const href = props.node.attrs?.href as string;
+  emit('linkTap', href);
   if (href) {
     if (href[0] === '#') {
       // 跳转锚点
@@ -298,6 +301,10 @@ const linkTap = (e: any) => {
   }
 };
 
+const viewTap = (e: any) => {
+  emit('viewTap', e);
+};
+
 function preview(url: string) {
   if (url) {
     if (praseImages.value.includes(url)) {

+ 2 - 0
src/components/form/Rate.vue

@@ -202,6 +202,8 @@ function handleDrag(x: number) {
   if (v === 0 && !props.canbeZero)
     v = props.half ? 0.5 : 1;
 
+  v = Math.max(0, Math.min(v, props.count));
+
   if (v !== value.value) {
     updateValue(v);
   }

+ 7 - 0
src/components/keyboard/NumberKeyBoard.vue

@@ -4,6 +4,7 @@
     closeable
     :closeIcon="false"
     :mask="mask === true"
+    :size="size"
     position="bottom"
     @close="onClose"
   >
@@ -39,6 +40,11 @@ export interface NumberKeyBoardProps extends NumberKeyBoardInnerProps {
    * @default false
    */
   mask?: boolean;
+  /**
+   * 键盘大小
+   * @default 'auto'
+   */
+  size?: string|number;
 }
 
 const emit = defineEmits([ 'delete', 'input', 'finish', 'update:show' ]);
@@ -47,6 +53,7 @@ const props = withDefaults(defineProps<NumberKeyBoardProps>(), {
   keyPressedImpactFeedback: true,
   keyRandomOrder: false,
   showCloseButton: true,
+  size: 'auto',
 });
 
 const onClose = () => {

+ 7 - 0
src/components/keyboard/PlateKeyBoard.vue

@@ -4,6 +4,7 @@
     closeable
     :closeIcon="false"
     :mask="mask === true"
+    :size="size"
     position="bottom"
     @close="onClose"
   >
@@ -41,6 +42,11 @@ export interface PlateKeyBoardProps extends PlateKeyBoardInnerProps {
    * @default false
    */
   mask?: boolean;
+  /**
+   * 键盘大小
+   * @default 'auto'
+   */
+  size?: string|number;
 }
 
 const emit = defineEmits([ 'delete', 'input', 'finish', 'cancel', 'update:show' ]);
@@ -48,6 +54,7 @@ const props = withDefaults(defineProps<PlateKeyBoardProps>(), {
   showFinishButton: () => propGetThemeVar('PlateKeyBoardShowFinishButton', true),
   showDeleteButton: () => propGetThemeVar('PlateKeyBoardShowDeleteButton', true),
   keyPressedImpactFeedback: () => propGetThemeVar('PlateKeyBoardKeyPressedImpactFeedback', true),
+  size: 'auto',
 });
 
 const onClose = () => {

+ 2 - 2
src/pages/home/discover/index.vue

@@ -8,13 +8,13 @@
       }">
         <Grid :borderGrid="false" :mainAxisCount="4">
           <GridItem title="全部" icon="https://mncdn.wenlvti.net/app_static/xiangyuan/images/icons/icon-all.png" touchable @click="goList('')" />
-          <GridItem title="历史文化" icon="https://mncdn.wenlvti.net/app_static/xiangyuan/images/icons/icon-history.png" touchable @click="goList('历史文化')" />
+          <!-- <GridItem title="历史文化" icon="https://mncdn.wenlvti.net/app_static/xiangyuan/images/icons/icon-history.png" touchable @click="goList('历史文化')" /> -->
           <GridItem title="环境格局" icon="https://mncdn.wenlvti.net/app_static/xiangyuan/images/icons/icon-envirounment.png" touchable @click="goList('环境格局')" />
           <GridItem title="传统建筑" icon="https://mncdn.wenlvti.net/app_static/xiangyuan/images/icons/icon-buliding.png" touchable @click="goList('传统建筑')" />
           <GridItem title="民俗文化" icon="https://mncdn.wenlvti.net/app_static/xiangyuan/images/icons/icon-location.png" touchable @click="goList('民俗文化')" />
           <GridItem title="地道美食" icon="https://mncdn.wenlvti.net/app_static/xiangyuan/images/icons/icon-foods.png" touchable @click="goList('美食物产')" />
           <GridItem title="物产资源" icon="https://mncdn.wenlvti.net/app_static/xiangyuan/images/icons/icon-resource.png" touchable @click="goList('历史人物')" />
-          <GridItem title="旅游线路" icon="https://mncdn.wenlvti.net/app_static/xiangyuan/images/icons/icon-route.png" touchable @click="goList('旅游线路')" />
+          <!-- <GridItem title="旅游线路" icon="https://mncdn.wenlvti.net/app_static/xiangyuan/images/icons/icon-route.png" touchable @click="goList('旅游线路')" /> -->
         </Grid>
       </ProvideVar>
     </Box>

+ 32 - 8
src/pages/home/index.vue

@@ -1,6 +1,6 @@
 <template>
-  <FlexCol :gap="20" :padding="20">
-    <FlexCol :radius="15" overflow="hidden">
+  <FlexCol :gap="20" :padding="30">
+    <!-- <FlexCol :radius="15" overflow="hidden">
       <ImageSwiper 
         :height="300"
         :images="[
@@ -11,19 +11,38 @@
           'https://mncdn.wenlvti.net/app_static/xiangyuan/images/causel/5.jpg',
         ]"
       />
-    </FlexCol>
+    </FlexCol> -->
+    <Height :height="220" />
     <Box title="村社分布" icon="https://mncdn.wenlvti.net/app_static/xiangyuan/images/home/icon-pin-distance.png">
       <map 
         id="prevMap"
         map-id="prevMap"
-        :style="{ width: '100%', height: '400rpx', borderRadius: '10rpx', overflow: 'hidden' }"
+        :style="{ width: '100%', height: '800rpx', borderRadius: '10rpx', overflow: 'hidden' }"
         :markers="mapLoader.content.value || []"
         :scale="10"
         :longitude="AppCofig.defaultLonLat[0]"
         :latitude="AppCofig.defaultLonLat[1]"
         @markertap="goVillageDetails($event)"
       />
+      <Height :height="20" />
+      <ProvideVar :vars="{
+        GridItemIconSize: 90,
+        GridItemBackgroundColor: 'transparent',
+        GridItemPaddingHorizontal: 0,
+      }">
+        <Grid :borderGrid="false" :mainAxisCount="4">
+          <GridItem title="匠韵薪传" icon="https://mncdn.wenlvti.net/app_static/xiangyuan/images/home/IconInherit.png" touchable @click="goList('匠韵薪传')" />
+          <GridItem title="文物古迹" icon="https://mncdn.wenlvti.net/app_static/xiangyuan/images/home/IconArtifact.png" touchable @click="goList('文物古迹')" />
+          <GridItem title="历史文化" icon="https://mncdn.wenlvti.net/app_static/xiangyuan/images/home/IconHistory.png" touchable @click="goList('历史文化')" />
+          <GridItem title="指导单位" icon="https://mncdn.wenlvti.net/app_static/xiangyuan/images/home/IconUnit.png" touchable @click="goList('指导单位')" />
+          <GridItem title="旅游路线" icon="https://mncdn.wenlvti.net/app_static/xiangyuan/images/home/IconRoute.png" touchable @click="goList('旅游路线')" />
+          <GridItem title="景区景点" icon="https://mncdn.wenlvti.net/app_static/xiangyuan/images/home/IconScenicArea.png" touchable @click="goList('景区景点')" />
+          <GridItem title="村务公开" icon="https://mncdn.wenlvti.net/app_static/xiangyuan/images/home/IconPublic.png" touchable @click="goList('村务公开')" />
+          <GridItem title="民情反馈" icon="https://mncdn.wenlvti.net/app_static/xiangyuan/images/home/IconFeedBack.png" touchable @click="goList('民情反馈')" />
+        </Grid>
+      </ProvideVar>
     </Box>
+
     <Box title="线上史馆展示" icon="https://mncdn.wenlvti.net/app_static/xiangyuan/images/home/icon-ancient-gate.png">
       <SimplePageContentLoader :loader="recommendLoader">
         <FlexRow justify="space-between" align="center" wrap :gap="25">
@@ -48,7 +67,7 @@
         </FlexRow>
       </SimplePageContentLoader>
     </Box>
-    <Box title="发现" icon="https://mncdn.wenlvti.net/app_static/xiangyuan/images/home/icon-compass.png" showMore @moreClicked="$emit('goDiscover')">  
+    <Box title="精彩推荐" icon="https://mncdn.wenlvti.net/app_static/xiangyuan/images/home/icon-compass.png" showMore @moreClicked="$emit('goDiscover')">  
       <SimplePageContentLoader :loader="discoverLoader">
         <FlexCol :gap="25">
           <Touchable 
@@ -67,11 +86,10 @@
             <Image 
               :src="item.image" 
               :failedImage="AppCofig.defaultImage"
-              :width="120" 
+              :width="170" 
               :height="120" 
               :radius="15" 
-              mode="aspectFill" 
-              round
+              mode="aspectFill"
             />
           </Touchable>
         </FlexCol>
@@ -100,6 +118,9 @@ import FlexCol from '@/components/layout/FlexCol.vue';
 import FlexRow from '@/components/layout/FlexRow.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 Grid from '@/components/layout/grid/Grid.vue';
+import GridItem from '@/components/layout/grid/GridItem.vue';
 
 const instance = getCurrentInstance();
 const mapCtx = uni.createMapContext('prevMap', instance);
@@ -164,4 +185,7 @@ function goDiscoverDetails(item: any) {
   });
 }
 
+function goList(keywords: string) {
+}
+
 </script>

+ 3 - 3
src/pages/index.vue

@@ -6,7 +6,7 @@
         :title="title"
         :titleScroll="false"
         backgroundColor="transparent"
-        textColor="white"
+        textColor="black"
         align="left"
       />
       <HomeIndex v-if="tabIndex === 0" @goDiscover="tabIndex = 1" />
@@ -80,8 +80,8 @@ onShareTimeline(() => {
 .index {
   background-position: top left;
   background-size: 100% auto;
-  background-repeat: no-repeat;
-  background-image: url('https://mncdn.wenlvti.net/app_static/xiangyuan/images/BackgroundMask.jpg');
+  background-repeat: repeat;
+  background-image: url('https://mncdn.wenlvti.net/app_static/xiangyuan/images/home/HomeBackground.jpg');
   overflow-x: hidden;
 }
 </style>