Kaynağa Gözat

📦 全部的内容接口基础搭建

imengyu 1 ay önce
ebeveyn
işleme
ab090e31d7
38 değiştirilmiş dosya ile 1351 ekleme ve 1539 silme
  1. 4 6
      src/App.vue
  2. 9 1
      src/api/CommonContent.ts
  3. 0 2
      src/changelog.md
  4. 0 831
      src/common/components/y-video-slide/y-video-slide.vue
  5. 0 68
      src/package.json
  6. 26 10
      src/pages.json
  7. 47 0
      src/pages/article/common/CommonContent.ts
  8. 41 4
      src/pages/article/common/CommonListPage.vue
  9. 6 0
      src/pages/article/common/list.vue
  10. 1 1
      src/pages/article/details.vue
  11. 0 1
      src/pages/article/list.vue
  12. 162 93
      src/pages/discover.vue
  13. 151 59
      src/pages/home.vue
  14. 1 1
      src/pages/home/introduction.vue
  15. 168 170
      src/pages/inhert.vue
  16. 4 66
      src/pages/inhert/artifact/details.vue
  17. 1 1
      src/pages/inhert/artifact/list.vue
  18. 49 0
      src/pages/inhert/intangible/details.vue
  19. 77 0
      src/pages/inhert/intangible/list.vue
  20. 38 0
      src/pages/parts/ImageSwiper.vue
  21. 161 132
      src/pages/travel.vue
  22. 397 0
      src/pages/travel/calendar.vue
  23. 2 2
      src/pages/user/login.vue
  24. 3 6
      src/pages/video/details.vue
  25. 0 84
      src/static/css/font.css
  26. BIN
      src/static/fonts/STSongti-SC-Black.ttf
  27. BIN
      src/static/fonts/STSongti-SC-Black.woff
  28. BIN
      src/static/fonts/STSongti-SC-Black.woff2
  29. BIN
      src/static/images/home/ImageTest2.jpg
  30. BIN
      src/static/images/home/ImageTest3.jpg
  31. BIN
      src/static/images/home/ImageTest4.jpg
  32. BIN
      src/static/images/home/ImageTest5.jpg
  33. BIN
      src/static/images/inhert/TestImage1.jpg
  34. BIN
      src/static/images/inhert/TestImage2.jpg
  35. BIN
      src/static/images/inhert/TestImage3.jpg
  36. BIN
      src/static/images/inhert/TestImage4.jpg
  37. BIN
      src/static/images/inhert/TestImage5.jpg
  38. 3 1
      src/uni.scss

+ 4 - 6
src/App.vue

@@ -18,11 +18,9 @@ onLaunch(() => {
 </script>
 
 <style lang="scss">
-  @import "@/uni_modules/uview-plus/index.scss";
-	@import "@/common/scss/fonts.scss";
-	@import "@/common/scss/common.scss";
-	@import "@/common/scss/global/base.scss";
+@use "@/common/scss/fonts.scss" as *;
+@use "@/common/scss/common.scss" as *;
+@use "@/common/scss/global/base.scss" as *;
+@import "@/uni_modules/uview-plus/index.scss";
 </style>
 
-<style></style>
-

+ 9 - 1
src/api/CommonContent.ts

@@ -173,6 +173,14 @@ export class GetContentDetailItem extends DataModel<GetContentDetailItem> {
         };
       return undefined;
     };
+    this._afterSolveServer = () => {
+      if (!this.image && this.images && this.images && this.images.length > 0  ) {
+        this.image = this.images[0]
+      }
+      if ((!this.images || this.images.length == 0) && this.image) {
+        this.images = [ this.image ]
+      }
+    }
   }
 
   id = 0;
