Parcourir la source

feat: 分类页面支持切换不同的展示模式

小莫唐尼 il y a 9 mois
Parent
commit
2a25727c0b

+ 215 - 213
components/article-min-card/article-min-card.vue

@@ -1,220 +1,222 @@
 <template>
-	<view class="article-min-card" :class="[globalAppSettings.layout.cardType]" @click="fnClickEvent('card')">
-		<view class="left">
-			<cache-image class="thumbnail" radius="6rpx" :url="$utils.checkThumbnailUrl(article.thumbnail)" :fileMd5="$utils.checkThumbnailUrl(article.thumbnail)" mode="aspectFill"></cache-image>
-		</view>
-		<view class="right">
-			<view class="title text-overflow">{{ article.title }}</view>
-			<view class="content text-overflow">{{ article.summary }}</view>
-			<view class="foot">
-				<view class="create-time">
-					<!-- <text class="icon iconfont icon-clock"></text> -->
-					<text class="time-label">发布时间:</text>
-					{{ { d: article.createTime, f: 'yyyy-MM-dd' } | formatTime }}
-				</view>
-				<view class="visits">
-					<!-- <text class="icon iconfont icon-eye"></text> -->
-					浏览
-					<text class="number">{{ article.visits }}</text>
-					次
-				</view>
-			</view>
-		</view>
-	</view>
+    <view class="article-min-card" @click="fnClickEvent('card')">
+        <view class="left">
+            <cache-image class="thumbnail" radius="6rpx" :url="$utils.checkThumbnailUrl(article.spec.cover)" :fileMd5="article.spec.cover"
+                         mode="aspectFill"></cache-image>
+        </view>
+        <view class="right">
+            <view class="title text-overflow">{{ article.spec.title }}</view>
+            <view class="content text-overflow">{{ article.status.excerpt }}</view>
+            <view class="foot">
+                <view class="create-time">
+                    <text class="time-label">发布时间:</text>
+                    {{ {d: article.spec.publishTime, f: 'yyyy-MM-dd'} | formatTime }}
+                </view>
+                <view class="visits">
+                    浏览
+                    <text class="number">{{ article.stats.visit }}</text>
+                    次
+                </view>
+            </view>
+        </view>
+    </view>
 </template>
 
 <script>
-	export default {
-		name: 'article-min-card',
-		props: {
-			article: {
-				type: Object,
-				default: () => {}
-			}
-		},
-		methods: {
-			fnClickEvent() {
-				this.$emit('on-click', this.article);
-			}
-		}
-	};
+export default {
+    name: 'article-min-card',
+    props: {
+        article: {
+            type: Object,
+            default: () => {
+            }
+        }
+    },
+    methods: {
+        fnClickEvent() {
+            this.$emit('on-click', this.article);
+        }
+    }
+};
 </script>
 
 <style scoped lang="scss">