@@ -182,7 +190,7 @@ export class GetContentDetailItem extends DataModel<GetContentDetailItem> {
   title = '';
   region = 0;
   image = '';
-  images = [];
+  images = [] as string[];
   audio = '';
   video = '';
   desc = '';

+ 0 - 2
src/changelog.md

@@ -1,2 +0,0 @@
-## 1.0.0(2022-01-05)
-初始版本

+ 0 - 831
src/common/components/y-video-slide/y-video-slide.vue

@@ -1,831 +0,0 @@
-<template>
-	<view class="widget-video" :style="{height:videoHeight}">
-		<!-- 下拉刷新 -->
-		<view v-if="marginTop>0" class="refresh-box">
-			松开刷新
-		</view>
-		<!-- 视频容器 -->
-		<view class="scroll-video-box" @touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd"
-			:style="{'marginTop':marginTop+'px','transition':transition}">
-			<view ref="videoItemBox" class="video-item-box" v-for="(item, index) in videoList" :key="index"
-				:style="{height:videoHeight}">
-				<video @click="$event => {pauseVideo($event, item)}" :id="item.id" class="fullscreen-video"
-					:src="item.videoUrl" @error="videoError(item,index)" :poster="item.posterUrl" :controls="false"
-					:show-progress="false" :show-fullscreen-btn="false" :show-play-btn="false" :loop="true"
-					:autoplay="index == 0" :show-center-play-btn="false">
-				</video>
-				<template v-for="(fabulous, fabulousIndx) in fabulousArr">
-					<i v-if="fabulous != null" @click="fabulousDbClick" class="iconfont iconxihuan fabulous-item"
-						:style="{'top':fabulous.top,'left':fabulous.left,'opacity':fabulous.opacity,'transform':fabulous.transform}"></i>
-				</template>
-
-				<i :class="['iconfont iconbofang btn-play',currentStatus == 'pause' && currentIndex == index ? 'show' : '']"
-					@click="pauseVideo"></i>
-				<view class="video-info">
-					<view class="atavar-box">
-						<image class="atavar-img" :src="item.userHead" mode="widthFix"></image>
-						<view class="add-follow-btn" @click="followFunc(index,item)">
-							<i
-								:class="['iconfont inline-block icon-follow', item.isFollow == 1 ? 'iconduihao' : 'iconjia1']"></i>
-						</view>
-					</view>
-					<view class="icon-box" @click="toggleFabulous(item, index)">
-						<i :class="['iconfont iconxihuan icon-btn', item.isFabulous ? 'color-red' : '']"></i>
-						<view class="count-text">{{item.fabulousCount}}</view>
-					</view>
-					<view class="icon-box" @click="commontAdd">
-						<i class="iconfont iconIMliaotian-shixin icon-btn"></i>
-						<view class="count-text">{{item.commentCount}}</view>
-					</view>
-					<view class="icon-box">
-						<i class="iconfont iconfenxiang icon-btn" @click="shareFunc(item)"></i>
-						<view class="count-text">{{item.shareCount}}</view>
-					</view>
-				</view>
-				<view class="video-title">
-					<view class="user-name">@{{item.userNick}}</view>
-					<view class="video-content">{{item.videoContent}}</view>
-				</view>
-			</view>
-			<view v-if="videoList.length == 0" class="empty-txt">当前没有可播放视频哦~</view>
-		</view>
-
-		<!-- 上拉加载 -->
-		<view v-if="videoList.length > 0" class="load-more-box">
-			加载更多
-		</view>
-		<!-- 评论弹窗 -->
-		<view :class="['commont-box',commontShow ? 'active' : '']">
-			<view class="commont-title">{{currentComment.count}}条评论</view>
-			<view class="commont-list">
-				<view v-for="(item, index) in currentComment.list" :key="index">
-					<view class="comment-panel">
-						<image class="first-user" :src="item.userHead" mode="widthFix"></image>
-						<view class="first-comment">
-							<view class="comment-name">{{item.userNick}}</view>
-							<view class="comment-content">{{item.content}}</view>
-							<view class="time-box">
-								<text class="inline-block">{{item.time}}</text>
-								<view class="inline-block reply-btn" @click="reply('first',item,index)">回复</view>
-							</view>
-						</view>
-						<view class="fabulous-box">
-							<i :class="['iconfont iconxihuan fabulous-btn', item.isFabulous == '1' ? 'color-red' : '']"
-								@click="commentFabulous('first',item,index)"></i>
-							<view class="fabulous-text">{{item.fabulousCount}}</view>
-						</view>
-					</view>
-					<view style="padding-left: 70rpx;">
-						<view class="comment-panel" v-for="(child, childIndex) in item.children">
-							<image class="first-user" :src="child.userHead" mode="widthFix"></image>
-							<view class="first-comment">
-								<view class="comment-name" v-if="child.replyTo == item.userNick">{{child.userNick}}
-								</view>
-								<view class="comment-name" v-else>
-									<span class="inline-block">{{child.userNick}}</span>
-									<span class="inline-block">
-										<i class="iconfont iconxiangyou1" style="font-size: 8px;"></i>
-									</span>
-									<span class="inline-block">{{child.replyTo}}</span>
-								</view>
-								<view class="comment-content">{{child.content}}</view>
-								<view class="time-box">
-									<text class="inline-block">{{child.time}}</text>
-									<view class="inline-block reply-btn"
-										@click="reply('second',child,index,childIndex)">回复</view>
-								</view>
-							</view>
-							<view class="fabulous-box">
-								<i :class="['iconfont iconxihuan fabulous-btn', child.isFabulous == '1' ? 'color-red' : '']"
-									@click="commentFabulous('second',child,index,childIndex)"></i>
-								<view class="fabulous-text">{{child.fabulousCount}}</view>
-							</view>
-						</view>
-					</view>
-				</view>
-			</view>
-			<!-- 评论输入框 -->
-			<input class="comment-input" @confirm="commentCommit" @blur="commentBlur" v-model="replyContent"
-				:focus="showInput" :placeholder="commentPlaceholder" type="text" />
-		</view>
-
-	</view>
-</template>
-
-<script>
-	// #ifdef APP-NVUE
-	const dom = weex.requireModule('dom');
-	// #endif
-	export default {
-		props: {
-			// 视频容器高度
-			videoHeight: {
-				type: String,
-				default: '100vh'
-			},
-			// 列表数据
-			data: {
-				type: Array,
-				default () {
-					return []
-				}
-			},
-			// 当前视频下标
-			videoIndex:{
-				type:[Number,String],
-				default:'0'
-			}
-		},
-		data() {
-			return {
-				// 视频列表数据
-				videoList: this.data,
-				// 视频实际高度,用于滚动计算
-				videoRealHeight: 0,
-				// 双击点赞记录
-				fabulousArr: [],
-				// 记录点击时间判断单击还是双击,单击暂停,双击点赞
-				clickTimer: null,
-				// 记录点击时间
-				clickTime: 0,
-				// 屏幕高度
-				windowHeight: uni.getSystemInfoSync().windowHeight || window.innerHeight,
-				// 动画效果
-				transition: 'none',
-				// 触摸开始值
-				startY: 0,
-				// 触摸移动值
-				moveY: 0,
-				// 滑动开始时间
-				startTime: 0,
-				// 向上滑动距离
-				marginTop: 0,
-				// 每次向上滑动的距离
-				fixMarginTop: 0,
-				// 滑动方向
-				moveDirection: '',
-				// 当前轮播的index
-				currentIndex: 0,
-				// 当前页的视频对象
-				currentVideo: null,
-				// 当前视频的评论
-				currentComment: [],
-				// 视频状态:播放/暂停
-				currentStatus: 'play',
-				// 是否显示评论
-				commontShow: false,
-				// 爱心动画双击
-				fabulousTime: 0,
-				fabulousTimer: null,
-				// 显示评论输入框
-				showInput: false,
-
-				// 评论提示
-				commentPlaceholder: '说点好听的~',
-				// 回复对象
-				replyType: 'video',
-				replyObj: {},
-				replyIndex: 0,
-				replyParentIndex: 0,
-				// 评论内容
-				replyContent: '',
-
-			};
-		},
-		watch: {
-			data: {
-				handler(n) {
-					this.videoList = n;
-				},
-				deep: true
-			}
-		},
-		// #ifdef APP-NVUE
-		onReady() {
-			dom.getComponentRect(this.$refs.videoItemBox, option => {
-				this.videoRealHeight = option.size.height;
-			});
-		},
-		// #endif
-		mounted() {
-			// 初始化视频容器计算高度
-			//#ifdef H5
-			this.videoRealHeight = this.$refs['videoItemBox'][0].$el.getBoundingClientRect().height;
-			//#endif
-			//#ifdef MP-WEIXIN
-			const query = uni.createSelectorQuery().in(this);
-			query.select('.video-item-box').boundingClientRect(data => {
-				this.videoRealHeight = data.height;
-			}).exec();
-			//#endif
-			// 初始化第一个视频播放器
-			this.currentVideo = uni.createVideoContext(this.videoList[0].id, this);
-			// 初始化评论
-			this.currentComment = this.videoList[0].commentObj;
-			// 定时清除动画元素
-			this.clearFabulousArr();
-		},
-		methods: {
-			// 视频出错
-			videoError(item, index) {
-				uni.showToast({
-					title: '视频出错了!',
-					icon: 'none'
-				})
-			},
-			// 触摸开始
-			touchStart(e) {
-				this.transition = 'none';
-				this.startY = e.touches[0].pageY;
-				this.startTime = new Date().getTime();
-			},
-			// 触摸滑动
-			touchMove(e) {
-				// 如果评论面板打开,禁止滑动
-				if (this.commontShow) {
-					return;
-				}
-				this.moveY = e.touches[0].pageY;
-				if (this.moveY > this.startY) {
-					// 返回上一个视频
-					let range = this.fixMarginTop + this.moveY - this.startY;
-					if (this.currentIndex == 0) {
-						this.marginTop = range > 50 ? 50 : range;
-					} else {
-						this.marginTop = range;
-					}
-					this.moveDirection = 'up';
-				} else {
-					if (this.videoList.length == 0) {
-						return;
-					}
-					// 查看下一个视频
-					let range = this.fixMarginTop - this.startY + this.moveY;
-					if (this.currentIndex == this.videoList.length - 1) {
-						// 最后一个视频的位置
-						let lastVideo = -this.currentIndex * this.videoRealHeight + -50;
-						this.marginTop = range < lastVideo ? lastVideo : range;
-					} else {
-						this.marginTop = range;
-					}
-					this.moveDirection = 'down';
-				}
-			},
-			// 触摸结束
-			touchEnd(e) {
-				this.transition = 'all .2s';
-				if (this.currentIndex == 0 && this.marginTop >= 45) {
-					// 下拉刷新
-					this.$emit('refresh');
-					this.marginTop = 0;
-					return;
-				}
-				if (this.currentIndex == this.videoList.length - 1 && this.marginTop < (this.fixMarginTop - 45)) {
-					this.marginTop = this.fixMarginTop;
-					// 加载更多
-					this.$emit('loadMore');
-					return;
-				}
-				let millisecond = new Date().getTime() - this.startTime;
-				let condition1 = this.moveY > 0 && Math.abs(this.moveY - this.startY) > 50 && millisecond < 500;
-				let condition2 = this.moveY > 0 && Math.abs(this.moveY - this.startY) > this.videoRealHeight / 3;
-				if (condition1 || condition2) {
-					if (this.moveDirection == 'up') {
-						// 返回上一个
-						if (this.currentIndex == 0) {
-							this.marginTop = 0;
-						} else {
-							this.marginTop = this.fixMarginTop + this.videoRealHeight;
-							this.currentIndex = this.currentIndex - 1;
-							this.$emit('update:videoIndex',this.currentIndex);
-							this.currentComment = this.videoList[this.currentIndex].commentObj;
-							this.videoPlayChange();
-						}
-					} else {
-						// 查看下一个
-						if (this.currentIndex == this.videoList.length - 1) {
-							this.marginTop = this.fixMarginTop;
-						} else {
-							this.marginTop = this.fixMarginTop - this.videoRealHeight;
-							this.currentIndex = this.currentIndex + 1;
-							this.$emit('update:videoIndex',this.currentIndex);
-							this.currentComment = this.videoList[this.currentIndex].commentObj;
-							this.videoPlayChange();
-						}
-					}
-				} else {
-					this.marginTop = this.fixMarginTop;
-				}
-				this.fixMarginTop = this.marginTop;
-				this.startY = 0;
-				this.moveY = 0;
-			},
-			// 滑动切换
-			videoPlayChange() {
-				this.stopOtherVideo();
-				let video = uni.createVideoContext(this.videoList[this.currentIndex].id, this);
-				this.currentVideo = video;
-				this.currentVideo.play();
-				this.currentStatus = 'play';
-			},
-			// 暂停其他视频
-			stopOtherVideo() {
-				this.videoList.map(v => {
-					let video = uni.createVideoContext(v.id, this);
-					video.seek(1);
-					video.pause();
-				})
-			},
-			// 暂停/播放视频/双击点赞事件
-			pauseVideo(e, item) {
-				// 视频对象为空,返回
-				if (!this.currentVideo) return;
-				if (this.commontShow) {
-					this.commontShow = false;
-					return;
-				}
-				clearTimeout(this.clickTimer);
-				let currentTime = new Date().getTime();
-				let timeRange = currentTime - this.clickTime;
-				if (timeRange < 300) {
-					// 双击事件
-					if (!item.isFabulous) {
-						this.$emit('fabulous', item, true);
-					}
-					this.dbClickAnimation(e);
-				} else {
-					// 单击事件
-					this.clickTimer = setTimeout(() => {
-						e.preventDefault();
-						e.stopPropagation();
-						if (this.currentStatus == 'play') {
-							this.currentVideo.pause();
-							this.currentStatus = 'pause';
-						} else {
-							this.currentVideo.play();
-							this.currentStatus = 'play';
-						}
-					}, 300);
-				}
-				this.clickTime = new Date().getTime();
-			},
-			// 已有爱心叠加双击事件
-			fabulousDbClick(e) {
-				clearTimeout(this.fabulousTimer);
-				let currentTime = new Date().getTime();
-				let timeRange = currentTime - this.fabulousTime;
-				if (timeRange < 300) {
-					// 双击事件
-					this.dbClickAnimation(e);
-				} else {
-
-				}
-				this.fabulousTime = new Date().getTime();
-			},
-			// 双击点赞动画
-			dbClickAnimation(e) {
-				let deg = Math.round(Math.random() * 40 + 5);
-				this.fabulousArr.push({
-					left: e.detail.x - 25 + 'px',
-					top: e.detail.y - 25 + 'px',
-					transform: 'rotate(' + (deg % 2 == 0 ? deg : -deg) + 'deg)',
-					createTime: new Date().getTime()
-				})
-
-				let index = this.fabulousArr.length > 0 ? this.fabulousArr.length - 1 : 0;
-				setTimeout(() => {
-					this.$set(this.fabulousArr, index, Object.assign(this.fabulousArr[index], {
-						opacity: 0,
-						transform: 'scale(3) ' + this.fabulousArr[index].transform
-					}))
-					setTimeout(() => {
-						this.fabulousArr.splice(index, 1, null);
-					}, 1000);
-				}, 500);
-
-				if (!this.videoList[this.currentIndex].isFabulous) {
-					this.$set(this.videoList, this.currentIndex, Object.assign(this.videoList[this.currentIndex], {
-						isFabulous: 1,
-						fabulousCount: this.videoList[this.currentIndex].isFabulous + 1
-					}))
-				}
-			},
-			// 定时清除点赞动画元素
-			clearFabulousArr() {
-				const indexArr = this.fabulousArr.map((v, i) => {
-					if (v.opacity == '0') {
-						return i;
-					}
-				});
-				indexArr.forEach(v => {
-					this.fabulousArr.splice(v, 1);
-				});
-			},
-			// 点赞切换
-			toggleFabulous(item, index) {
-				this.$emit('fabulous', item, item.isFabulous ? false : true);
-				this.$set(this.videoList, index, Object.assign(item, {
-					isFabulous: item.isFabulous ? 0 : 1,
-					fabulousCount: item.isFabulous ? item.fabulousCount - 1 : item.fabulousCount + 1,
-				}));
-			},
-			// 评论
-			commontAdd() {
-				this.commontShow = true;
-				this.replyType = 'video';
-				this.replyObj = this.currentVideo;
-			},
-			// 分享
-			shareFunc(item) {
-				this.$emit('share', item);
-			},
-			// 关注
-			followFunc(index, item) {
-				let flag = item.isFollow == 1 ? false : true;
-				if (flag) {
-					uni.showToast({
-						title: '关注成功',
-						icon: 'none'
-					})
-				} else {
-					uni.showToast({
-						title: '取消关注',
-						icon: 'none'
-					})
-				}
-				this.$emit('follow', item, flag);
-				this.$set(this.videoList, index, Object.assign(item, {
-					isFollow: item.isFollow == 1 ? 0 : 1
-				}));
-			},
-			// 评论点赞
-			commentFabulous(level, item, index, childIndex) {
-				const result = item.isFabulous == '1' ? '0' : '1';
-				item.isFabulous = result;
-				if (result == '1') {
-					item.fabulousCount = item.fabulousCount + 1;
-				} else {
-					item.fabulousCount = item.fabulousCount - 1;
-				}
-				if (level === 'first') {
-					this.currentComment.list[index] = item;
-				} else {
-					this.currentComment.list[index].children[childIndex] = item;
-				}
-				this.$emit('commentFabulous', item);
-			},
-			// 回复评论
-			reply(level, item, index, childIndex) {
-				this.showInput = true;
-				this.commentPlaceholder = `回复@${item.userNick}`;
-				this.replyIndex = childIndex;
-				this.replyType = level;
-				this.replyParentIndex = index;
-				this.replyObj = item;
-			},
-			// 提交评论
-			commentCommit() {
-				this.showInput = false;
-				if (this.replyType == 'video') {
-					this.currentComment.list.push({
-						userHead: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fup.enterdesk.com%2Fedpic%2F5e%2F4e%2Ff0%2F5e4ef0e451852e0114d75eac14f60924.jpeg&refer=http%3A%2F%2Fup.enterdesk.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1642669624&t=028d851350e18512dbf4bfe3a86cbfa4',
-						userNick: 'yjyyyyy',
-						content: this.replyContent,
-						fabulousCount: 0,
-					})
-				} else if (this.replyType == 'first') {
-					this.currentComment.list[this.replyParentIndex].children.push({
-						userHead: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fup.enterdesk.com%2Fedpic%2F5e%2F4e%2Ff0%2F5e4ef0e451852e0114d75eac14f60924.jpeg&refer=http%3A%2F%2Fup.enterdesk.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1642669624&t=028d851350e18512dbf4bfe3a86cbfa4',
-						userNick: 'yjyyyyy',
-						content: this.replyContent,
-						fabulousCount: 0,
-						replyTo: this.replyObj.userNick
-					});
-				} else {
-					this.currentComment.list[this.replyParentIndex].children.push({
-						userHead: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fup.enterdesk.com%2Fedpic%2F5e%2F4e%2Ff0%2F5e4ef0e451852e0114d75eac14f60924.jpeg&refer=http%3A%2F%2Fup.enterdesk.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1642669624&t=028d851350e18512dbf4bfe3a86cbfa4',
-						userNick: 'yjyyyyy',
-						content: this.replyContent,
-						fabulousCount: 0,
-						replyTo: this.replyObj.userNick
-					});
-				}
-				this.replyContent = '';
-			},
-			// 收起键盘
-			commentBlur() {
-				this.commentPlaceholder = `说点好听的~`;
-				this.showInput = false;
-				this.replyType = 'video';
-				this.replyObj = this.currentVideo;
-			}
-		}
-	}
-</script>
-
-<style lang="scss" scoped>
-	@import '../../static/css/font.css';
-
-	.color-red {
-		color: #f73b3b;
-	}
-
-	.inline-block {
-		display: inline-block;
-		vertical-align: middle;
-	}
-
-	// 喜欢按钮动画
-	.iconxihuan,
-	.icon-follow {
-		transition: all .3s;
-	}
-
-	.iconxihuan:active,
-	.icon-follow:active {
-		transform: scale(1.5);
-	}
-
-	@keyframes double-fabulous {
-		from {
-			opacity: 1;
-			transform: scale(1);
-		}
-
-		to {
-			opacity: 0;
-			transform: scale(3);
-		}
-	}
-
-	// 双击点赞样式
-	.fabulous-item {
-		position: absolute;
-		z-index: 99999;
-		width: 100rpx;
-		height: 100rpx;
-		color: #f73b3b;
-		font-size: 100rpx;
-		// animation: double-fabulous 5s;
-		transform-origin: 50% 100%;
-		transition: opacity .8s, transform .8s;
-		opacity: 0.8;
-	}
-
-	// 评论框
-	.commont-box {
-		position: fixed;
-		z-index: -1;
-		left: 0;
-		bottom: 0;
-		width: 100%;
-		height: 60%;
-		overflow-y: auto;
-		background-color: #222;
-		border-top-left-radius: 20rpx;
-		border-top-right-radius: 20rpx;
-		transition: all .3s;
-		transform: translateY(100%);
-		display: flex;
-		flex-direction: column;
-
-		&.active {
-			z-index: 9;
-			transform: translateY(0);
-		}
-
-		.commont-title {
-			text-align: center;
-			color: white;
-			font-size: 24rpx;
-			margin: 20rpx 0;
-			font-weight: bold;
-		}
-
-		.commont-list {
-			flex: 1;
-			overflow-y: auto;
-
-			.comment-panel {
-				margin: 30rpx 40rpx;
-				display: flex;
-
-				.first-user {
-					width: 50rpx;
-					height: 50rpx;
-					border-radius: 100%;
-				}
-
-				.first-comment {
-					flex: 1;
-					margin: 0rpx 20rpx;
-
-					.comment-name {
-						font-size: 24rpx;
-						font-weight: bold;
-						color: #999;
-					}
-
-					.comment-content {
-						color: white;
-						font-size: 26rpx;
-						margin-top: 10rpx;
-					}
-
-					.time-box {
-						margin-top: 10rpx;
-						font-size: 24rpx;
-						color: #999;
-
-						.reply-btn {
-							margin-left: 20rpx;
-						}
-					}
-				}
-
-				.fabulous-box {
-					text-align: center;
-					color: #666;
-
-					.fabulous-btn {
-						font-size: 36rpx;
-						transition: color .3s;
-					}
-
-					.fabulous-text {
-						font-size: 24rpx;
-						color: #999;
-					}
-				}
-			}
-		}
-
-		.comment-input {
-			display: block;
-			margin: 10px auto;
-			box-sizing: border-box;
-			width: 90%;
-			height: 70rpx;
-			padding: 0 20px;
-			border-radius: 60rpx;
-			background-color: #4a4a4a;
-			color: white;
-		}
-	}
-
-	// 全局容器
-	.widget-video {
-		width: 100%;
-		height: 100%;
-		overflow: hidden;
-		position: relative;
-
-		.scroll-video-box {
-			min-height: 100%;
-			position: relative;
-
-			.empty-txt {
-				position: absolute;
-				left: 50%;
-				top: 50%;
-				transform: translate(-50%, -50%);
-			}
-		}
-
-
-		.refresh-box {
-			position: absolute;
-			top: 0;
-			left: 0;
-			width: 100%;
-			height: 50px;
-			display: flex;
-			justify-content: center;
-			align-items: center;
-		}
-
-		.load-more-box {
-			position: absolute;
-			bottom: 0;
-			left: 0;
-			width: 100%;
-			height: 50px;
-			display: flex;
-			justify-content: center;
-			align-items: center;
-		}
-
-		// 视频容器
-		.video-item-box {
-			position: relative;
-
-			.btn-play {
-				font-size: 80rpx;
-				color: white;
-				position: absolute;
-				top: 50%;
-				left: 50%;
-				transition: all .3s;
-				transform: translateX(-50%) translateY(-50%) scale(1.5);
-				z-index: 8;
-				opacity: 0;
-
-				&.show {
-					opacity: 0.5;
-					transform: translateX(-50%) translateY(-50%) scale(1);
-
-				}
-			}
-
-			.fullscreen-video {
-				width: 100%;
-				height: 100%;
-				position: relative;
-			}
-
-			.video-info {
-				width: 100rpx;
-				position: absolute;
-				right: 20rpx;
-				bottom: 100rpx;
-				display: flex;
-				flex-direction: column;
-				justify-content: center;
-				align-items: center;
-
-				.atavar-box {
-					background-color: white;
-					padding: 6rpx;
-					border-radius: 100%;
-					width: 100rpx;
-					height: 100rpx;
-					margin-bottom: 60rpx;
-					position: relative;
-
-					.atavar-img {
-						width: 100%;
-						display: block;
-						border-radius: 100%;
-					}
-
-					.add-follow-btn {
-						width: 40rpx;
-						height: 40rpx;
-						padding: 4rpx;
-						border-radius: 100%;
-						color: white;
-						background-color: #f73b3b;
-						position: absolute;
-						bottom: -24rpx;
-						left: 50%;
-						transform: translateX(-50%);
-						font-weight: bold;
-						text-align: center;
-						line-height: 32rpx;
-
-						.iconjia1 {
-							font-size: 26rpx;
-						}
-					}
-				}
-
-				.icon-box {
-					width: 100rpx;
-					height: 100rpx;
-					margin-top: 30rpx;
-					display: flex;
-					align-items: center;
-					justify-content: space-around;
-					flex-direction: column;
-					color: white;
-
-					.icon-btn {
-						font-size: 60rpx;
-					}
-
-					.count-text {
-						font-size: 24rpx;
-					}
-				}
-
-			}
-
-			.video-title {
-				position: absolute;
-				left: 20rpx;
-				bottom: 20rpx;
-				width: calc(100% - 160rpx);
-				color: white;
-				z-index: 1;
-
-				.user-name {
-					font-weight: bold;
-				}
-
-				.video-content {
-					font-size: 24rpx;
-				}
-			}
-		}
-	}
-</style>

+ 0 - 68
src/package.json

@@ -1,68 +0,0 @@
-{
-    "id": "y-video-slide",
-    "displayName": "模仿抖音视频滑动组件",
-    "version": "1.1.1",
-    "description": "模仿抖音视频滑动组件",
-    "keywords": [
-        "视频",
-        "滑动",
-        "抖音",
-        "点赞",
-        "评论"
-    ],
-    "repository": "",
-    "engines": {
-        "HBuilderX": "^3.1.0"
-    },
-    "dcloudext": {
-        "category": [
-            "前端组件",
-            "通用组件"
-        ]
-    },
-    "uni_modules": {
-        "dependencies": [],
-        "encrypt": [],
-        "platforms": {
-            "cloud": {
-                "tcb": "y",
-                "aliyun": "y"
-            },
-            "client": {
-                "Vue": {
-                    "vue2": "y",
-                    "vue3": "y"
-                },
-                "App": {
-                    "app-vue": "y",
-                    "app-nvue": "y"
-                },
-                "H5-mobile": {
-                    "Safari": "y",
-                    "Android Browser": "y",
-                    "微信浏览器(Android)": "y",
-                    "QQ浏览器(Android)": "y"
-                },
-                "H5-pc": {
-                    "Chrome": "y",
-                    "IE": "y",
-                    "Edge": "y",
-                    "Firefox": "y",
-                    "Safari": "y"
-                },
-                "小程序": {
-                    "微信": "y",
-                    "阿里": "y",
-                    "百度": "y",
-                    "字节跳动": "y",
-                    "QQ": "y"
-                },
-                "快应用": {
-                    "华为": "y",
-                    "联盟": "y"
-                }
-            }
-        }
-    },
-    "name": "模仿抖音短视频滑动组件(支持H5、微信小程序)"
-}

+ 26 - 10
src/pages.json

@@ -32,6 +32,13 @@
       }
     },
     {
+      "path": "pages/travel/calendar",
+      "style": {
+        "navigationBarTitleText": "节庆日历",
+        "navigationStyle": "custom"
+      }
+    },
+    {
       "path": "pages/discover",
       "style": {
         "navigationBarTitleText": "闽南文化生态保护-发现",
@@ -48,47 +55,56 @@
     {
       "path": "pages/inhert/artifact/list",
       "style": {
-        "navigationBarTitleText": "文物",
+        "navigationBarTitleText": "文物列表",
         "navigationStyle": "custom"
       }
     },
     {
       "path": "pages/inhert/artifact/details",
       "style": {
-        "navigationBarTitleText": "文物"
+        "navigationBarTitleText": "文物详情"
+      }
+    },
+    {
+      "path": "pages/inhert/intangible/list",
+      "style": {
+        "navigationBarTitleText": "非遗列表"
+      }
+    },
+    {
+      "path": "pages/inhert/intangible/details",
+      "style": {
+        "navigationBarTitleText": "非遗详情"
       }
     },
     {
       "path": "pages/inhert/inheritor/list",
       "style": {
-        "navigationBarTitleText": "人物列表"
+        "navigationBarTitleText": "传承人列表"
       }
     },
     {
       "path": "pages/inhert/inheritor/details",
       "style": {
-        "navigationBarTitleText": "人物详情"
+        "navigationBarTitleText": "传承人详情"
       }
     },
     {
       "path": "pages/article/common/list",
       "style": {
-        "navigationBarTitleText": "通用列表页",
-        "navigationStyle": "custom"
+        "navigationBarTitleText": "通用列表页"
       }
     },
     {
       "path": "pages/article/details",
       "style": {
-        "navigationBarTitleText": "新闻详情",
-        "navigationStyle": "custom"
+        "navigationBarTitleText": "新闻详情"
       }
     },
     {
       "path": "pages/article/list",
       "style": {
-        "navigationBarTitleText": "文章列表页",
-        "navigationStyle": "custom"
+        "navigationBarTitleText": "文章列表页"
       }
     },
     {

+ 47 - 0
src/pages/article/common/CommonContent.ts

@@ -0,0 +1,47 @@
+import CommonContent, { GetContentListParams } from "@/api/CommonContent";
+import { useSimpleDataLoader } from "@/common/composeabe/SimpleDataLoader";
+import { navTo } from "@/common/utils/PageAction"
+
+/**
+ * 专用于通用内容的首页小列表控制代码组合
+ * @param p 
+ * @returns 
+ */
+export function useHomePageMiniCommonListGoMoreAndGoDetail(p: {
+  title?: string,
+  mainBodyColumnId?: number,
+  modelId?: number,
+  itemType?: string,
+  detailsPage: string,
+  count?: number,
+}) {
+  function goDetail(id: number) {
+    navTo(p.detailsPage, {
+      mainBodyColumnId: p.mainBodyColumnId,
+      modelId: p.modelId,
+      id,
+    }) 
+  }
+  function goList() {
+    navTo('/pages/article/common/list', {
+      title: p.title,
+      mainBodyColumnId: p.mainBodyColumnId,
+      modelId: p.modelId,
+      itemType: p.itemType,
+      detailsPage: p.detailsPage,
+    }) 
+  }
+
+  const loader = useSimpleDataLoader(async () => 
+    (await CommonContent.getContentList(new GetContentListParams().setSelfValues({
+      mainBodyColumnId: p.mainBodyColumnId,
+      modelId: p.modelId,
+    }), 1, p.count ?? 4)).list
+  );
+
+  return {
+    loader,
+    goDetail,
+    goList,
+  }
+}

+ 41 - 4
src/pages/article/common/CommonListPage.vue

@@ -1,10 +1,27 @@
 <template>
   <!-- 通用列表页 -->
-  <view class="d-flex flex-column bg-base">
+  <view class="common-list-page d-flex flex-column bg-base">
+    <u-tabs 
+      v-if="tabs"
+      :list="tabs" 
+      lineWidth="30"
+      lineColor="#d9492e"
+      :activeStyle="{
+        color: '#000',
+        fontWeight: 'bold',
+        transform: 'scale(1.05)'
+      }"
+      :inactiveStyle="{
+        color: '#606266',
+        transform: 'scale(1)'
+      }"
+      :scrollable="tabs && tabs.length > 5"
+      class="top-tab"
+      @click="(e: any) => tab = e.id"
+    />
     <!-- 搜索 -->
     <view v-if="showSearch" class="d-flex flex-col p-2">
       <uni-search-bar 
-        
         v-model="searchValue"
         radius="100" 
         bgColor="#fff" 
@@ -72,7 +89,7 @@
 </template>
 
 <script setup lang="ts">
-import { onMounted, ref, type PropType } from 'vue';
+import { onMounted, ref, watch, type PropType } from 'vue';
 import { useSimplePageListLoader } from '@/common/composeabe/SimplePageListLoader';
 import { navTo } from '@/common/utils/PageAction';
 import SimplePageListLoader from '@/common/components/SimplePageListLoader.vue';
@@ -99,6 +116,13 @@ const props = defineProps({
     default: '通用列表页',
   },
   /**
+   * 分组标签
+   */
+  tabs: {
+    type: Array as PropType<{ id: number, name: string }[]>,
+    default: null,
+  },
+  /**
    * 是否显示搜索框
    */
   showSearch: {
@@ -139,6 +163,7 @@ const props = defineProps({
       pageSize: number,
       searchText: string,
       dropDownValues: number[],
+      tabSelect: number,
     ) => Promise<CommonListItem[]>>,
     required: true,
   },
@@ -164,7 +189,9 @@ const listLoader = useSimplePageListLoader(props.pageSize, async (page, pageSize
   page, pageSize, 
   searchValue.value,
   dropDownValues.value,
+  tab.value,
 ));
+const tab = ref(0)
 
 function handleChangeDropDownValue(index: number, value: number) {
   dropDownValues.value[index] = value;
@@ -180,10 +207,20 @@ function goDetails(id: number) {
   })
 }
 
+watch(tab, () => {
+  listLoader.loadData(undefined, true);
+});
+
 onMounted(() => {
   uni.setNavigationBarTitle({
     title: props.title,
   })
   listLoader.loadData(undefined, true);
 });
-</script>
+</script>
+
+<style lang="scss">
+.common-list-page {
+  min-height: 100vh; 
+}
+</style>

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

@@ -1,8 +1,13 @@
 <template>
   <CommonListPage 
+    :title="querys.title || undefined"
     :load="loadData"
     :itemType="querys.itemType as any || undefined"
     :detailsPage="querys.detailsPage || undefined"
+    :detailsParams="{
+      mainBodyColumnId: querys.mainBodyColumnId || undefined,
+      modelId: querys.modelId || undefined,
+    }"
   />
 </template>
 
@@ -16,6 +21,7 @@ const { querys } = useLoadQuerys({
   modelId: 0,
   itemType: '',
   detailsPage: '',
+  title: '',
 });
 
 async function loadData(

+ 1 - 1
src/pages/article/details.vue

@@ -1,6 +1,5 @@
 <template>
   <view class="main">
-    <u-navbar title="文物" autoBack placeholder bgColor="transparent" />
     <SimplePageContentLoader :loader="loader">
       <template v-if="loader.content.value">
         <view class="article">
@@ -36,6 +35,7 @@ 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 SimplePageContentLoader from "@/common/components/SimplePageContentLoader.vue";
 
 const loader = useSimplePageContentLoader<
   GetContentDetailItem, 

+ 0 - 1
src/pages/article/list.vue

@@ -1,6 +1,5 @@
 <template>
   <view class="article_list">
-    <u-navbar title="文物" autoBack placeholder bgColor="transparent" />
     <view class="search">
       <uni-search-bar 
         v-model="searchText"

+ 162 - 93
src/pages/discover.vue

@@ -14,6 +14,7 @@
           v-for="(item, i) in categories" 
           :key="i"
           class="d-flex flex-col align-center"
+          @click="item.onClick"
         >
           <image :src="item.icon" class="width-100 height-100" />
           <text class="width-130 text-align-center mt-2 color-primary size-s">{{ item.name }}</text>
@@ -27,63 +28,73 @@
       <Box2LinePlayRightArrow 
         title="听语音猜词语"
         desc="每日更新,赢取积分"
+        @click="navTo('/pages/answer/words/index')"
       />
 
       <!-- 文化挑战 -->
       <HomeTitle title="文化挑战" />
+      <!-- 
+      方言配音大赛隐藏
       <Box2LineRightSlot 
         title="方言配音大赛"
         desc="参与人数:1,234"
+        @click="navTo('/pages/answer/index')"
       >
         <image class="width-60 height-60 radius-base" src="/static/images/discover/IconCup.png" mode="aspectFill" />
-      </Box2LineRightSlot>
+      </Box2LineRightSlot> -->
       <Box2LineRightSlot
         title="闽南知识问答"
         desc="可获积分:500"
       >
         <view class="width-1-5">
-          <u-button shape="circle" type="primary">立即报名</u-button>
+          <u-button shape="circle" type="primary" @click="navTo('/pages/answer/index')">立即报名</u-button>
         </view>
       </Box2LineRightSlot>
 
       <!-- 文化社区 -->
       <HomeTitle title="文化社区" />
       
-      <view class="d-flex w-100 flex-row flex-wrap align-center justify-between">
-        <Box2LineLargeImageUserShadow 
-          v-for="(item, i) in communityData"
-          :key="i"
-          :title="item.title"
-          :desc="item.desc"
-          :image="item.image"
-          :userName="item.userName"
-          :userHead="item.userHead"
-          :likes="item.likes"
-          :comment="item.comment"
-        />
-      </view>
+      <SimplePageContentLoader :loader="communityData">
+        <view class="d-flex w-100 flex-row flex-wrap align-center justify-between">
+          <Box2LineLargeImageUserShadow 
+            v-for="(item, i) in communityData.content.value"
+            :key="i"
+            :title="item.title"
+            :desc="item.desc"
+            :image="item.image"
+            :userName="item.userName"
+            :userHead="item.userHead"
+            :likes="item.likes"
+            :comment="item.comment"
+          />
+        </view>
+      </SimplePageContentLoader>
 
       <!-- 老照片 -->
       <HomeTitle title="老照片" showMore />
-      <scroll-view scroll-x>
-        <view class="d-flex flex-row">
-          <view v-for="(item, i) in imagesData" :key="i" class="mr-2">
-            <image class="width-300 radius-base" :src="item.image" mode="widthFix" />
+      <SimplePageContentLoader :loader="imagesData">
+        <scroll-view scroll-x>
+          <view class="d-flex flex-row">
+            <view v-for="(item, i) in imagesData.content.value" :key="i" class="mr-2">
+              <image class="width-300 radius-base" :src="item.image" mode="widthFix" />
+            </view>
           </view>
-        </view>
-      </scroll-view>
+        </scroll-view>
+      </SimplePageContentLoader>
 
       <!-- 热门话题 -->
-      <HomeTitle title="热门话题" />
-      <view class="d-flex flex-col">
-        <Box2LineRightShadow 
-          v-for="(item, i) in topicsData" 
-          :key="i" 
-          :title="item.title"
-          :desc="item.desc"
-          :right="item.right"
-        />
-      </view>
+      <!-- <HomeTitle title="热门话题" />
+      <SimplePageContentLoader :loader="topicsData">
+        <view class="d-flex flex-col">
+          <Box2LineRightShadow 
+            v-for="(item, i) in topicsData.content.value" 
+            :key="i" 
+            :title="item.title"
+            :desc="item.desc"
+            :right="item.right"
+          />
+        </view>
+      </SimplePageContentLoader> -->
 
     </view>
   </view> 
@@ -107,79 +118,137 @@ import Box2LinePlayRightArrow from './parts/Box2LinePlayRightArrow.vue';
 import Box2LineRightSlot from './parts/Box2LineRightSlot.vue';
 import Box2LineLargeImageUserShadow from './parts/Box2LineLargeImageUserShadow.vue';
 import HomeTitle from './parts/HomeTitle.vue';
+import { navTo } from '@/common/utils/PageAction';
+import { useSimpleDataLoader } from '@/common/composeabe/SimpleDataLoader';
+import SimplePageContentLoader from '@/common/components/SimplePageContentLoader.vue';
 
 const categories = [
-  { name: '民俗文化', icon: CategoryIcon1 },
-  { name: '建筑遗产', icon: CategoryIcon2 },
-  { name: '戏曲艺术', icon: CategoryIcon3 },
-  { name: '闽南美食', icon: CategoryIcon4 },
-  { name: '宗教信仰', icon: CategoryIcon5 },
-]
-const communityData = [
   { 
-    title: '茶艺传承作坊', 
-    desc: '',
-    image: ImageTest4,
-    likes: 123,
-    comment: 66,
-    userHead: UserHead,
-    userName: 'Regular',
+    name: '民俗文化', 
+    icon: CategoryIcon1  , 
+    onClick: () => navTo('/pages/article/common/list', {
+      title: '民俗文化',
+      mainBodyColumnId: 0,
+      modelId: 0,
+      itemType: 'article-common',
+      detailsPage: '/pages/article/details',
+    }) 
   },
   { 
-    title: '茶艺传承作坊', 
-    desc: '', 
-    image: ImageTest2,
-    likes: 123,
-    comment: 66,
-    userHead: UserHead,
-    userName: 'Regular',
+    name: '建筑遗产', 
+    icon: CategoryIcon2  , 
+    onClick: () => navTo('/pages/article/common/list', {
+      title: '建筑遗产',
+      mainBodyColumnId: 0,
+      modelId: 0,
+      itemType: 'article-common',
+      detailsPage: '/pages/article/details',
+    }) 
   },
   { 
-    title: '茶艺传承作坊',  
-    desc: '',
-    image: ImageTest3,
-    likes: 123,
-    comment: 66,
-    userHead: UserHead,
-    userName: 'Regular',
+    name: '戏曲艺术', 
+    icon: CategoryIcon3  , 
+    onClick: () => navTo('/pages/article/common/list', {
+      title: '戏曲艺术',
+      mainBodyColumnId: 0,
+      modelId: 0,
+      itemType: 'article-common',
+      detailsPage: '/pages/article/details',
+    }) 
   },
   { 
-    title: '茶艺传承作坊',  
-    desc: '',
-    image: ImageTest5,
-    likes: 123,
-    comment: 66,
-    userHead: UserHead,
-    userName: 'Regular',
+    name: '闽南美食', 
+    icon: CategoryIcon4 , 
+    onClick: () => navTo('/pages/article/common/list', {
+      title: '闽南美食',
+      mainBodyColumnId: 0,
+      modelId: 0,
+      itemType: 'article-common',
+      detailsPage: '/pages/article/details',
+    })  
   },
-]
-const imagesData = [
-  {
-    image: ImageTest2,
-  },
-  {
-    image: ImageTest3, 
-  },
-  {
-    image: ImageTest4,
-  },
-  {
-    image: ImageTest5,  
-  }
-]
-const topicsData = [
-  {
-    title: '宗族文化探讨',
-    desc: '关于闽南宗教的传承与发展',
-    right: '234 人参与讨论', 
-  },
-  {
-    title: '宗族文化探讨',
-    desc: '关于闽南宗教的传承与发展',
-    right: '234 人参与讨论', 
+  { 
+    name: '宗教信仰', 
+    icon: CategoryIcon5  , 
+    onClick: () => navTo('/pages/article/common/list', {
+      title: '宗教信仰',
+      mainBodyColumnId: 0,
+      modelId: 0,
+      itemType: 'article-common',
+      detailsPage: '/pages/article/details',
+    }) 
   },
-]
-
+];
+const communityData = useSimpleDataLoader(async () => {
+  return [
+    { 
+      title: '茶艺传承作坊', 
+      desc: '',
+      image: ImageTest4,
+      likes: 123,
+      comment: 66,
+      userHead: UserHead,
+      userName: 'Regular',
+    },
+    { 
+      title: '茶艺传承作坊', 
+      desc: '', 
+      image: ImageTest2,
+      likes: 123,
+      comment: 66,
+      userHead: UserHead,
+      userName: 'Regular',
+    },
+    { 
+      title: '茶艺传承作坊',  
+      desc: '',
+      image: ImageTest3,
+      likes: 123,
+      comment: 66,
+      userHead: UserHead,
+      userName: 'Regular',
+    },
+    { 
+      title: '茶艺传承作坊',  
+      desc: '',
+      image: ImageTest5,
+      likes: 123,
+      comment: 66,
+      userHead: UserHead,
+      userName: 'Regular',
+    },
+  ]
+});
+const imagesData = useSimpleDataLoader(async () => {
+  return [
+    {
+      image: ImageTest2,
+    },
+    {
+      image: ImageTest3, 
+    },
+    {
+      image: ImageTest4,
+    },
+    {
+      image: ImageTest5,  
+    }
+  ]
+});
+const topicsData = useSimpleDataLoader(async () => {
+  return [
+    {
+      title: '宗族文化探讨',
+      desc: '关于闽南宗教的传承与发展',
+      right: '234 人参与讨论', 
+    },
+    {
+      title: '宗族文化探讨',
+      desc: '关于闽南宗教的传承与发展',
+      right: '234 人参与讨论', 
+    },
+  ]
+});
 </script>
 
 <style lang="scss">

+ 151 - 59
src/pages/home.vue

@@ -37,6 +37,7 @@
             v-for="(tab, k) in subTabs2" 
             :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>
@@ -44,7 +45,7 @@
         </view>
       </view>
 
-      <!-- 文化地图 -->
+      <!-- 文化地图
       <HomeTitle title="文化地图" />
       <view class="position-relative radius-l overflow-hidden">
         <map 
@@ -64,58 +65,65 @@
             传习所
           </view>
         </view>
-      </view>
+      </view> -->
 
       <!-- 近期活动 -->
       <HomeTitle title="近期活动" />
-      <view class="d-flex flex-col shadow-l radius-l bg-base p-3">
-        <image 
-          class="w-100 radius-base"
-          src="/static/images/home/ImageTest.jpg"
-          mode="widthFix"
-        />
-        <view class="d-flex flex-row justify-between mt-3">
-          <text class="color-primary size-l">茶艺传承工坊</text>
-          <text class="color-primary">剩余名额:8</text>
-        </view>
-        <view class="d-flex flex-row justify-between align-center mt-3">
-          <view class="d-flex flex-one flex-col">
-            <view class="d-flex flex-row align-center">
-              <image :src="IconLocation" class="width-30 height-30 mr-3" />
-              <text class="color-second size-l">湖里创新园</text>
-            </view>
-            <text class="color-second">
-              <text class="iconfont icon-time mr-2" />
-              2025年06月16日 12:00
-            </text>
-          </view>
-          <view class="width-1-5">
-            <u-button shape="circle" type="primary">立即报名</u-button>
-          </view>
-        </view>
-      </view>
-
-      <!-- 精彩推荐 -->
-      <HomeTitle title="精彩推荐" />
-      <view class="d-flex flex-row justify-between flex-wrap">
+      <SimplePageContentLoader :loader="activityLoader">
         <view 
-          v-for="(tab, k) in recommend"
+          class="d-flex flex-col shadow-l radius-l bg-base p-3"
+          v-for="(item, k) in activityLoader.content.value"
           :key="k"
-          class="grid4-item position-relative mb-3"
         >
-          <text 
-            class="tag bg-mask-white color-primary radius-l p-2 position-absolute size-s"
-          >
-            {{ tab.name }}
-          </text> 
-          <image
+          <image 
             class="w-100 radius-base"
-            :src="tab.icon"
+            :src="item.image"
             mode="widthFix"
           />
+          <view class="d-flex flex-row justify-between mt-3">
+            <text class="color-primary size-l">{{ item.title }}</text>
+            <text class="color-primary">剩余名额:{{item.count}}</text>
+          </view>
+          <view class="d-flex flex-row justify-between align-center mt-3">
+            <view class="d-flex flex-one flex-col">
+              <view class="d-flex flex-row align-center">
+                <image :src="IconLocation" class="width-30 height-30 mr-3" />
+                <text class="color-second size-l">{{ item.location }}</text>
+              </view>
+              <text class="color-second">
+                <text class="iconfont icon-time mr-2" />
+                {{ item.time }}
+              </text>
+            </view>
+            <view class="width-1-5">
+              <u-button shape="circle" type="primary">立即报名</u-button>
+            </view>
+          </view>
         </view>
-      </view>
+      </SimplePageContentLoader>
 
+      <!-- 精彩推荐 -->
+      <HomeTitle title="精彩推荐" />
+      <SimplePageContentLoader :loader="recommendLoader">
+        <view class="d-flex flex-row justify-between flex-wrap">
+          <view 
+            v-for="(tab, k) in recommendLoader.content.value"
+            :key="k"
+            class="grid4-item position-relative mb-3"
+          >
+            <text 
+              class="tag bg-mask-white color-primary radius-l p-2 position-absolute size-s"
+            >
+              {{ tab.title }}
+            </text> 
+            <image
+              class="w-100 radius-base"
+              :src="tab.image"
+              mode="widthFix"
+            />
+          </view>
+        </view>
+      </SimplePageContentLoader>
     </view>
   </view>
   <tabbar :current="0"></tabbar>
@@ -131,33 +139,117 @@ import MainBoxIcon5 from '/static/images/home/MainBoxIcon5.png';
 import MainBoxIcon6 from '/static/images/home/MainBoxIcon6.png';
 import MainBoxIcon7 from '/static/images/home/MainBoxIcon7.png';
 import MainBoxIcon8 from '/static/images/home/MainBoxIcon8.png';
-import ImageTest2 from '/static/images/home/ImageTest2.jpg';
-import ImageTest3 from '/static/images/home/ImageTest3.jpg';
-import ImageTest4 from '/static/images/home/ImageTest4.jpg';
-import ImageTest5 from '/static/images/home/ImageTest5.jpg';
+import ImageTest  from '/static/images/home/ImageTest.jpg';
 import HomeTitle from '@/pages/parts/HomeTitle.vue'; 
 import IconLocation from '/static/images/inhert/IconLocation.png';
 import Box1AudioPlay from '@/pages/parts/Box1AudioPlay.vue';
+import SimplePageContentLoader from "@/common/components/SimplePageContentLoader.vue";
 import { navTo } from '@/common/utils/PageAction';
+import { useSimpleDataLoader } from '@/common/composeabe/SimpleDataLoader';
+import CommonContent, { GetContentListParams } from '@/api/CommonContent';
 
 const subTabs1 = [
-  { name: '闽南语', icon: MainBoxIcon1 },
-  { name: '古早味', icon: MainBoxIcon2 },
+  { 
+    name: '闽南语', 
+    icon: MainBoxIcon1, 
+    onClick: () => navTo('/pages/article/common/list', {
+      title: '闽南语',
+      mainBodyColumnId: 0,
+      modelId: 0,
+      itemType: 'article-common',
+      detailsPage: '/pages/video/details',
+    }) 
+  },
+  { 
+    name: '古早味', 
+    icon: MainBoxIcon2, 
+    onClick: () => navTo('/pages/article/common/list', {
+      title: '古早味',
+      mainBodyColumnId: 0,
+      modelId: 0,
+      itemType: 'article-common',
+      detailsPage: '/pages/article/details',
+    }) 
+  },
   { name: '先贤列传', icon: MainBoxIcon3, onClick: () => navTo('/pages/introduction/character') },
-  { name: '民俗活动', icon: MainBoxIcon4 },
+  { 
+    name: '民俗活动', 
+    icon: MainBoxIcon4, 
+    onClick: () => navTo('/pages/article/common/list', {
+      title: '民俗活动', 
+      mainBodyColumnId: 0,
+      modelId: 0,
+      itemType: 'article-common',
+      detailsPage: '/pages/article/details',
+    }) 
+  },
 ]
 const subTabs2 = [
-  { name: '红砖厝韵', icon: MainBoxIcon5 },
-  { name: '薪传匠艺', icon: MainBoxIcon6 },
-  { name: '工夫茶道', icon: MainBoxIcon7 },
-  { name: '闽南魂', icon: MainBoxIcon8 },
-]
-const recommend = [
-  { name: '非遗', icon: ImageTest2 },
-  { name: '文物', icon: ImageTest3 },
-  { name: '民俗', icon: ImageTest4 }, 
-  { name: '文物', icon: ImageTest5 },
+  { 
+    name: '红砖厝韵', 
+    icon: MainBoxIcon5 , 
+    onClick: () => navTo('/pages/article/common/list', {
+      title: '红砖厝韵',
+      mainBodyColumnId: 0,
+      modelId: 0,
+      itemType: 'article-common',
+      detailsPage: '/pages/article/details',
+    }) 
+  },
+  { 
+    name: '薪传匠艺', 
+    icon: MainBoxIcon6 , 
+    onClick: () => navTo('/pages/article/common/list', {
+      title: '薪传匠艺',
+      mainBodyColumnId: 0,
+      modelId: 0,
+      itemType: 'article-common',
+      detailsPage: '/pages/article/details',
+    }) 
+  },
+  { 
+    name: '工夫茶道', 
+    icon: MainBoxIcon7 , 
+    onClick: () => navTo('/pages/article/common/list', {
+      title: '工夫茶道',
+      mainBodyColumnId: 0,
+      modelId: 0,
+      itemType: 'article-common',
+      detailsPage: '/pages/article/details',
+    }) 
+  },
+  { 
+    name: '文化地图', 
+    icon: MainBoxIcon8 , 
+    onClick: () => navTo('/pages/article/common/list', {
+      title: '文化地图',
+      mainBodyColumnId: 0,
+      modelId: 0,
+      itemType: 'article-common',
+      detailsPage: '/pages/article/details',
+    }) 
+  },
 ]
+
+const activityLoader = useSimpleDataLoader(async () => {
+  //TODO: 活动接口
+  return [
+    {
+      title: '茶艺传承工坊',
+      image: ImageTest,
+      count: 8,
+      content: '这是一个活动的内容',
+      time: '2025年06月16日 12:00',
+      location: '湖里创新园',
+      link: '/pages/article/details',
+    }
+  ]
+})
+const recommendLoader = useSimpleDataLoader(async () => {
+  return (await CommonContent.getContentList(new GetContentListParams().setSelfValues({
+    flag: 'recommend',
+  }), 1, 6)).list
+});
 </script>
 
 <style lang="scss">

+ 1 - 1
src/pages/home/introduction.vue

@@ -37,7 +37,7 @@ const introdData = useSimpleDataLoader(async () => {
   return (await NewsIndexContent.getColumList(new GetContentListParams().setSelfValues({
     modelId: 3,
     mainBodyColumnId: 234,
-  }))).list[0]?.overview
+  }))).list[0]?.overview || '无内容!请添加内容!!';
 }, true);
 
 </script>

+ 168 - 170
src/pages/inhert.vue

@@ -28,7 +28,7 @@
       </SimplePageContentLoader>
 
       <!-- 非遗 -->
-      <HomeTitle title="非遗" showMore inWing />
+      <HomeTitle title="非遗" showMore inWing @clickMore="navTo('inhert/intangible/list')" />
       <SimplePageContentLoader :loader="intangibleData" >
         <scroll-view scroll-x>
           <view class="padding-wing-l pb-3 pt-3 d-flex flex-row overflow-visible align-stretch">
@@ -42,98 +42,111 @@
               :image="item.image"
               :bottomLocate="item.bottomLocate"
               :bottomScore="item.bottomScore"
+              @click="navTo('inhert/intangible/details', { id: item.id })"
             />
           </view>
         </scroll-view>
       </SimplePageContentLoader>
 
       <!-- 闽南语在线课程 -->
-      <HomeTitle title="闽南语在线课程" showMore inWing />
-      <scroll-view scroll-x>
-        <view class="padding-wing-l pb-3 pt-3 d-flex flex-row overflow-visible align-stretch">
-          <Box2LineLargeImageUserShadow
-            v-for="(item, i) in corseData"
-            classNames="width-2-3 mr-2"
-            titleColor="title-text"
-            :key="i"
-            :title="item.title"
-            :desc="item.desc"
-            :image="item.image"
-            :videoMark="true"
-          />
-        </view>
-      </scroll-view>
+      <HomeTitle title="闽南语在线课程" showMore inWing @clickMore="goCourseList" />
+      <SimplePageContentLoader :loader="corseData" >
+        <scroll-view scroll-x>
+          <view class="padding-wing-l pb-3 pt-3 d-flex flex-row overflow-visible align-stretch">
+            <Box2LineLargeImageUserShadow
+              v-for="(item, i) in corseData.content.value"
+              classNames="width-2-3 mr-2"
+              titleColor="title-text"
+              :key="i"
+              :title="item.title"
+              :desc="item.desc"
+              :image="item.image"
+              :videoMark="true"
+              @click="goCourseDetail(item.id)"
+            />
+          </view>
+        </scroll-view>
+      </SimplePageContentLoader>
 
       <view class="d-flex flex-col wing-l">
         <!-- 闽南语原创歌曲 -->