-	.article-min-card {
-		display: flex;
-		box-sizing: border-box;
-		border-radius: 12rpx;
-		background-color: #ffff;
-		overflow: hidden;
-		margin: 12rpx 24rpx;
-		margin-bottom: 24rpx;
-		padding: 16rpx;
-		box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.03);
-
-		&.lr_image_text {}
-
-		&.lr_text_image {
-			.left {
-				order: 2;
-				padding-left: 30rpx;
-			}
-
-			.right {
-				order: 1;
-				padding-left: 0;
-			}
-		}
-
-		&.tb_image_text {
-			flex-direction: column;
-
-			.left {
-				width: 100%;
-				height: 220rpx;
-			}
-
-			.right {
-				padding-left: 0;
-				width: 100%;
-
-				.title {
-					margin-top: 24rpx;
-				}
-
-				.foot {
-					justify-content: flex-start;
-
-					.create-time {
-						.time-label {
-							display: inline-block;
-						}
-					}
-
-					.visits {
-						margin-left: 24rpx;
-					}
-				}
-			}
-		}
-
-		&.tb_text_image {
-			flex-direction: column;
-
-			.left {
-				width: 100%;
-				height: 220rpx;
-				order: 2;
-				margin-top: 20rpx;
-			}
-
-			.right {
-				padding-left: 0;
-				width: 100%;
-				order: 1;
-
-				.foot {
-					justify-content: flex-start;
-
-					.create-time {
-						.time-label {
-							display: inline-block;
-						}
-					}
-
-					.visits {
-						margin-left: 24rpx;
-					}
-				}
-			}
-		}
-
-		&.only_text {
-			.left {
-				display: none;
-			}
-
-			.right {
-				padding-left: 0;
-
-				.foot {
-					justify-content: flex-start;
-
-					.create-time {
-						.time-label {
-							display: inline-block;
-						}
-					}
-
-					.visits {
-						margin-left: 24rpx;
-					}
-				}
-			}
-		}
-
-		.left {
-			width: 180rpx;
-			height: 130rpx;
-
-			.thumbnail {
-				width: 100%;
-				height: 100%;
-				border-radius: 12rpx;
-			}
-		}
-
-		.right {
-			width: 0;
-			flex-grow: 1;
-			display: flex;
-			flex-direction: column;
-			padding-left: 20rpx;
-
-			.title {
-				font-size: 28rpx;
-				font-weight: 600;
-				color: var(--main-text-color);
-			}
-
-			.content {
-				font-size: 26rpx;
-				color: #909399;
-				margin-top: 14rpx;
-			}
-
-			.foot {
-				display: flex;
-				font-size: 24rpx;
-				justify-content: space-between;
-				align-items: center;
-				color: #909399;
-				margin-top: 14rpx;
-
-				.create-time {
-					font-size: 24rpx;
-
-					.time-label {
-						display: none;
-					}
-
-					.icon {
-						font-size: 24rpx;
-						padding-right: 4rpx;
-					}
-				}
-
-				.visits {
-					.icon {
-						font-size: 28rpx;
-					}
-
-					.number {
-						padding: 0 6rpx;
-						font-size: 24rpx;
-					}
-				}
-			}
-		}
-	}
-</style>
+.article-min-card {
+    display: flex;
+    box-sizing: border-box;
+    border-radius: 12rpx;
+    background-color: #ffff;
+    overflow: hidden;
+    margin: 12rpx 24rpx;
+    margin-bottom: 24rpx;
+    padding: 16rpx;
+    box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.03);
+
+    &.lr_image_text {
+    }
+
+    &.lr_text_image {
+        .left {
+            order: 2;
+            padding-left: 30rpx;
+        }
+
+        .right {
+            order: 1;
+            padding-left: 0;
+        }
+    }
+
+    &.tb_image_text {
+        flex-direction: column;
+
+        .left {
+            width: 100%;
+            height: 220rpx;
+        }
+
+        .right {
+            padding-left: 0;
+            width: 100%;
+
+            .title {
+                margin-top: 24rpx;
+            }
+
+            .foot {
+                justify-content: flex-start;
+
+                .create-time {
+                    .time-label {
+                        display: inline-block;
+                    }
+                }
+
+                .visits {
+                    margin-left: 24rpx;
+                }
+            }
+        }
+    }
+
+    &.tb_text_image {
+        flex-direction: column;
+
+        .left {
+            width: 100%;
+            height: 220rpx;
+            order: 2;
+            margin-top: 20rpx;
+        }
+
+        .right {
+            padding-left: 0;
+            width: 100%;
+            order: 1;
+
+            .foot {
+                justify-content: flex-start;
+
+                .create-time {
+                    .time-label {
+                        display: inline-block;
+                    }
+                }
+
+                .visits {
+                    margin-left: 24rpx;
+                }
+            }
+        }
+    }
+
+    &.only_text {
+        .left {
+            display: none;
+        }
+
+        .right {
+            padding-left: 0;
+
+            .foot {
+                justify-content: flex-start;
+
+                .create-time {
+                    .time-label {
+                        display: inline-block;
+                    }
+                }
+
+                .visits {
+                    margin-left: 24rpx;
+                }
+            }
+        }
+    }
+
+    .left {
+        width: 180rpx;
+        height: 130rpx;
+
+        .thumbnail {
+            width: 100%;
+            height: 100%;
+            border-radius: 12rpx;
+        }
+    }
+
+    .right {
+        width: 0;
+        flex-grow: 1;
+        display: flex;
+        flex-direction: column;
+        padding-left: 20rpx;
+
+        .title {
+            font-size: 28rpx;
+            font-weight: 600;
+            color: var(--main-text-color);
+        }
+
+        .content {
+            font-size: 26rpx;
+            color: #909399;
+            margin-top: 14rpx;
+        }
+
+        .foot {
+            display: flex;
+            font-size: 24rpx;
+            justify-content: space-between;
+            align-items: center;
+            color: #909399;
+            margin-top: 14rpx;
+
+            .create-time {
+                font-size: 24rpx;
+
+                .time-label {
+                    display: none;
+                }
+
+                .icon {
+                    font-size: 24rpx;
+                    padding-right: 4rpx;
+                }
+            }
+
+            .visits {
+                .icon {
+                    font-size: 28rpx;
+                }
+
+                .number {
+                    padding: 0 6rpx;
+                    font-size: 24rpx;
+                }
+            }
+        }
+    }
+}
+
+</style>