-        <HomeTitle title="闽南语原创歌曲" showMore />
-        <Box1AudioPlay class="w-100 mt-3" title="里厚吖:你好呀" />
-        <Box1AudioPlay class="w-100 mt-3" title="里厚吖:你好呀" />
+        <HomeTitle title="闽南语原创歌曲" showMore @clickMore="goSongsList" />
 
-        <!-- 方言故事音频库 -->
-        <HomeTitle title="方言故事音频库" showMore />
-        <Box2LinePlayRightArrow 
-          title="方言故事"
-          desc="简介简介简介"
-        />
-        <Box2LinePlayRightArrow 
-          title="方言故事"
-          desc="简介简介简介"
-        />
+        <SimplePageContentLoader :loader="songsData" >
+          <Box1AudioPlay 
+            v-for="s in songsData.content.value" 
+            :key="s.id"
+            :title="s.title" 
+            class="w-100 mt-3" 
+            @click="goSongsDetail(s.id)"
+          />
+        </SimplePageContentLoader>
 
-        <!-- 热门话题 -->
-        <HomeTitle title="热门话题" showMore />
-        <view class="d-flex flex-row flex-wrap column-gap-ss">
-          <Box2LinePlayRightArrow style="width:calc(50% - 20rpx)" title="市井声" />
-          <Box2LinePlayRightArrow style="width:calc(50% - 20rpx)" title="叫卖声" />
-          <Box2LinePlayRightArrow style="width:calc(50% - 20rpx)" title="市井声" />
-          <Box2LinePlayRightArrow style="width:calc(50% - 20rpx)" title="叫卖声" />
-        </view>
+        <!-- 方言故事音频库 -->
+        <HomeTitle title="方言故事音频库" showMore @clickMore="goStoryList" />
+        <SimplePageContentLoader :loader="storyData" >
+          <Box2LinePlayRightArrow 
+            v-for="s in songsData.content.value" 
+            :key="s.id"
+            :title="s.title" 
+            :desc="s.desc"
+            @click="goStoryDetail(s.id)"
+          />
+        </SimplePageContentLoader>
       </view>
 
       <!-- 童趣记忆 -->
-      <HomeTitle title="童趣记忆" showMore inWing />
-      <scroll-view scroll-x>
-        <view class="padding-wing-l pb-3 pt-3 d-flex flex-row overflow-visible align-stretch">
-          <Box2LineLargeImageUserShadow
-            v-for="(item, i) in memoryData"
-            classNames="width-2-3 mr-2"
-            titleColor="title-text"
-            :key="i"
-            :title="item.title"
-            :desc="item.desc"
-            :image="item.image"
-          />
-        </view>
-      </scroll-view>
-      
+      <HomeTitle title="童趣记忆" showMore inWing @clickMore="goMemoryList" />
+      <SimplePageContentLoader :loader="memoryData" >
+        <scroll-view scroll-x>
+          <view class="padding-wing-l pb-3 pt-3 d-flex flex-row overflow-visible align-stretch">
+            <Box2LineLargeImageUserShadow
+              v-for="(item, i) in memoryData.content.value"
+              classNames="width-2-3 mr-2"
+              titleColor="title-text"
+              :key="i"
+              :title="item.title"
+              :desc="item.desc"
+              :image="item.image"
+              @click="goMemoryDetail(item.id)"
+            />
+          </view>
+        </scroll-view>
+      </SimplePageContentLoader>
+
       <!-- 老字号 -->