+ 3 - 0
config/index.js

@@ -26,6 +26,9 @@ export const DefaultAppConfigs = {
                 type: "post",
                 list: []
             }
+        },
+        categoryConfig: {
+            type: "list"
         }
     },
     auditConfig: {

+ 3 - 8
config/token.config.template.js

@@ -1,18 +1,13 @@
 import {getAppConfigs} from "@/config/index";
 
-/** 配置后台管理员token */
-const HaloTokenConfig = Object.freeze({
+/** 配置博客的内容 */
+const UniHaloConfig = Object.freeze({
 
 	/** 基础请求域名:你的Halo博客基础域名 */
 	BASE_API: "",
 	// BASE_API: "https://blog.xiaoxiaomo.cn",
 
-
-	/** 管理员token */
 	systemToken: getAppConfigs()?.basicConfig?.tokenConfig?.personalToken,
-	/** 匿名用户token */
-	anonymousToken: ``
 })
 
-
-export default HaloTokenConfig;
+export default UniHaloConfig;

+ 251 - 39
pages/tabbar/category/category.vue

@@ -1,36 +1,69 @@
 <template>
-    <view class="app-page">
-
+    <view class="app-page" :style="{
+		padding:calcShowType==='list-post'? 0 : '24rpx 0'
+	}">
         <view v-if="loading !== 'success'" class="loading-wrap">
             <tm-skeleton model="listAvatr"></tm-skeleton>
             <tm-skeleton model="listAvatr"></tm-skeleton>
             <tm-skeleton model="listAvatr"></tm-skeleton>
         </view>
         <!-- 内容区域 -->
-        <view v-else class="app-page-content">
+        <view v-else class="app-page-content" :class="[calcShowType==='list-post'?'list-post':'']">
             <view v-if="dataList.length === 0" class="content-empty flex flex-center" style="height: 70vh;">
                 <!-- 空布局 -->
                 <tm-empty icon="icon-shiliangzhinengduixiang-" label="暂无数据"></tm-empty>
             </view>
             <block v-else>
-                <tm-translate v-for="(item, index) in dataList" :key="index"
-                              style="box-sizing: border-box;width: 50%;padding: 0 8rpx;" animation-name="fadeUp"
-                              :wait="calcAniWait(index)">
-                    <view class="catgory-card" :style="{backgroundImage:`url(${item.spec.cover})`}">
-                        <view class="content" @click="handleToCategory(item)">
-                            <view style="font-size: 32rpx;color: #ffffff;">{{ item.spec.displayName }}</view>
-                            <view v-if="!calcAuditModeEnabled" style="font-size: 24rpx;color: #ffffff;margin-top: 6rpx;">
-                                共 {{ item.postCount }} 篇文章
-                            </view>
-                            <view v-else style="font-size: 24rpx;color: #ffffff;margin-top: 6rpx;">
-                                共 {{ item.postCount }} 篇内容
+                <block v-if="calcShowType==='list'">
+                    <tm-translate v-for="(item, index) in dataList" :key="index"
+                                  style="box-sizing: border-box;width: 50%;padding: 0 8rpx;" animation-name="fadeUp"
+                                  :wait="calcAniWait(index)">
+                        <view class="catgory-card" :style="{backgroundImage:`url(${item.spec.cover})`}">
+                            <view class="content" @click="handleToCategory(item)">
+                                <view style="font-size: 32rpx;color: #ffffff;">{{ item.spec.displayName }}</view>
+                                <view v-if="!calcAuditModeEnabled"
+                                      style="font-size: 24rpx;color: #ffffff;margin-top: 6rpx;">
+                                    共 {{ item.postCount }} 篇文章
+                                </view>
+                                <view v-else style="font-size: 24rpx;color: #ffffff;margin-top: 6rpx;">
+                                    共 {{ item.postCount }} 篇内容
+                                </view>
                             </view>
                         </view>
+                    </tm-translate>
+                    <view class="load-text">{{ loadMoreText }}</view>
+                </block>
+                <view v-else-if="calcShowType==='list-post'" class="fulled flex" style="min-height:100vh">
+                    <view class="bg-white" :style="{height: '100%'}">
+                        <tm-sliderNav :list="categoryList" bg-color="white" color="light-blue" rang-key="displayName"
+                                      @change="fnOnCategoryChange"></tm-sliderNav>
                     </view>
-                </tm-translate>
-                <tm-flotbutton @click="fnToTopPage" size="m" color="light-blue"
-                               icon="icon-angle-up"></tm-flotbutton>
-                <view class="load-text">{{ loadMoreText }}</view>
+                    <scroll-view class="right-content pt-12 pb-12" :scroll-y="true" :scroll-top="scrollTop"
+                                 :scroll-with-animation="true" :refresher-enabled="true" :refresher-triggered="triggered"
+                                 :refresher-threshold="60" refresher-background="#fafafa"
+                                 @refresherrefresh="fnGetPostByCategory(true)" @scrolltolower="fnGetPostByCategory(false)"
+                                 @scroll="fnOnScroll" @touchmove.stop @touchstart="fnOnTouchStart" @touchend="fnOnTouchEnd"
+                                 @touchcancel="fnOnTouchEnd">
+                        <view v-if="postList.length === 0" class="article-empty flex flex-center">
+                            <tm-empty :size="120" icon="icon-shiliangzhinengduixiang-" label="该分类下暂无文章~"></tm-empty>
+                        </view>
+                        <block v-else>
+                            <block v-for="(post, index) in postList" :key="post.spec.publishTime">
+                                <tm-translate animation-name="fadeUp" :wait="calcAniWait(index)">
+                                    <article-min-card :article="post" @on-click="fnToArticleDetail"></article-min-card>
+                                </tm-translate>
+                            </block>
+                            <view class="load-text">{{ loadMoreText }}</view>
+                        </block>
+                    </scroll-view>
+                </view>
+
+                <view class="flot-buttons">
+                    <tm-button @click="fnScrollTop" size="m" :fab="true" theme="light-blue"
+                               icon="icon-angle-up"></tm-button>
+                    <tm-button @click="fnChangeShowType" size="m" :fab="true" theme="light-blue"
+                               :icon="calcShowType==='list'?'icon-align-left':'icon-all'"></tm-button>
+                </view>
             </block>
         </view>
 
@@ -39,20 +72,27 @@
 
 <script>
 import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
-import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
+import tmButton from '@/tm-vuetify/components/tm-button/tm-button.vue';
 import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
 import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
 
 import MarkdownConfig from '@/common/markdown/markdown.config.js';
 import mpHtml from '@/components/mp-html/components/mp-html/mp-html.vue';
+import tmFlowLayout from '@/tm-vuetify/components/tm-flowLayout/tm-flowLayout.vue';
+import tmSliderNav from '@/tm-vuetify/components/tm-sliderNav/tm-sliderNav.vue';
+import ArticleMinCard from '@/components/article-min-card/article-min-card.vue';
+
 
 export default {
     components: {
         tmSkeleton,
-        tmFlotbutton,
+        tmButton,
         tmTranslate,
         tmEmpty,
-        mpHtml
+        mpHtml,
+        tmFlowLayout,
+        tmSliderNav,
+        ArticleMinCard
     },
     data() {
         return {
@@ -65,30 +105,58 @@ export default {
             },
             hasNext: false,
             dataList: [],
+            categoryList: [],
             isLoadMore: false,
-            loadMoreText: '加载中...'
+            loadMoreText: '加载中...',
+            currentCategoryConfig: {
+                type: "list"
+            },
+            currentCategoryName: "",
+            postQueryParams: {
+                size: 10,
+                page: 0,
+            },
+            postList: [],
+            triggered: false,
+            scrollTop: 0,
+            tempScrollTop: 0,
+            scrollTimeout: null,
         };
     },
     computed: {
         haloConfigs() {
             return this.$tm.vx.getters().getConfigs;
         },
-        calcAuditModeEnabled(){
+        calcAuditModeEnabled() {
             return this.haloConfigs.auditConfig.auditModeEnabled
         },
         mockJson() {
             return this.$tm.vx.getters().getMockJson;
+        },
+        categoryConfig() {
+            return this.haloConfigs.pageConfig.categoryConfig
+        },
+        calcShowType() {
+            return this.currentCategoryConfig.type
         }
     },
-    onLoad() {
-        this.fnGetData();
+    watch: {
+        categoryConfig: {
+            deep: true,
+            immediate: true,
+            handler(newVal) {
+                console.log("执行了", newVal)
+                if (!newVal) return;
+                this.currentCategoryConfig = newVal
+                this.handleInitPage()
+            },
+        }
     },
     onPullDownRefresh() {
         this.isLoadMore = false;
         this.queryParams.page = 0;
         this.fnGetData();
     },
-
     onReachBottom(e) {
         if (this.calcAuditModeEnabled) {
             uni.showToast({
@@ -98,7 +166,12 @@ export default {
             return
         }
         if (this.hasNext) {
-            this.queryParams.page += 1;
+            if (this.calcShowType === 'list') {
+
+                this.queryParams.page += 1;
+            } else {
+                this.postQueryParams.page += 1;
+            }
             this.isLoadMore = true;
             this.fnGetData();
         } else {
@@ -109,8 +182,37 @@ export default {
         }
     },
     methods: {
+        fnChangeShowType() {
+            if (this.calcShowType === 'list-post') {
+                this.currentCategoryConfig.type = 'list'
+            } else {
+                this.currentCategoryConfig.type = 'list-post'
+            }
+            this.handleInitPage();
+        },
+        handleResetInit() {
+            this.postList = []
+            this.dataList = []
+            this.categoryList = []
+            this.queryParams.page = 0;
+            this.postQueryParams.page = 0;
+            this.hasNext = false
+            this.isLoadMore = false
+            this.loadMoreText = '加载中...'
+            this.currentCategoryName = ""
+            this.triggered = false
+            this.fnResetSetAniWaitIndex()
+        },
+        handleInitPage() {
+            this.handleResetInit()
+            if (this.calcShowType === 'list-post') {
+                this.queryParams.size = 99999
+            }
+            this.fnGetData();
+        },
         fnGetData() {
             if (this.calcAuditModeEnabled) {
+                this.categoryConfig.type = "list"
                 this.dataList = this.mockJson.category.list.map((item) => {
                     return {
                         metadata: {
@@ -143,21 +245,37 @@ export default {
                 .then(res => {
                     console.log('请求结果:');
                     console.log(res);
+                    if (this.calcShowType === 'list') {
+                        this.loading = 'success';
+                        this.loadMoreText = res.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
+                        // 处理数据
+                        this.hasNext = res.hasNext;
 
-                    this.loading = 'success';
-                    this.loadMoreText = res.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
-                    // 处理数据
-                    this.hasNext = res.hasNext;
+                        const tempItems = res.items.map(item => {
+                            item.spec.cover = this.$utils.checkThumbnailUrl(item.spec.cover, true)
+                            return item;
+                        })
 
-                    const tempItems = res.items.map(item => {
-                        item.spec.cover = this.$utils.checkThumbnailUrl(item.spec.cover, true)
-                        return item;
-                    })
-
-                    if (this.isLoadMore) {
-                        this.dataList = this.dataList.concat(tempItems);
+                        if (this.isLoadMore) {
+                            this.dataList = this.dataList.concat(tempItems);
+                        } else {
+                            this.dataList = tempItems;
+                        }
                     } else {
-                        this.dataList = tempItems;
+                        this.dataList = res.items
+                        this.categoryList = res.items.map(item => {
+                            return {
+                                displayName: item.spec.displayName,
+                                name: item.metadata.name,
+                                ...item,
+                            }
+                        })
+                        this.triggered = false;
+                        this.loading = 'success';
+                        if (this.dataList.length !== 0) {
+                            this.currentCategoryName = this.dataList[0].metadata.name;
+                            this.fnGetPostByCategory()
+                        }
                     }
                 })
                 .catch(err => {
@@ -185,6 +303,84 @@ export default {
             uni.navigateTo({
                 url: `/pagesA/category-detail/category-detail?name=${data.metadata.name}&title=${data.spec.displayName}`
             })
+        },
+        fnGetPostByCategory(isPulldownRefresh = true, triggered = true) {
+            if (!isPulldownRefresh) {
+                if (this.hasNext) {
+                    this.postQueryParams.page += 1;
+                } else {
+                    return uni.showToast({
+                        icon: 'none',
+                        title: '没有更多数据了'
+                    });
+                }
+            } else {
+                this.postQueryParams.page = 0;
+                if (triggered) {
+                    this.triggered = true;
+                }
+            }
+
+            this.$httpApi.v2
+                .getCategoryPostList(this.currentCategoryName, this.postQueryParams)
+                .then(res => {
+                    this.hasNext = res.hasNext;
+
+                    if (!isPulldownRefresh) {
+                        this.postList = this.postList.concat(res.items);
+                    } else {
+                        this.postList = res.items;
+                    }
+                    this.loadMoreText = res.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
+                })
+                .catch(err => {
+                    this.loadMoreText = '加载失败!';
+                })
+                .finally(() => {
+                    this.triggered = false;
+                });
+        },
+
+        fnOnCategoryChange(e) {
+            this.fnResetSetAniWaitIndex();
+            this.currentCategoryName = this.dataList[e].metadata.name;
+            this.fnToTopScroll();
+            this.postList = [];
+            this.fnGetPostByCategory();
+        },
+
+        fnOnScroll(e) {
+            this.tempScrollTop = e.detail.scrollTop;
+        },
+        fnToTopScroll() {
+            uni.pageScrollTo({
+                scrollTop: 0,
+                duration: 500
+            });
+            this.scrollTop = 0;
+            this.tempScrollTop = 0;
+        },
+        fnOnTouchStart() {
+            clearTimeout(this.scrollTimeout);
+        },
+        fnOnTouchEnd() {
+            this.scrollTimeout = setTimeout(() => {
+                this.scrollTop = this.tempScrollTop;
+            }, 500);
+        },
+        //跳转文章详情
+        fnToArticleDetail(post) {
+            uni.navigateTo({
+                url: '/pagesA/article-detail/article-detail?name=' + post.metadata.name,
+                animationType: 'slide-in-right'
+            });
+        },
+        fnScrollTop() {
+            if (this.calcShowType === 'list') {
+                this.fnToTopPage()
+            } else {
+                this.fnToTopScroll()
+            }
         }
     }
 };
@@ -216,8 +412,14 @@ export default {
     flex-wrap: wrap;
     padding: 0 12rpx;
     gap: 20rpx 0;
+
+    &.list-post {
+        padding: 0;
+        gap: 0;
+    }
 }
 
+
 .catgory-card {
     width: 100%;
     height: 200rpx;
@@ -259,4 +461,14 @@ export default {
     width: 100%;
     text-align: center;
 }
+
+.flot-buttons {
+    position: fixed;
+    bottom: 100rpx;
+    right: 32rpx;
+    flex-direction: column;
+    display: flex;
+    gap: 6rpx;
+    z-index: 999;
+}
 </style>

+ 4 - 5
store/config.js

@@ -5,7 +5,7 @@
  *  时间:2024年06月22日 12:00:44
  *  版本:v0.1.0
  */
-import {DefaultAppConfigs, getAppConfigs, setAppConfigs,setAppMockJson,getAppMockJson} from '@/config/index.js'
+import {DefaultAppConfigs, getAppConfigs, getAppMockJson, setAppConfigs, setAppMockJson} from '@/config/index.js'
 import v2Config from '@/api/v2/all.config.js'
 import utils from '@/utils/index.js'
 
@@ -21,7 +21,7 @@ export default {
             return getAppConfigs()
         },
         getMockJson(state) {
-            if(state.mockJson) return state.mockJson;
+            if (state.mockJson) return state.mockJson;
             return getAppMockJson()
         }
     },
@@ -36,12 +36,12 @@ export default {
         }
     },
     actions: {
-        fetchConfigs({commit, dispatch}) {
+        fetchConfigs({state, commit, dispatch}) {
             return new Promise(async (resolve, reject) => {
                 try {
                     const res = await v2Config.getAppConfigs()
                     if (res) {
-                        commit('setConfigs', res)
+                        commit('setConfigs', utils.deepMerge(DefaultAppConfigs, res))
                         resolve(res)
                     } else {
                         dispatch("setDefaultAppSettings");
@@ -65,7 +65,6 @@ export default {
                     url: mockJsonUrl,
                     method: "GET",
                     success: (res) => {
-                        console.log("mockJson", res.data)
                         commit('setMockJson', res.data)
                         resolve({
                             ok: true,

+ 23 - 0
utils/index.js

@@ -178,7 +178,30 @@ const utils = {
                 jsonData: {},
             }
         }
+    },
+    isObject(obj) {
+        return obj && typeof obj === 'object' && !Array.isArray(obj);
+    },
+    deepMerge(target, source) {
+        let output = Object.assign({}, target);
+
+        if (this.isObject(target) && this.isObject(source)) {
+            Object.keys(source).forEach(key => {
+                const targetValue = target[key];
+                const sourceValue = source[key];
+
+                if (Array.isArray(targetValue) && Array.isArray(sourceValue)) {
+                    output[key] = targetValue.concat(sourceValue);
+                } else if (this.isObject(targetValue) && this.isObject(sourceValue)) {
+                    output[key] = this.deepMerge(targetValue, sourceValue);
+                } else {
+                    output[key] = sourceValue;
+                }
+            });
+        }
+        return output;
     }
+
 };