-      <HomeTitle title="老字号" showMore inWing />
-      <scroll-view scroll-x>
-        <view class="padding-wing-l pb-3 pt-3 d-flex flex-row overflow-visible align-stretch">
-          <Box2LineLargeImageUserShadow
-            v-for="(item, i) in oldData"
-            classNames="width-2-3 mr-2"
-            titleColor="title-text"
-            :key="i"
-            :title="item.title"
-            :desc="item.desc"
-            :image="item.image"
-            :bottomLocate="item.bottomLocate"
-            :bottomScore="item.bottomScore"
-          />
-        </view>
-      </scroll-view>
+      <HomeTitle title="老字号" showMore inWing @clickMore="goOldList" />
+      <SimplePageContentLoader :loader="oldData">
+        <scroll-view scroll-x>
+          <view class="padding-wing-l pb-3 pt-3 d-flex flex-row overflow-visible align-stretch">
+            <Box2LineLargeImageUserShadow
+              v-for="(item, i) in oldData.content.value"
+              classNames="width-2-3 mr-2"
+              titleColor="title-text"
+              :key="i"
+              :title="item.title"
+              :desc="item.desc"
+              :image="item.image"
+              :bottomLocate="'item.bottomLocate'"
+              :bottomScore="'item.bottomScore'"
+              @click="goOldDetail(item.id)"
+            />
+          </view>
+        </scroll-view>
+      </SimplePageContentLoader>
 
       <!-- 古早味知识百科 -->
       <view class="d-flex flex-col wing-l">
-        <HomeTitle title="古早味知识百科" showMore />
-        <Box2LineRightShadow
-          v-for="(item, i) in topicsData" 
-          :key="i" 
-          :title="item.title"
-          :desc="item.desc"
-        />
+        <HomeTitle title="古早味知识百科" showMore @clickMore="goTopicsList" />
+        <SimplePageContentLoader :loader="topicsData">
+          <Box2LineRightShadow
+            v-for="(item, i) in topicsData.content.value" 
+            :key="i" 
+            :title="item.title"
+            :desc="item.desc"
+            @click="goTopicsDetail(item.id)"
+          />
+        </SimplePageContentLoader>
       </view>
 
     </view>
@@ -142,23 +155,19 @@
 </template>
 
 <script setup lang="ts">
+import { navTo } from '@/common/utils/PageAction';
+import { useSimpleDataLoader } from '@/common/composeabe/SimpleDataLoader';
+import { GetContentListParams } from '@/api/CommonContent';
 import Tabbar from '@/common/components/tabs/tabbar.vue';
 import HomeTitle from './parts/HomeTitle.vue';
-import TestImage1 from '@/static/images/inhert/TestImage1.jpg';
-import TestImage2 from '@/static/images/inhert/TestImage2.jpg';
-import TestImage3 from '@/static/images/inhert/TestImage3.jpg';
-import TestImage4 from '@/static/images/inhert/TestImage4.jpg';
-import TestImage5 from '@/static/images/inhert/TestVideoImage.png';
 import Box2LineLargeImageUserShadow from './parts/Box2LineLargeImageUserShadow.vue';
 import Box2LinePlayRightArrow from './parts/Box2LinePlayRightArrow.vue';
 import Box1AudioPlay from './parts/Box1AudioPlay.vue';
 import Box2LineRightShadow from './parts/Box2LineRightShadow.vue';
-import { useSimpleDataLoader } from '@/common/composeabe/SimpleDataLoader';
-import UnmoveableContent from '@/api/inheritor/UnmoveableContent';
-import { GetContentListParams } from '@/api/CommonContent';
 import SimplePageContentLoader from '@/common/components/SimplePageContentLoader.vue';
 import ProjectsContent from '@/api/inheritor/ProjectsContent';
-import { navTo } from '@/common/utils/PageAction';
+import UnmoveableContent from '@/api/inheritor/UnmoveableContent';
+import { useHomePageMiniCommonListGoMoreAndGoDetail } from './article/common/CommonContent';
 
 const artifactData = useSimpleDataLoader(async () => 
   (await UnmoveableContent.getContentList(new GetContentListParams().setSelfValues({
@@ -172,7 +181,7 @@ const artifactData = useSimpleDataLoader(async () =>
     likes: p.likes,
     comment: p.comments,
   }))
-, true);
+);
 const intangibleData = useSimpleDataLoader(async () => 
   (await ProjectsContent.getContentList(new GetContentListParams().setSelfValues({
     type: GetContentListParams.TYPE_ARTICLE,
@@ -185,91 +194,80 @@ const intangibleData = useSimpleDataLoader(async () =>
     bottomLocate: p.area as string,
     bottomScore: '5.0',
   }))
-, true);
-const corseData = [
-  { 
-    title: '南安水头', 
-    desc: '千年古镇风情',
-    image: TestImage5,
-  },
-  { 
-    title: '南安水头', 
-    desc: '千年古镇风情',
-    image: TestImage5,
-  },
-  { 
-    title: '南安水头', 
-    desc: '千年古镇风情',
-    image: TestImage5,
-  },
-  { 
-    title: '南安水头', 
-    desc: '千年古镇风情',
-    image: TestImage5,
-  },
-]
-const memoryData = [
-  { 
-    title: '南安水头', 
-    desc: '千年古镇风情',
-    image: TestImage3,
-  },
-  { 
-    title: '南安水头', 
-    desc: '千年古镇风情',
-    image: TestImage4,
-  },
-  { 
-    title: '南安水头', 
-    desc: '千年古镇风情',
-    image: TestImage3,
-  },
-  { 
-    title: '南安水头', 
-    desc: '千年古镇风情',
-    image: TestImage4,
-  },
-]
-const oldData = [
-  { 
-    title: '南安水头', 
-    desc: '千年古镇风情',
-    bottomLocate: '泉州市',
-    bottomScore: '5.0',
-    image: TestImage3,
-  },
-  { 
-    title: '南安水头', 
-    desc: '千年古镇风情',
-    bottomLocate: '泉州市',
-    bottomScore: '5.0',
-    image: TestImage4,
-  },
-  { 
-    title: '南安水头', 
-    desc: '千年古镇风情',
-    bottomLocate: '泉州市',
-    bottomScore: '5.0',
-    image: TestImage3,
-  },
-  { 
-    title: '南安水头', 
-    desc: '千年古镇风情',
-    bottomLocate: '泉州市',
-    bottomScore: '5.0',
-    image: TestImage4,
-  },
-]
-const topicsData = [
-  {
-    title: '古早味',
-    desc: '是闽南人用来形容古旧的味道的一个词',
-  },
-  {
-    title: '古早味',
-    desc: '是闽南人用来形容古旧的味道的一个词',
-  },
-]
+);
+
+const {
+  loader: corseData,
+  goList: goCourseList,
+  goDetail: goCourseDetail,
+} = useHomePageMiniCommonListGoMoreAndGoDetail({
+  title: '闽南语在线课程',
+  mainBodyColumnId: 0,
+  modelId: 0,
+  itemType: 'article-common',
+  detailsPage: '/pages/video/details',
+});
+
+const {
+  loader: songsData,
+  goList: goSongsList,
+  goDetail: goSongsDetail,
+} = useHomePageMiniCommonListGoMoreAndGoDetail({
+  title: '闽南语原创歌曲',
+  mainBodyColumnId: 0,
+  modelId: 0,
+  itemType: 'article-common',
+  detailsPage: '/pages/video/details',
+});
+
+const {
+  loader: storyData,
+  goList: goStoryList,
+  goDetail: goStoryDetail,
+} = useHomePageMiniCommonListGoMoreAndGoDetail({
+  title: '方言故事频率库',
+  mainBodyColumnId: 0,
+  modelId: 0,
+  itemType: 'article-common',
+  detailsPage: '/pages/video/details',
+});
+
+const {
+  loader: memoryData,
+  goList: goMemoryList,
+  goDetail: goMemoryDetail,
+} = useHomePageMiniCommonListGoMoreAndGoDetail({
+  title: '童趣记忆',
+  mainBodyColumnId: 0,
+  modelId: 0,
+  itemType: 'article-common',
+  detailsPage: '/pages/article/details',
+});
+
+const {
+  loader: oldData,
+  goList: goOldList,
+  goDetail: goOldDetail,
+} = useHomePageMiniCommonListGoMoreAndGoDetail({
+  title: '老字号',
+  mainBodyColumnId: 0,
+  modelId: 0,
+  itemType: 'article-common',
+  detailsPage: '/pages/article/details',
+});
+
+const {
+  loader: topicsData,
+  goList: goTopicsList,
+  goDetail: goTopicsDetail,
+} = useHomePageMiniCommonListGoMoreAndGoDetail({
+  title: '古早味知识百科',
+  mainBodyColumnId: 0,
+  modelId: 0,
+  itemType: 'article-common',
+  detailsPage: '/pages/article/details',
+});
+
 </script>
 
 <style lang="scss">

+ 4 - 66
src/pages/inhert/artifact/details.vue

@@ -1,5 +1,5 @@
 <template>
-  <view class="d-flex flex-col h-100vh">
+  <view class="d-flex flex-col bg-base">
     <SimplePageContentLoader :loader="loader">
       <template v-if="loader.content.value">
         <view class="banner">
@@ -11,7 +11,7 @@
             </swiper-item>
           </swiper>
         </view>
-        <view class="d-flex flex-col p-3">
+        <view class="d-flex flex-col p-3 bg-light">
           <view class="intro-block artifact-info">
             <HomeTitle :title="loader.content.value.title" />
             <view class="desc no-indent">
@@ -60,12 +60,11 @@
             <view class="desc">
               <u-parse :content="loader.content.value.intro" :tagStyle="commonParserStyle"></u-parse>
             </view>
-            <view class="sub-title">详情</view>
             <view class="desc">
               <u-parse :content="loader.content.value.value" :tagStyle="commonParserStyle"></u-parse>
             </view>
           </view>
-          <HomeTitle title="更多人气好去处" showMore />
+          <HomeTitle title="更多人气好去处" />
           <view class="rec-list">
             <swiper class="swiper" :autoplay="false" :circular="false" :duration="500"
                     :next-margin="'145rpx'">
@@ -79,15 +78,6 @@
               </swiper-item>
             </swiper>
           </view>
-          <HomeTitle title="本地吃透透" showMore />
-          <view class="food-list">
-            <view class="item" v-for="item in foodList" :key="item.id">
-              <image :src="item.image" mode="aspectFill"></image>
-              <view class="info">
-                <view class="name">{{ item.name }}</view>
-              </view>
-            </view>
-          </view>
         </view>
       </template>
     </SimplePageContentLoader>
@@ -117,63 +107,11 @@ const loader = useSimplePageContentLoader<
 useLoadQuerys({ id : 0, }, (p) => loader.loadData(p));
 
 function goDetails(item: any) {
-  navTo('inherit_artifact_details', { id: item.id })
+  navTo('./details', { id: item.id })
 }
-
-const foodList = [
-  {
-    id: 1,
-    image: 'https://lucheng.app4lh.cn/static/tmp/static/tmp/food1.png',
-    name: '沙茶面',
-  },
-  {
-    id: 2,
-    image: 'https://lucheng.app4lh.cn/static/tmp/static/tmp/food2.png',
-    name: '碗糕',
-  },
-  {
-    id: 3,
-    image: 'https://lucheng.app4lh.cn/static/tmp/static/tmp/food1.png',
-    name: '姜母鸭',
-  },
-  {
-    id: 4,
-    image: 'https://lucheng.app4lh.cn/static/tmp/static/tmp/food2.png',
-    name: '炸枣',
-  }
-];
 </script>
 
 <style lang="scss" scoped>
-page {
-  background: #FFF3E1;
-}
-
-.food-list {
-  display: flex;
-  justify-content: space-between;
-  flex-wrap: wrap;
-
-  .item {
-    width: calc(50% - 15rpx);
-    margin-bottom: 53rpx;
-
-    image {
-      width: 100%;
-      height: 360rpx;
-      display: block;
-    }
-
-    .info {
-      text-align: center;
-      padding-top: 20rpx;
-      font-weight: bold;
-      font-size: 30rpx;
-      color: #312520;
-    }
-  }
-}
-
 .rec-list {
   swiper {
     height: 300rpx;

+ 1 - 1
src/pages/inhert/artifact/list.vue

@@ -126,7 +126,7 @@ const listLoader = useSimplePageListLoader<{
   return res.list.map((item) => {
     return {
       id: item.id,
-      image: item.image,
+      image: item.thumbnail,
       name: item.title,
     }
   })

+ 49 - 0
src/pages/inhert/intangible/details.vue

@@ -0,0 +1,49 @@
+<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">
+          <ImageSwiper :images="loader.content.value.images" />
+          <view class="d-flex flex-col text-align-center mt-3">
+            <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.desc }}</text>
+          </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";
+import ImageSwiper from "@/pages/parts/ImageSwiper.vue";
+
+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>

+ 77 - 0
src/pages/inhert/intangible/list.vue

@@ -0,0 +1,77 @@
+<template>
+  <CommonListPage 
+    title="非遗"
+    itemType="image-large-2"
+    detailsPage="/pages/inhert/intangible/details"
+    :dropDownNames="dropdownNames"
+    :tabs="[
+      { id: 0, name: '非遗项目' },
+      { id: 1, name: '非遗产品' },
+    ]"
+    :load="loadData" 
+  />
+</template>
+
+<script setup lang="ts">
+import CommonContent, { GetContentListParams } from '@/api/CommonContent';
+import ProductsContent from '@/api/inheritor/ProductsContent';
+import ProjectsContent from '@/api/inheritor/ProjectsContent';
+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[],
+  tabSelect: number,
+) {
+  let api;
+  switch (tabSelect) {
+    case 0: api = ProjectsContent; break;
+    default:
+    case 1: api = ProductsContent; break;
+  }
+  return (await api.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],
+    keyword: searchText,
+  }), 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>

+ 38 - 0
src/pages/parts/ImageSwiper.vue

@@ -0,0 +1,38 @@
+<template>
+  <swiper 
+    class="image-swiper" 
+    circular
+    :indicator-dots="true"
+    :autoplay="true"
+    :interval="2000"
+    :duration="1000"
+  >
+    <swiper-item v-for="(item, key) in images" :key="key">
+      <view class="item">
+        <ImageWrapper :src="item" mode="aspectFill" width="750rpx" radius="20rpx" />
+      </view>
+    </swiper-item>
+  </swiper>
+</template>
+
+<script setup lang="ts">
+import ImageWrapper from '@/common/components/ImageWrapper.vue';
+import type { PropType } from 'vue';
+
+defineProps({
+  images: {
+    type: Array as PropType<string[]>,
+    default: () => [],
+  },
+})
+</script>
+
+<style lang="scss">
+.image-swiper {
+  height: 400rpx;
+
+  image {
+    border-radius: 20rpx;
+  }
+}
+</style>

+ 161 - 132
src/pages/travel.vue

@@ -24,6 +24,7 @@
             v-for="(tab, k) in subTabs" 
             :key="k"
             class="d-flex bg-light-light-primary radius-base p-2 flex-column align-center"
+            @click="tab.onClick"
           >
             <image class="width-100" :src="tab.icon" mode="widthFix" />
             <text class="color-title-text mt-2">{{ tab.name }}</text>
@@ -32,72 +33,83 @@
       </view>
 
       <!-- 精品路线 -->
-      <HomeTitle title="精品路线" showMore inWing />
-      <scroll-view scroll-x>
-        <view class="padding-wing-l pb-3 pt-3 d-flex flex-row overflow-visible align-stretch">
-          <Box2LineLargeImageUserShadow
-            v-for="(item, i) in routeData"
-            classNames="width-2-3 mr-2"
-            titleColor="title-text"
-            :key="i"
-            :title="item.title"
-            :desc="item.desc"
-            :image="item.image"
-            :bottomTime="item.bottomTime"
-          />
-        </view>
-      </scroll-view>
+      <HomeTitle title="精品路线" showMore inWing @clickMore="goRouteList" />
+      <SimplePageContentLoader :loader="routeData">
+        <scroll-view scroll-x>
+          <view class="padding-wing-l pb-3 pt-3 d-flex flex-row overflow-visible align-stretch">
+            <Box2LineLargeImageUserShadow
+              v-for="(item, i) in routeData.content.value"
+              classNames="width-2-3 mr-2"
+              titleColor="title-text"
+              :key="i"
+              :title="item.title"
+              :desc="item.desc"
+              :image="item.image"
+              :bottomTime="'item.bottomTime'"
+              @click="goRouteDetail(item.id)"
+            />
+          </view>
+        </scroll-view>
+      </SimplePageContentLoader>
 
       <!-- 精选推荐 -->
-      <HomeTitle title="精选推荐" showMore inWing />
-      <scroll-view scroll-x>
-        <view class="padding-wing-l pb-3 pt-3 d-flex flex-row overflow-visible align-stretch">
-          <Box2LineLargeImageUserShadow
-            v-for="(item, i) in recommendData"
-            classNames="width-2-3 mr-2"
-            titleColor="title-text"
-            :key="i"
-            :title="item.title"
-            :desc="item.desc"
-            :image="item.image"
-            :bottomLocate="item.bottomLocate"
-            :bottomScore="item.bottomScore"
-          />
-        </view>
-      </scroll-view>
+      <HomeTitle title="精选推荐" showMore inWing @clickMore="goRecommendList" />
+      <SimplePageContentLoader :loader="recommendData">
+        <scroll-view scroll-x>
+          <view class="padding-wing-l pb-3 pt-3 d-flex flex-row overflow-visible align-stretch">
+            <Box2LineLargeImageUserShadow
+              v-for="(item, i) in recommendData.content.value"
+              classNames="width-2-3 mr-2"
+              titleColor="title-text"
+              :key="i"
+              :title="item.title"
+              :desc="item.desc"
+              :image="item.image"
+              :bottomLocate="'item.bottomLocate'"
+              :bottomScore="'item.bottomScore'"
+              @click="goRecommendDetail(item.id)"
+            />
+          </view>
+        </scroll-view>
+      </SimplePageContentLoader>
 
       <!-- 文创好物 -->
-      <HomeTitle title="文创好物" showMore inWing />
-      <scroll-view scroll-x>
-        <view class="padding-wing-l pb-3 pt-3 d-flex flex-row overflow-visible align-stretch">
-          <Box2LineLargeImageUserShadow
-            v-for="(item, i) in creativeData"
-            classNames="width-2-3 mr-2"
-            titleColor="title-text"
-            :key="i"
-            :title="item.title"
-            :image="item.image"
-          />
-        </view>
-      </scroll-view>
+      <HomeTitle title="文创好物" showMore inWing @clickMore="goCreativeList" />
+      <SimplePageContentLoader :loader="creativeData">
+        <scroll-view scroll-x>
+          <view class="padding-wing-l pb-3 pt-3 d-flex flex-row overflow-visible align-stretch">
+            <Box2LineLargeImageUserShadow
+              v-for="(item, i) in creativeData.content.value"
+              classNames="width-2-3 mr-2"
+              titleColor="title-text"
+              :key="i"
+              :title="item.title"
+              :image="item.image"
+              @click="goCreativeDetail(item.id)"
+            />
+          </view>
+        </scroll-view>
+      </SimplePageContentLoader>
 
       <!-- 近期活动 -->
       <view class="d-flex flex-col wing-l">
         <HomeTitle title="近期活动" showMore />
-        <Box2LineRightShadow
-          v-for="(item, i) in activityData" 
-          :key="i" 
-          :title="item.title"
-          :desc="item.desc"
-          :right="item.right"
-        >
-          <template #left>
-            <view class="d-flex flex-col justify-center align-center radius-base bg-light-light-primary p-25 pt-2 pb-2">
-              <text class="color-primary size-s">12月</text>
-              <text class="color-primary size-base text-bold">28</text>
-            </view>
-          </template>
-        </Box2LineRightShadow>
+        <SimplePageContentLoader :loader="activityData">
+          <Box2LineRightShadow
+            v-for="(item, i) in activityData.content.value" 
+            :key="i" 
+            :title="item.title"
+            :desc="item.desc"
+            :right="item.right"
+          >
+            <template #left>
+              <view class="d-flex flex-col justify-center align-center radius-base bg-light-light-primary p-25 pt-2 pb-2">
+                <text class="color-primary size-s">12月</text>
+                <text class="color-primary size-base text-bold">28</text>
+              </view>
+            </template>
+          </Box2LineRightShadow>
+        </SimplePageContentLoader>
       </view>
     </view>
 
@@ -114,97 +126,114 @@ import CategoryIcon3 from '@/static/images/travel/CategoryIcon3.png';
 import CategoryIcon4 from '@/static/images/travel/CategoryIcon4.png';
 import CategoryIcon5 from '@/static/images/travel/CategoryIcon5.png';
 import CategoryIcon6 from '@/static/images/travel/CategoryIcon6.png';
-import TestImage1 from '@/static/images/inhert/TestImage1.jpg';
-import TestImage2 from '@/static/images/inhert/TestImage2.jpg';
-import TestImage3 from '@/static/images/inhert/TestImage3.jpg';
-import TestImage4 from '@/static/images/inhert/TestImage4.jpg';
 import Box2LineLargeImageUserShadow from './parts/Box2LineLargeImageUserShadow.vue';
 import Box2LineRightShadow from './parts/Box2LineRightShadow.vue';
 import HomeTitle from './parts/HomeTitle.vue';
+import { useHomePageMiniCommonListGoMoreAndGoDetail } from './article/common/CommonContent';
+import { useSimpleDataLoader } from '@/common/composeabe/SimpleDataLoader';
+import { navTo } from '@/common/utils/PageAction';
+import SimplePageContentLoader from '@/common/components/SimplePageContentLoader.vue';
 
 const subTabs = [
-  { name: '节庆日历', icon: CategoryIcon1 },
-  { name: '文化景区', icon: CategoryIcon2 },
-  { name: '旅游路线', icon: CategoryIcon3 },
-  { name: '文化产品', icon: CategoryIcon4 },
-  { name: '示范点', icon: CategoryIcon5 },
-  { name: '闽南歌曲', icon: CategoryIcon6 },
-]
-const routeData = [
   { 
-    title: '古城文化之旅', 
-    desc: '千年古镇风情',
-    bottomTime: '123',
-    image: TestImage3,
+    name: '节庆日历', 
+    icon: CategoryIcon1,
+    onClick: () => navTo('/pages/travel/calendar'),
   },
   { 
-    title: '古城文化之旅', 
-    desc: '千年古镇风情',
-    bottomTime: '123',
-    image: TestImage4,
+    name: '文化景区', 
+    icon: CategoryIcon2 , 
+    onClick: () => navTo('/pages/article/common/list', {
+      title: '闽南语',
+      mainBodyColumnId: 0,
+      modelId: 0,
+      itemType: 'article-common',
+      detailsPage: '/pages/video/details',
+    }) 
   },
   { 
-    title: '古城文化之旅', 
-    desc: '千年古镇风情',
-    bottomTime: '123',
-    image: TestImage3,
+    name: '旅游路线', 
+    icon: CategoryIcon3 , 
+    onClick: () => navTo('/pages/article/common/list', {
+      title: '闽南语',
+      mainBodyColumnId: 0,
+      modelId: 0,
+      itemType: 'article-common',
+      detailsPage: '/pages/video/details',
+    }) 
   },
   { 
-    title: '古城文化之旅', 
-    desc: '千年古镇风情',
-    bottomTime: '123',
-    image: TestImage4,
+    name: '文化产品', 
+    icon: CategoryIcon4 , 
+    onClick: () => navTo('/pages/article/common/list', {
+      title: '闽南语',
+      mainBodyColumnId: 0,
+      modelId: 0,
+      itemType: 'article-common',
+      detailsPage: '/pages/video/details',
+    }) 
   },
-]
-const recommendData = [
   { 
-    title: '南安水头', 
-    desc: '千年古镇风情',
-    bottomLocate: '泉州市',
-    bottomScore: '5.0',
-    image: TestImage3,
+    name: '示范点', 
+    icon: CategoryIcon5 , 
+    onClick: () => navTo('/pages/article/common/list', {
+      title: '闽南语',
+      mainBodyColumnId: 0,
+      modelId: 0,
+      itemType: 'article-common',
+      detailsPage: '/pages/video/details',
+    }) 
   },
   { 
-    title: '南安水头', 
-    desc: '千年古镇风情',
-    bottomLocate: '泉州市',
-    bottomScore: '5.0',
-    image: TestImage4,
-  },
-  { 
-    title: '南安水头', 
-    desc: '千年古镇风情',
-    bottomLocate: '泉州市',
-    bottomScore: '5.0',
-    image: TestImage3,
-  },
-  { 
-    title: '南安水头', 
-    desc: '千年古镇风情',
-    bottomLocate: '泉州市',
-    bottomScore: '5.0',
-    image: TestImage4,
+    name: '闽南歌曲', 
+    icon: CategoryIcon6 , 
+    onClick: () => navTo('/pages/article/common/list', {
+      title: '闽南语',
+      mainBodyColumnId: 0,
+      modelId: 0,
+      itemType: 'article-common',
+      detailsPage: '/pages/video/details',
+    }) 
   },
 ]
-const creativeData = [
-  { 
-    title: '南安水头', 
-    image: TestImage3,
-  },
-  { 
-    title: '南安水头', 
-    image: TestImage4,
-  },
-  { 
-    title: '南安水头', 
-    image: TestImage3,
-  },
-  { 
-    title: '南安水头', 
-    image: TestImage4,
-  },
-]
-const activityData = [
+
+const {
+  loader: routeData,
+  goList: goRouteList,
+  goDetail: goRouteDetail,
+} = useHomePageMiniCommonListGoMoreAndGoDetail({
+  title: '旅游路线',
+  mainBodyColumnId: 0,
+  modelId: 0,
+  itemType: 'article-common',
+  detailsPage: '/pages/article/details',
+});
+
+const {
+  loader: recommendData,
+  goList: goRecommendList,
+  goDetail: goRecommendDetail,
+} = useHomePageMiniCommonListGoMoreAndGoDetail({
+  title: '文化景区',
+  mainBodyColumnId: 0,
+  modelId: 0,
+  itemType: 'article-common',
+  detailsPage: '/pages/article/details',
+});
+
+const {
+  loader: creativeData,
+  goList: goCreativeList,
+  goDetail: goCreativeDetail,
+} = useHomePageMiniCommonListGoMoreAndGoDetail({
+  title: '文化产品',
+  mainBodyColumnId: 0,
+  modelId: 0,
+  itemType: 'article-common',
+  detailsPage: '/pages/article/details',
+});
+
+const activityData = useSimpleDataLoader(async () => [
   {
     title: '闽南文化节',
     desc: '泉州市区',
@@ -215,7 +244,7 @@ const activityData = [
     desc: '泉州市区',
     right: '已截至',
   },
-]
+]);
 
 </script>
 

+ 397 - 0
src/pages/travel/calendar.vue

@@ -0,0 +1,397 @@
+<template>
+  <view class="travel_calendar bg-base">
+    <u-navbar title="节庆日历" autoBack bgColor="transparent" />
+    <view class="banner">
+      <swiper class="swiper right-indicator" circular :indicator-dots="true" :autoplay="true" :interval="2000"
+        :duration="1000">
+        <swiper-item v-for="item in bannerData" :key="item.id">
+          <view class="item">
+            <image class="w-100" :src="item.image" mode="aspectFill"></image>
+          </view>
+        </swiper-item>
+      </swiper>
+    </view>
+    <view class="main m-3 radius-l p-3 bg-light">
+      <view class="change-year">
+        <view class="year">
+          <text class="iconfont icon-arrow-left" @click="changeYear(currentYear - 1)"></text>
+          <picker mode="date" :value="currentYear" @change="(e: any) => changeYear(e.detail.value)" fields="year">
+            <view class="current-year">{{ currentYear }} 年</view>
+          </picker>
+          <text class="iconfont icon-arrow-right" @click="changeYear(currentYear + 1)"></text>
+        </view>
+        <text class="iconfont icon-calendar"></text>
+      </view>
+      <u-tabs 
+        :current="activeTab" 
+        :list="tabs" 
+        lineWidth="30" 
+        lineColor="#d9492e" 
+        :activeStyle="{
+          color: '#000',
+          fontWeight: 'bold',
+          transform: 'scale(1.05)'
+        }" 
+        :inactiveStyle="{
+          color: '#606266',
+          transform: 'scale(1)'
+        }" 
+        class="top-tab" 
+        @click="tabClick" 
+      />
+      <view class="activity-wrap mt-3">
+        <view class="month-list">
+          <view 
+            v-for="month in monthList"
+            :key="month.value"
+            :class="{ active: month.value === currentMonth }" 
+            class="month" 
+            @click="goMonth(month.value)"
+          >
+            {{ month.label }}
+          </view>
+        </view>
+        <SimplePageContentLoader 
+          :loader="listLoader"
+          :showEmpty="!listLoader.content.value?.length"
+        >
+          <view 
+            v-if="listLoader.content.value && listLoader.content.value.length" 
+            class="activity-list"
+          >
+            <scroll-view scroll-y :scroll-into-view="'month' + currentMonth" scroll-with-animation>
+              <view class="item" v-for="item in listLoader.content.value" :key="item.id">
+                <view class="head" :id="'month' + item.month">
+                  <view class="year-month">{{ item.year }}年{{ item.month }}月</view>
+                  <view>本月活动 <text>{{ item.data.length }}</text></view>
+                </view>
+                <view class="activity" v-for="act in item.data" :key="act.id">
+                  <view class="title">{{ act.title }}</view>
+                  <view class="dot" :class="{ ing: act.status === 0 }"></view>
+                  <view class="desc ellipsis-2">{{ act.desc }}</view>
+                  <view class="place"><text class="iconfont icon-place"></text>{{ act.place }}</view>
+                  <view class="time"><text class="iconfont icon-time"></text>{{ act.time }}</view>
+                </view>
+              </view>
+            </scroll-view>
+          </view>
+        </SimplePageContentLoader>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script setup lang="ts">
+import { GetContentListParams } from '@/api/CommonContent';
+import NewsIndexContent from '@/api/news/NewsIndexContent';
+import SimplePageContentLoader from '@/common/components/SimplePageContentLoader.vue';
+import { useSimplePageContentLoader } from '@/common/composeabe/SimplePageContentLoader';
+import { onLoad } from '@dcloudio/uni-app';
+import { ref } from 'vue';
+
+const tabs = [
+  {
+    id: 1,
+    name: '全部'
+  },
+  {
+    id: 2,
+    name: '节庆民俗'
+  },
+  {
+    id: 3,
+    name: '信仰祭祀'
+  },
+  {
+    id: 4,
+    name: '游艺竞技'
+  },
+  {
+    id: 5,
+    name: '民间艺术'
+  },
+  {
+    id: 7,
+    name: '其他'
+  }
+];
+const activeTab = ref(0);
+const bannerData = [
+  {
+    id: 1,
+    image: 'https://lucheng.app4lh.cn/static/tmp/static/tmp/banner_act.png',
+  },
+  {
+    id: 2,
+    image: 'https://lucheng.app4lh.cn/static/tmp/static/tmp/banner_act.png',
+  }
+]
+
+const currentMonth = ref(1);
+const currentYear = ref(new Date().getFullYear());
+const monthList = [
+  {
+    label: '1月',
+    value: 1
+  }, {
+    label: '2月',
+    value: 2
+  }, {
+    label: '3月',
+    value: 3
+  }, {
+    label: '4月',
+    value: 4
+  }, {
+    label: '5月',
+    value: 5
+  }, {
+    label: '6月',
+    value: 6
+  }, {
+    label: '7月',
+    value: 7
+  }, {
+    label: '8月',
+    value: 8
+  }, {
+    label: '9月',
+    value: 9
+  }, {
+    label: '10月',
+    value: 10
+  }, {
+    label: '11月',
+    value: 11
+  }, {
+    label: '12月',
+    value: 12
+  }
+];
+
+const listLoader = useSimplePageContentLoader<{
+  id: number;
+  month: number,
+  year: number,
+  data: {
+    id: number,
+    title: string,
+    desc: string,
+    place: string,
+    time: string,
+    status: number,
+  }[]
+}[]>(async () => {
+  const res = await NewsIndexContent.getContentList(new GetContentListParams().setSelfValues({
+    mainBodyColumnId: 302
+  }), 1, 50);
+  return [];
+});
+
+function tabClick(e: { index: number }) {
+  activeTab.value = e.index;
+}
+function goMonth(month: number) {
+  currentMonth.value = month;
+}
+async function changeYear(year: number) {
+  currentYear.value = year;
+  listLoader.loadData(undefined, true);
+}
+
+onLoad(() => {
+  listLoader.loadData(undefined, true);
+});
+</script>
+
+<style lang="scss">
+@use "sass:map";
+@use "@/common/scss/define/colors.scss" as *;
+
+$color-primary: map.get($colors, "primary");
+
+.travel_calendar {
+  .banner {
+    margin-top: 0;
+
+    .swiper {
+      height: 400rpx;
+      border-radius: 0 0 28rpx 28rpx;
+
+      .item {
+        image {
+          border-radius: 0 0 28rpx 28rpx;
+        }
+      }
+    }
+  }
+
+  .activity-wrap {
+    display: flex;
+
+    .activity-list {
+      .head {
+        background: #FFFFFF;
+        border-radius: 28rpx;
+        margin-bottom: 18rpx;
+        color: #111111;
+        padding: 12rpx 42rpx 12rpx 50rpx;
+        display: flex;
+        align-items: center;
+        font-size: 24rpx;
+
+        .year-month {
+          font-weight: 600;
+          font-size: 30rpx;
+          flex: 1;
+        }
+
+        text {
+          font-weight: 600;
+          display: inline-block;
+          margin-left: 12rpx;
+        }
+      }
+
+      .activity {
+        padding: 36rpx 32rpx 38rpx 48rpx;
+        background: #FFFFFF;
+        box-shadow: 0rpx 12rpx 28rpx 0rpx rgba(215, 215, 215, 0.35);
+        border-radius: 24rpx;
+        position: relative;
+        font-size: 24rpx;
+        overflow: hidden;
+        margin-bottom: 46rpx;
+
+        .desc {
+          text-align: justify;
+          margin-bottom: 36rpx;
+        }
+
+        .dot {
+          width: 12rpx;
+          height: 12rpx;
+          background: #E0E0E0;
+          border-radius: 50%;
+          position: absolute;
+          left: 20rpx;
+          top: 50rpx;
+
+          &.ing {
+            background: $color-primary;
+          }
+        }
+
+        .title {
+          font-weight: 600;
+          font-size: 30rpx;
+          color: #111111;
+          margin-bottom: 25rpx;
+        }
+
+        .place {
+          margin-bottom: 18rpx;
+          align-items: center;
+          display: flex;
+          font-size: 28rpx;
+
+        }
+
+        .iconfont {
+          display: inline-block;
+          margin-right: 6rpx;
+          font-size: 36rpx;
+        }
+
+        .time {
+          display: flex;
+          align-items: center;
+          font-size: 28rpx;
+        }
+
+        .status {
+          position: absolute;
+          bottom: 0;
+          right: 0;
+          background: $color-primary;
+          padding: 14rpx 26rpx;
+          border-radius: 31rpx 0rpx 0rpx 0rpx;
+          color: #fff;
+
+          view {
+            font-size: 24rpx;
+          }
+
+          &.ing {
+            background: #24515D;
+          }
+
+          &.end {
+            background: #C9C9C9;
+          }
+        }
+      }
+    }
+
+    .month-list {
+      text-align: center;
+      flex-shrink: 0;
+      margin-right: 28rpx;
+
+      .month {
+        border-radius: 10rpx;
+        margin-bottom: 30rpx;
+        padding: 12rpx 20rpx;
+
+        &.active {
+          border: 1px solid $color-primary;
+          background: #FFFFFF;
+        }
+      }
+    }
+  }
+
+  scroll-view {
+    height: calc(100vh - 540rpx);
+    padding-bottom: 50rpx;
+  }
+
+  .change-year {
+    padding: 0 34rpx 34rpx 34rpx;
+    text-align: center;
+    position: relative;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+
+    .year {
+      display: flex;
+      align-items: center;
+      justify-content: center;
+    }
+
+    .current-year {
+      font-size: 36rpx;
+      color: #333333;
+    }
+
+    text.icon-arrow-left {
+      display: inline-block;
+      margin-right: 100rpx;
+      font-size: 32rpx;
+    }
+
+    text.icon-arrow-right {
+      display: inline-block;
+      margin-left: 100rpx;
+      font-size: 32rpx;
+    }
+
+    text.icon-calendar {
+      position: absolute;
+      right: 0;
+      top: 8rpx;
+    }
+  }
+}
+</style>

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

@@ -50,10 +50,10 @@
       <u-button type="primary" @click="loginWechat">
         微信登录
       </u-button>
-      <view class="mt-3" />
+      <!-- <view class="mt-3" />
       <u-button type="primary" :plain="true" @click="type='mobile'">
         手机号登录
-      </u-button>
+      </u-button> -->
     </view>
   </view>
 </template>

+ 3 - 6
src/pages/video/details.vue

@@ -33,9 +33,10 @@
 <script setup lang="ts">
 import type { GetContentDetailItem } from "@/api/CommonContent";
 import { useSimplePageContentLoader } from "@/common/composeabe/SimplePageContentLoader";
-import { onLoad } from "@dcloudio/uni-app";
 import NewsIndexContent from "@/api/news/NewsIndexContent";
 import commonParserStyle from "@/common/style/commonParserStyle";
+import SimplePageContentLoader from "@/common/components/SimplePageContentLoader.vue";
+import { useLoadQuerys } from "@/common/composeabe/LoadQuerys";
 
 const loader = useSimplePageContentLoader<
   GetContentDetailItem, 
@@ -47,11 +48,7 @@ const loader = useSimplePageContentLoader<
   return res;
 });
 
-onLoad((options) => {
-  loader.loadData({
-    id: Number(options?.id),
-  })
-});
+useLoadQuerys({ id: 0 }, (t) => loader.loadData(t));
 </script>
 
 <style lang="scss">

Dosya farkı çok büyük olduğundan ihmal edildi
+ 0 - 84
src/static/css/font.css


BIN
src/static/fonts/STSongti-SC-Black.ttf


BIN
src/static/fonts/STSongti-SC-Black.woff


BIN
src/static/fonts/STSongti-SC-Black.woff2


BIN
src/static/images/home/ImageTest2.jpg


BIN
src/static/images/home/ImageTest3.jpg


BIN
src/static/images/home/ImageTest4.jpg


BIN
src/static/images/home/ImageTest5.jpg


BIN
src/static/images/inhert/TestImage1.jpg


BIN
src/static/images/inhert/TestImage2.jpg


BIN
src/static/images/inhert/TestImage3.jpg


BIN
src/static/images/inhert/TestImage4.jpg


BIN
src/static/images/inhert/TestImage5.jpg


+ 3 - 1
src/uni.scss

@@ -11,7 +11,9 @@
  *
  * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
  */
-@import '@/uni_modules/uview-plus/theme.scss';
+ 
+ @use '@/uni_modules/uview-plus/theme.scss' as *;
+
 /* 颜色变量 */
 
 /* 行为相关颜色 */