1
0
mirror of https://github.com/ialley-workshop-open/uni-halo.git synced 2026-06-10 11:59:28 +08:00

refactor: 将页面配置通过插件动态化配置(plugin-uni-halo)

This commit is contained in:
小莫唐尼
2024-06-24 18:59:05 +08:00
parent 959acab9c7
commit e17edade28
54 changed files with 5299 additions and 5653 deletions
-1
View File
@@ -4,7 +4,6 @@ package-lock.json
.idea
config/halo.config.js
config/ad.config.js
config/love.config.js
config/token.config.js
config/plugins.config.js
+7 -17
View File
@@ -1,7 +1,5 @@
<script>
import HaloTokenConfig from '@/config/token.config.js';
import HaloConfig from '@/config/halo.config.js';
import HaloAdConfig from '@/config/ad.config.js';
// app升级检测(搭配:https://ext.dcloud.net.cn/plugin?id=4470 升级中心)
import CheckAppUpdate from '@/uni_modules/uni-upgrade-center-app/utils/check-update';
@@ -10,9 +8,7 @@
} from '@/utils/update.js';
export default {
globalData: {
baseApiUrl: HaloTokenConfig.BASE_API,
...HaloConfig,
haloAdConfig: HaloAdConfig
baseApiUrl: HaloTokenConfig.BASE_API
},
onLaunch: function() {
console.log('App Launch');
@@ -23,20 +19,14 @@
// #ifdef MP-WEIXIN
CheckWxUpdate();
uni.$tm.vx.commit('setWxShare', HaloConfig.wxShareConfig);
// #endif
// 监听中间按钮(暂时没有使用)
uni.onTabBarMidButtonTap(() => {
console.log('点击中间按钮');
});
// 初始化博主信息
uni.$tm.vx.actions('blogger/fnGetBlogger');
// 临时:检查是否有用户,没有的话添加一个默认的用户
uni.$tm.vx.actions('user/checkAndSetDefaultUser');
uni.$tm.vx.actions('config/fetchConfigs').then((res) => {
console.log('正常:', res)
// #ifdef MP-WEIXIN
uni.$tm.vx.commit('setWxShare', res.shareConfig);
// #endif
})
// 启动检查app的配置是否已经就绪,若未就绪则设置默认的
uni.$tm.vx.actions('setting/checkAndSetDefaultAppSettings');
},
+5 -5
View File
@@ -10,19 +10,19 @@
* 修改时间:
*/
import HttpHandler from '@/common/http/request.js'
// 2.0接口
import v2 from './v2/all.api.js'
import v2Config from './v2/all.config.js'
const ApiManager = {
v2
v2,
v2Config,
};
const install = (Vue) => {
Vue.prototype.$httpApi = ApiManager
Vue.prototype.$httpApi = ApiManager
}
export default {
install
install
}
+164 -163
View File
@@ -3,191 +3,192 @@
*/
import HaloTokenConfig from '@/config/token.config.js'
import HttpHandler from '@/common/http/request.js'
import {
getCache
} from '@/utils/storage.js'
import HaloPluginsConfig from '@/config/plugins.config.js'
getAppConfigs
} from '@/config/index.js'
export default {
/**
* 获取文章列表
* @param {Object} params 参数
*/
getPostList: (params) => {
return HttpHandler.Get(`/apis/api.content.halo.run/v1alpha1/posts`, params)
},
/**
* 获取文章列表
* @param {Object} params 参数
*/
getPostList: (params) => {
return HttpHandler.Get(`/apis/api.content.halo.run/v1alpha1/posts`, params)
},
/**
* 根据名称获取文章
* @param {String} name 分类名称
*/
getPostByName: (name) => {
return HttpHandler.Get(`/apis/api.content.halo.run/v1alpha1/posts/${name}`, {}, {
header: {
'Wechat-Session-Id': uni.getStorageSync('openid'),
}
})
},
/**
* 根据名称获取文章
* @param {String} name 分类名称
*/
getPostByName: (name) => {
return HttpHandler.Get(`/apis/api.content.halo.run/v1alpha1/posts/${name}`, {}, {
header: {
'Wechat-Session-Id': uni.getStorageSync('openid'),
}
})
},
/**
* 搜索文章
* @param {Object} params 数据
*/
getPostListByKeyword: (params) => {
return HttpHandler.Get(`/apis/api.halo.run/v1alpha1/indices/post`, params)
},
/**
* 搜索文章
* @param {Object} params 数据
*/
getPostListByKeyword: (params) => {
return HttpHandler.Get(`/apis/api.halo.run/v1alpha1/indices/post`, params)
},
/**
* 查询分类列表
* @param {Object} params 查询参数
*/
getCategoryList: (params) => {
return HttpHandler.Get('/apis/api.content.halo.run/v1alpha1/categories', params)
},
/**
* 查询分类下的文章
* @param {String} name 分类名称
* @param {Object} params 查询参数
*/
getCategoryPostList: (name, params) => {
return HttpHandler.Get(`/apis/api.content.halo.run/v1alpha1/categories/${name}/posts`, params)
},
/**
* 查询分类列表
* @param {Object} params 查询参数
*/
getCategoryList: (params) => {
return HttpHandler.Get('/apis/api.content.halo.run/v1alpha1/categories', params)
},
/**
* 查询分类下的文章
* @param {String} name 分类名称
* @param {Object} params 查询参数
*/
getCategoryPostList: (name, params) => {
return HttpHandler.Get(`/apis/api.content.halo.run/v1alpha1/categories/${name}/posts`, params)
},
/**
* 获取评论列表接口(列表数据)
* @param {Object} params 查询参数
*/
getPostCommentList: (params) => {
return HttpHandler.Get(`/apis/api.halo.run/v1alpha1/comments`, params)
},
/**
* 获取评论列表接口(列表数据)
* @param {Object} params 查询参数
*/
getPostCommentList: (params) => {
return HttpHandler.Get(`/apis/api.halo.run/v1alpha1/comments`, params)
},
/**
* 获取回复列表
* @param {String} commentName 名称
* @param {Object} params 查询参数
*/
getPostCommentReplyList: (commentName, params) => {
return HttpHandler.Get(`/apis/api.halo.run/v1alpha1/comments/${commentName}/reply`, params)
},
/**
* 获取回复列表
* @param {String} commentName 名称
* @param {Object} params 查询参数
*/
getPostCommentReplyList: (commentName, params) => {
return HttpHandler.Get(`/apis/api.halo.run/v1alpha1/comments/${commentName}/reply`, params)
},
// 提交评论
addPostComment: (data) => {
return HttpHandler.Post(`/apis/api.halo.run/v1alpha1/comments`, data)
},
// 提交回复
addPostCommentReply: (commentName, data) => {
return HttpHandler.Post(`/apis/api.halo.run/v1alpha1/comments/${commentName}/replay`, data)
},
// 提交评论
addPostComment: (data) => {
return HttpHandler.Post(`/apis/api.halo.run/v1alpha1/comments`, data)
},
// 提交回复
addPostCommentReply: (commentName, data) => {
return HttpHandler.Post(`/apis/api.halo.run/v1alpha1/comments/${commentName}/replay`, data)
},
/**
* 获取标签列表
* @param {Object} params 查询参数
*/
getTagList: (params) => {
return HttpHandler.Get(`/apis/api.content.halo.run/v1alpha1/tags`, params)
},
/**
* 获取标签列表
* @param {Object} params 查询参数
*/
getTagList: (params) => {
return HttpHandler.Get(`/apis/api.content.halo.run/v1alpha1/tags`, params)
},
/**
* 根据标签获取文章列表
* @param {String} tagName 参数
* @param {Object} params 查询参数
*/
getPostByTagName: (tagName, params) => {
return HttpHandler.Get(`/apis/api.content.halo.run/v1alpha1/tags/${tagName}/posts`, params)
},
/**
* 根据标签获取文章列表
* @param {String} tagName 参数
* @param {Object} params 查询参数
*/
getPostByTagName: (tagName, params) => {
return HttpHandler.Get(`/apis/api.content.halo.run/v1alpha1/tags/${tagName}/posts`, params)
},
/**
* 获取瞬间列表
*/
getMomentList: (params) => {
return HttpHandler.Get(`/apis/moment.halo.run/v1alpha1/moments`, params, {
custom: {
systemToken: HaloTokenConfig.systemToken
}
})
},
/**
* 获取瞬间列表
*/
getMomentList: (params) => {
return HttpHandler.Get(`/apis/moment.halo.run/v1alpha1/moments`, params, {
custom: {
systemToken: HaloTokenConfig.systemToken
}
})
},
/**
* 查询站点统计信息
*/
getBlogStatistics: () => {
return HttpHandler.Get(`/apis/api.halo.run/v1alpha1/stats/-`, {})
},
/**
* 查询站点统计信息
*/
getBlogStatistics: () => {
return HttpHandler.Get(`/apis/api.halo.run/v1alpha1/stats/-`, {})
},
/**
* 获取相册分组
*/
getPhotoGroupList: (params) => {
return HttpHandler.Get(`/apis/core.halo.run/v1alpha1/photogroups`, params, {
custom: {
systemToken: HaloTokenConfig.systemToken
}
})
},
/**
* 获取相册分组
*/
getPhotoGroupList: (params) => {
return HttpHandler.Get(`/apis/core.halo.run/v1alpha1/photogroups`, params, {
custom: {
systemToken: HaloTokenConfig.systemToken
}
})
},
/**
* 根据分组获取相册
*/
getPhotoListByGroupName: (params) => {
return HttpHandler.Get(`/apis/console.api.photo.halo.run/v1alpha1/photos`, params, {
custom: {
systemToken: HaloTokenConfig.systemToken
}
})
},
/**
* 根据分组获取相册
*/
getPhotoListByGroupName: (params) => {
return HttpHandler.Get(`/apis/console.api.photo.halo.run/v1alpha1/photos`, params, {
custom: {
systemToken: HaloTokenConfig.systemToken
}
})
},
/**
* 获取友链
*/
getFriendLinkList: (params) => {
return HttpHandler.Get(`/apis/api.plugin.halo.run/v1alpha1/plugins/PluginLinks/links`, params)
},
/**
* 获取友链
*/
getFriendLinkList: (params) => {
return HttpHandler.Get(`/apis/api.plugin.halo.run/v1alpha1/plugins/PluginLinks/links`, params)
},
/**
* 校验文章访问密码
*/
checkPostVerifyCode: (verifyCode, postId) => {
return HttpHandler.Get(`/apis/tools.muyin.site/v1alpha1/verificationCode/check?code=${verifyCode}`, null, {
header: {
'Authorization': HaloPluginsConfig.toolsPlugin.Authorization,
'Wechat-Session-Id': uni.getStorageSync('openid'),
'Post-Id': postId
}
})
},
/**
* 校验文章访问密码
*/
checkPostVerifyCode: (verifyCode, postId) => {
return HttpHandler.Get(`/apis/tools.muyin.site/v1alpha1/verificationCode/check?code=${verifyCode}`, null, {
header: {
'Authorization': getAppConfigs().pluginConfig.toolsPlugin?.Authorization,
'Wechat-Session-Id': uni.getStorageSync('openid'),
'Post-Id': postId
}
})
},
/**
* 校验文章访问密码
*/
checkPostPasswordAccess: (password, postId) => {
return HttpHandler.Get(`/apis/tools.muyin.site/v1alpha1/visitPassword/checkPost?password=${password}`, null, {
header: {
'Authorization': HaloPluginsConfig.toolsPlugin.Authorization,
'Wechat-Session-Id': uni.getStorageSync('openid'),
'Post-Id': postId
}
})
},
/**
* 校验文章访问密码
*/
checkPostPasswordAccess: (password, postId) => {
return HttpHandler.Get(`/apis/tools.muyin.site/v1alpha1/visitPassword/checkPost?password=${password}`,
null, {
header: {
'Authorization': getAppConfigs().pluginConfig.toolsPlugin?.Authorization,
'Wechat-Session-Id': uni.getStorageSync('openid'),
'Post-Id': postId
}
})
},
/**
* 获取文章验证码
*/
getPostVerifyCode: () => {
return HttpHandler.Get(`/apis/tools.muyin.site/v1alpha1/verificationCode/create`, null, {
header: {
'Authorization': HaloPluginsConfig.toolsPlugin.Authorization
}
})
},
/**
* 提交友情链接
*/
submitLink(form) {
return HttpHandler.Post(`/apis/linksSubmit.muyin.site/v1alpha1/submit`, form, null)
}
/**
* 获取文章验证码
*/
getPostVerifyCode: () => {
return HttpHandler.Get(`/apis/tools.muyin.site/v1alpha1/verificationCode/create`, null, {
header: {
'Authorization': getAppConfigs().pluginConfig.toolsPlugin?.Authorization,
}
})
},
/**
* 提交友情链接
*/
submitLink(form) {
return HttpHandler.Post(`/apis/linksSubmit.muyin.site/v1alpha1/submit`, form, null)
}
}
+10
View File
@@ -0,0 +1,10 @@
import HttpHandler from '@/common/http/request.js'
export default {
/**
* 获取应用基本配置
*/
getAppConfigs: () => {
return HttpHandler.Get(`/apis/api.uni.uhalo.pro/v1alpha1/plugins/plugin-uni-halo/getConfigs`, {})
},
}
-1
View File
@@ -10,7 +10,6 @@
* 修改时间:
*/
import HaloConfig from '@/config/halo.config.js'
import HaloTokenConfig from '@/config/token.config.js'
import {
setInterceptors
+5 -3
View File
@@ -2,7 +2,9 @@
* markdown配置
*/
import HaloConfig from '@/config/halo.config.js'
import {
getAppConfigs
} from '@/config/index.js'
import HaloTokenConfig from '@/config/token.config.js'
export default {
domain: HaloTokenConfig.BASE_API,
@@ -93,6 +95,6 @@ export default {
},
containStyle: 'font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;padding:12px;font-size: 14px;color: #606266;word-spacing: 0.8px;letter-spacing: 0.8px;border-radius: 6px;background-color:#FFFFFF;',
loadingGif: HaloConfig.loadingGifUrl,
emptyGif: HaloConfig.loadingEmptyUrl,
loadingGif: getAppConfigs().imagesConfig.loadingGifUrl,
emptyGif: getAppConfigs().imagesConfig.loadingEmptyUrl,
}
+82 -78
View File
@@ -9,85 +9,89 @@
* 修改人员:
* 修改时间:
*/
import HaloConfig from '@/config/halo.config.js';
import HaloAdConfig from '@/config/ad.config.js';
import HaloPluginsConfig from '@/config/plugins.config.js';
export default {
install(Vue) {
Vue.mixin({
data() {
return {
author: HaloConfig.author,
_isWechat: true,
haloConfig: HaloConfig,
haloAdConfig: HaloAdConfig,
haloPluginsConfig: HaloPluginsConfig,
_aniWaitIndex: 0, // 动画索引
};
},
computed: {
// 获取全局应用设置
globalAppSettings() {
return uni.$tm.vx.getters().getSettings;
},
// 计算动画索引
calcAniWait() {
return (index) => {
if ((index + 1) % 10 == 0) {
this._aniWaitIndex = 1;
} else {
this._aniWaitIndex += 1;
}
console.log('this._aniWaitIndex', this._aniWaitIndex);
return this._aniWaitIndex * 50
}
}
},
onLoad() {
this.fnResetSetAniWaitIndex()
},
created() {
// #ifdef MP-WEIXIN
this._isWechat = true;
uni.$tm.vx.commit('setWxShare', HaloConfig.wxShareConfig);
// #endif
// #ifndef MP-WEIXIN
this._isWechat = false;
// #endif
},
onShow() {
this.fnResetSetAniWaitIndex()
},
methods: {
/**
* 设置页面标题
* @param {Object} title 标题
*/
fnSetPageTitle(title) {
uni.setNavigationBarTitle({
title: title || HaloConfig.title
})
},
install(Vue) {
Vue.mixin({
data() {
return {
_isWechat: true,
_aniWaitIndex: 0
};
},
computed: {
haloConfig() {
return this.$tm.vx.getters().getConfigs;
},
haloPluginsConfig() {
return this.$tm.vx.getters().getConfigs?.pluginConfig;
},
// 获取全局应用设置
globalAppSettings() {
return uni.$tm.vx.getters().getSettings;
},
// 计算动画索引
calcAniWait() {
return (index) => {
if ((index + 1) % 10 === 0) {
this._aniWaitIndex = 1;
} else {
this._aniWaitIndex += 1;
}
return this._aniWaitIndex * 50
}
}
},
watch: {
haloConfig: {
deep: true,
immediate: true,
handler(newVal) {
if (!newVal) return;
// #ifdef MP-WEIXIN
uni.$tm.vx.commit('setWxShare', newVal.shareConfig);
// #endif
}
}
},
onLoad() {
this.fnResetSetAniWaitIndex()
},
created() {
// #ifdef MP-WEIXIN
this._isWechat = true;
// #endif
// #ifndef MP-WEIXIN
this._isWechat = false;
// #endif
},
onShow() {
this.fnResetSetAniWaitIndex()
},
methods: {
// 设置页面标题
fnSetPageTitle(title) {
uni.setNavigationBarTitle({
title: title || (this.haloConfig && this.haloConfig.startConfig.title) || "uni-halo",
})
},
/**
* 页面返回顶部
*/
fnToTopPage(duration = 500) {
duration = isNaN(duration) ? 500 : duration
uni.pageScrollTo({
scrollTop: 0,
duration: duration,
fail: (err) => {
console.log('err:', err);
},
});
},
// 初始化动画索引值(需要在每个页面调用)
fnResetSetAniWaitIndex() {
this._aniWaitIndex = 0
}
},
});
},
// 页面返回顶部
fnToTopPage(duration = 500) {
duration = isNaN(duration) ? 500 : duration
uni.pageScrollTo({
scrollTop: 0,
duration: duration,
fail: (err) => {
console.log('err:', err);
},
});
},
// 初始化动画索引值(需要在每个页面调用)
fnResetSetAniWaitIndex() {
this._aniWaitIndex = 0
}
},
});
},
};
+7 -8
View File
@@ -1,16 +1,15 @@
// 微信分享配置
import haloConfig from '@/config/halo.config.js'
import HaloTokenConfig from '@/config/token.config.js'
import { jsonToUrlParams2 } from '@/utils/url.params.js'
import {
jsonToUrlParams2
} from '@/utils/url.params.js'
export const haloWxShareMixin = {
data() {
return {
haloWxShareData: {
...haloConfig.wxShareConfig
},
computed: {
haloWxShareData() {
const configs = this.$tm.vx.getters().getConfigs;
return configs.shareConfig || {}
}
},
//#ifdef MP-WEIXIN
onShareAppMessage(res) {
return {
+7 -3
View File
@@ -10,7 +10,8 @@
<text class="img-load-text">{{ loadErrText }}</text> -->
<image class="img-error-img" :src="loadingErrorImageSrc" mode="scaleToFill"></image>
</view>
<image v-show="loadStatus == 'success'" :src="src" @load="fnOnLoad" @error="fnOnError" :lazy-load="lazyLoad" :style="[imgStyle]" :mode="mode" @click="$emit('on-click', url)"></image>
<image v-show="loadStatus == 'success'" :src="src" @load="fnOnLoad" @error="fnOnError" :lazy-load="lazyLoad"
:style="[imgStyle]" :mode="mode" @click="$emit('on-click', url)"></image>
</view>
</template>
@@ -91,11 +92,14 @@
};
},
computed: {
imagesConfig() {
return this.$tm.vx.getters().getConfigs.imagesConfig
},
loadingImgSrc() {
return getApp().globalData.loadingGifUrl;
return this.imagesConfig.loadingGifUrl;
},
loadingErrorImageSrc() {
return getApp().globalData.loadingErrUrl
return this.imagesConfig.loadingErrUrl
}
},
watch: {
@@ -1,6 +1,6 @@
<template>
<view class="category-mini-card">
<cache-image class="img" height="180rpx" :url="$utils.checkThumbnailUrl(category.spec.cover,true)"
<cache-image class="img" height="180rpx" :url="$utils.checkThumbnailUrl(category.spec.cover,false)"
:fileMd5="$utils.checkThumbnailUrl(category.spec.cover)" mode="aspectFill"></cache-image>
<view class="content">
<view class="name">{{ category.spec.displayName }}</view>
+7 -5
View File
@@ -72,9 +72,11 @@
}
},
computed: {
// 获取博主信息
imageConfigs() {
return this.$tm.vx.getters().getConfigs.imagesConfig;
},
bloggerInfo() {
let blogger = this.$tm.vx.getters().getBlogger;
let blogger = this.$tm.vx.getters().getConfigs.authorConfig.blogger;
blogger.avatar = this.$utils.checkAvatarUrl(blogger.avatar, true);
return blogger;
}
@@ -82,10 +84,10 @@
methods: {
fnOnImageError(data) {
if (data && data.owner) {
if (this.$haloConfig.defaultAvatarUrl.indexOf('?') == -1) {
data.owner.avatar = `${this.$haloConfig.defaultAvatarUrl}?next-v=${new Date().getTime()}`
if (this.imageConfigs.defaultAvatarUrl.indexOf('?') == -1) {
data.owner.avatar = `${this.imageConfigs.defaultAvatarUrl}?next-v=${new Date().getTime()}`
} else {
data.owner.avatar = `${this.$haloConfig.defaultAvatarUrl}&next-v=${new Date().getTime()}`
data.owner.avatar = `${this.imageConfigs.defaultAvatarUrl}&next-v=${new Date().getTime()}`
}
}
}
+126 -144
View File
@@ -2,176 +2,158 @@
<view class="journal-card mb-24 round-3 bg-white ">
<view class="head pa-24 pb-0 flex flex-between">
<view class="left flex">
<cache-image
class="avatar rounded"
radius="50%"
width="70rpx"
height="70rpx"
:url="bloggerInfo.avatar"
:fileMd5="bloggerInfo.avatar"
mode="scaleToFill"
></cache-image>
<cache-image class="avatar rounded" radius="50%" width="70rpx" height="70rpx" :url="bloggerInfo.avatar"
:fileMd5="bloggerInfo.avatar" mode="scaleToFill"></cache-image>
<view class="info pl-16 flex flex-col">
<view class="nickname text-weight-b text-grey-darken-4">{{ bloggerInfo.nickname }}</view>
<view class="mt-3 time text-size-m ">{{ $tm.dayjs(journal.createTime).format('YYYY-MM-DD HH:mm:ss') }}</view>
<view class="mt-3 time text-size-m ">
{{ $tm.dayjs(journal.createTime).format('YYYY-MM-DD HH:mm:ss') }}</view>
</view>
</view>
<view class="right">
<tm-button v-if="useLike" :shadow="0" theme="light-blue" size="s" @click="fnLike(journal)">点赞({{ journal.likes }})</tm-button>
<tm-button v-if="useEdit" :shadow="0" theme="light-blue" size="s" @click="$emit('on-edit', journal)">编辑</tm-button>
<tm-button v-if="useLike" :shadow="0" theme="light-blue" size="s"
@click="fnLike(journal)">点赞({{ journal.likes }})</tm-button>
<tm-button v-if="useEdit" :shadow="0" theme="light-blue" size="s"
@click="$emit('on-edit', journal)">编辑</tm-button>
<tm-button v-if="useDel" :shadow="0" theme="red" size="s" @click="fnDel(journal)">删除</tm-button>
</view>
</view>
<tm-more v-if="journal.content.length > 50" :maxHeight="100" label="查看全部内容" open-label="隐藏部分内容">
<mp-html
class="evan-markdown"
lazy-load
:domain="markdownConfig.domain"
:loading-img="markdownConfig.loadingGif"
:scroll-table="true"
:selectable="true"
:tag-style="markdownConfig.tagStyle"
:container-style="markdownConfig.containStyle"
:content="journal.content"
:markdown="true"
:showLineNumber="true"
:showLanguageName="true"
:copyByLongPress="true"
/>
<mp-html class="evan-markdown" lazy-load :domain="markdownConfig.domain"
:loading-img="markdownConfig.loadingGif" :scroll-table="true" :selectable="true"
:tag-style="markdownConfig.tagStyle" :container-style="markdownConfig.containStyle"
:content="journal.content" :markdown="true" :showLineNumber="true" :showLanguageName="true"
:copyByLongPress="true" />
</tm-more>
<mp-html
v-else
class="evan-markdown"
lazy-load
:domain="markdownConfig.domain"
:loading-img="markdownConfig.loadingGif"
:scroll-table="true"
:selectable="true"
:tag-style="markdownConfig.tagStyle"
:container-style="markdownConfig.containStyle"
:content="journal.content"
:markdown="true"
:showLineNumber="true"
:showLanguageName="true"
:copyByLongPress="true"
/>
<mp-html v-else class="evan-markdown" lazy-load :domain="markdownConfig.domain"
:loading-img="markdownConfig.loadingGif" :scroll-table="true" :selectable="true"
:tag-style="markdownConfig.tagStyle" :container-style="markdownConfig.containStyle"
:content="journal.content" :markdown="true" :showLineNumber="true" :showLanguageName="true"
:copyByLongPress="true" />
</view>
</template>
<script>
import MarkdownConfig from '@/common/markdown/markdown.config.js';
import mpHtml from '@/components/mp-html/components/mp-html/mp-html.vue';
import tmButton from '@/tm-vuetify/components/tm-button/tm-button.vue';
import tmMore from '@/tm-vuetify/components/tm-more/tm-more.vue';
export default {
name: 'journal-card',
components: { mpHtml, tmButton, tmMore },
props: {
isAdmin: {
type: Boolean,
default: false
import MarkdownConfig from '@/common/markdown/markdown.config.js';
import mpHtml from '@/components/mp-html/components/mp-html/mp-html.vue';
import tmButton from '@/tm-vuetify/components/tm-button/tm-button.vue';
import tmMore from '@/tm-vuetify/components/tm-more/tm-more.vue';
export default {
name: 'journal-card',
components: {
mpHtml,
tmButton,
tmMore
},
journal: {
type: Object,
default: () => {}
props: {
isAdmin: {
type: Boolean,
default: false
},
journal: {
type: Object,
default: () => {}
},
useLike: {
type: Boolean,
default: false
},
useEdit: {
type: Boolean,
default: false
},
useDel: {
type: Boolean,
default: false
}
},
useLike: {
type: Boolean,
default: false
data() {
return {
markdownConfig: MarkdownConfig
};
},
useEdit: {
type: Boolean,
default: false
computed: {
bloggerInfo() {
let blogger = this.$tm.vx.getters().getConfigs.authorConfig.blogger;
blogger.avatar = this.$utils.checkAvatarUrl(blogger.avatar, true);
return blogger;
},
},
useDel: {
type: Boolean,
default: false
}
},
data() {
return {
markdownConfig: MarkdownConfig
};
},
computed: {
// 获取博主信息
bloggerInfo() {
let blogger = this.$tm.vx.getters().getBlogger;
blogger.avatar = this.$utils.checkAvatarUrl(blogger.avatar, true);
return blogger;
}
},
methods: {
fnLike(journal) {
uni.showLoading({
mask: true,
title: '正在点赞中...'
});
this.$httpApi
.postJournalLikes(journal.id)
.then(res => {
if (res.status == 200) {
journal.likes += 1;
uni.$tm.toast('o( ̄▽ ̄)d点赞成功!');
} else {
uni.$tm.toast('Ծ‸Ծ点赞失败了~');
}
})
.catch(err => {
uni.$tm.toast('Ծ‸Ծ点赞失败了~');
methods: {
fnLike(journal) {
uni.showLoading({
mask: true,
title: '正在点赞中...'
});
},
this.$httpApi
.postJournalLikes(journal.id)
.then(res => {
if (res.status == 200) {
journal.likes += 1;
uni.$tm.toast('o( ̄▽ ̄)d点赞成功!');
} else {
uni.$tm.toast('Ծ‸Ծ点赞失败了~');
}
})
.catch(err => {
uni.$tm.toast('Ծ‸Ծ点赞失败了~');
});
},
fnDel(journal) {
uni.$eShowModal({
title: '提示',
content: '您确定要删除该日记吗?',
showCancel: true,
cancelText: '否',
cancelColor: '#999999',
confirmText: '是',
confirmColor: '#03a9f4'
})
.then(res => {
this.$httpApi.admin
.deleteJournalsById(journal.id)
.then(res => {
if (res.status == 200) {
this.$emit('on-del', journal);
uni.$tm.toast('删除成功!');
} else {
fnDel(journal) {
uni.$eShowModal({
title: '提示',
content: '您确定要删除该日记吗?',
showCancel: true,
cancelText: '否',
cancelColor: '#999999',
confirmText: '是',
confirmColor: '#03a9f4'
})
.then(res => {
this.$httpApi.admin
.deleteJournalsById(journal.id)
.then(res => {
if (res.status == 200) {
this.$emit('on-del', journal);
uni.$tm.toast('删除成功!');
} else {
uni.$tm.toast('Ծ‸Ծ删除失败~');
}
})
.catch(err => {
uni.$tm.toast('Ծ‸Ծ删除失败~');
}
})
.catch(err => {
uni.$tm.toast('Ծ‸Ծ删除失败~');
});
})
.catch(() => {});
});
})
.catch(() => {});
}
}
}
};
};
</script>
<style scoped lang="scss">
.journal-card {
box-sizing: border-box;
box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.05);
overflow: hidden;
.avatar {
width: 70rpx;
height: 70rpx;
border: 6rpx solid #fff;
box-shadow: 0rpx 0rpx 24rpx rgba(0, 0, 0, 0.05);
}
.info {
justify-content: center;
.nickname {
font-size: 30rpx;
.journal-card {
box-sizing: border-box;
box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.05);
overflow: hidden;
.avatar {
width: 70rpx;
height: 70rpx;
border: 6rpx solid #fff;
box-shadow: 0rpx 0rpx 24rpx rgba(0, 0, 0, 0.05);
}
.time {
font-size: 26rpx;
.info {
justify-content: center;
.nickname {
font-size: 30rpx;
}
.time {
font-size: 26rpx;
}
}
}
}
</style>
-14
View File
@@ -1,14 +0,0 @@
/**
* 广告配置
*/
export default {
// 文章详情广告
articleDetail: {
use: true,
cover: 'https://b.925i.cn/uni_halo/uni_halo_ad_cover.png',
title: 'uni-halo 正式开源啦,欢迎来使用和体验!',
content: '基于 uni-app + halo1.x API 实现一款现代化的开源博客 / CMS 系统API开发的多端应用。功能包括:前台博客系统 和 后台管理系统,同时满足浏览和管理两端合一的需求,真正实现一个应用实现博客浏览和后台管理。',
url: 'https://uni-halo.925i.cn'
},
rewardedVideoAd: '微信小程序激励广告id' // 奖励视频广告
}
-94
View File
@@ -1,94 +0,0 @@
/**
* 功能:基础配置
* 作者:小莫唐尼
* 邮箱:studio@925i.cn
* 时间:2022年08月23日 15:19:14
* 版本:v0.1.0
* 修改记录:
* 修改内容:
* 修改人员:
* 修改时间:
*/
export default {
showCopyright: true, // 显示开源版权信息
showAbout: true, // 显示关于项目入口
uni_halo_logo: 'https://b.925i.cn/uni_halo/uni_halo_logo.png', // uni-halo的logo
title: '', // 博客标题 [建议必填]:在某些页面没有设置具体的页面名称时候,使用该值显示
miniCodeImageUrl: '', // 小程序的太阳码/二维码的图片地址 [建议必填]
aboutProfileImageUrl: '', // 关于页面中的资料卡背景图 [建议必填]
// 启动页面的配置(页面地址`/pagesA/start/start`)
start: {
use: true, // 是否使用首次启动页:用户第一次使用你的应用会显示否则不显示
title: 'uni-halo2.0', // 标题
bg: '', // 留空则使用默认 开屏首页背景,可以是颜色值或者图片图片地址
logo: 'https://b.925i.cn/uni_halo/uni_halo_logo.png', // 开屏首页图片
desc1: '准备好了吗,即刻就出发', // 描述信息1
desc2: '新触动 新感受 新体验', // 描述信息2
btnText: '立即体验'
},
// 博主信息
author: {
use: true, // 是否启用这里配置的信息,不启用则获取PC端博客设置的信息
nickname: '', // 昵称
avatar: '', // 头像
email: '', // 邮箱
description: '', // 介绍
},
// 版权信息(用于文章详情)
copyright: {
use: true, // 是否使用版权描述
author: '', // 版权归属说明
description: '', // 版权描述
violation: '', // 侵权处理说明
},
// 社交信息(将会在`/pagesA/contact/contact`页面中展示)
// 具体的某个参数值留空则不展示
social: {
qq: "", // qq号
wechat: "", // 微信号
weibo: "", // 微博地址
email: "", // 邮箱地址
blog: "", // 博客地址
juejin: "", // 掘金地址
bilibili: "", // b站地址
gitee: "", // gitee地址
github: "", // github地址
csdn: "" // CSDN地址
},
defaultThumbnailUrl: '', // 默认封面图地址
defaultStaticThumbnailUrl: '', // 静态默认封面图(不可以是随机图地址)
defaultImageUrl: '', // 默认图片地址
defaultAvatarUrl: '', // 默认头像地址
loadingGifUrl: '', // 图片加载中的地址
loadingErrUrl: '', // 图片加载失败的地址
loadingEmptyUrl: '', // 加载图片为空地址
waveImageUrl: '', // 关于页面波浪图片
// 微信分享信息
wxShareConfig: {
title: '', // 小程序分享标题[非必填]
desc: '', // 小程序分享描述[非必填]
imageUrl: '', // 小程序分享时候图片地址[非必填]
path: '/pages/index/index', // 分享路径[非必填] - 基本不需要修改
copyLink: '/pages/index/index', // 复制链接[非必填] - 基本不需要修改
query: {}, // 分享参数[非必填] - 基本不需要填写
},
colors: [
'#39B449',
'#E44C41',
'#8698A2',
'#0080FE',
'#1CBCB4',
'#6638B5',
]
}
+30
View File
@@ -0,0 +1,30 @@
// 应用设置存储key值
export const _AppConfigKey = 'APP_GLOBAL_CONFIGS';
// 默认的应用设置
export const DefaultAppConfigs = {
loveConfig: {},
imagesConfig: {},
authorConfig: {},
startConfig: {},
pluginConfig: {},
adConfig: {},
}
/**
* 获取应用设置
*/
export const getAppConfigs = () => {
let configs = uni.getStorageSync(_AppConfigKey)
if (configs) return JSON.parse(configs)
uni.setStorageSync(_AppConfigKey, JSON.stringify(DefaultAppConfigs))
return configs;
}
/**
* 保存应用设置
*/
export const setAppConfigs = (configs) => {
uni.setStorageSync(_AppConfigKey, JSON.stringify(configs))
}
-148
View File
@@ -1,148 +0,0 @@
/**
* 恋爱日记配置
*/
export default {
waveImageUrl: 'https://b.925i.cn/uni_halo/uni_halo_about_wave.gif', // 波浪图片地址
bgImageUrl: 'https://b.925i.cn/uni_halo_love/love_bg1.png', // 背景图片
loveImageUrl: 'https://b.925i.cn/uni_halo_love/like.png', // 爱心图片
boy: {
name: '未知男主',
avatar: 'https://b.925i.cn/uni_halo_love/love_boy.png',
birthday: '2022-09-25', // 生日
},
girl: {
name: '未知女主',
avatar: 'https://b.925i.cn/uni_halo_love/love_girl.png',
birthday: '2022-04-19', // 生日
},
timeTitle: '这是我们一起走过的',
loveStartDate: '2022-04-10 13:14:20', // 恋爱开始时间
nav: [{
key: 'journey',
use: true,
iconImageUrl: 'https://b.925i.cn/uni_halo_love/diandian.png',
title: '关于我们',
desc: '我们一起度过的那些经历'
},
// {
// key: 'album',
// use: true,
// iconImageUrl: 'https://b.925i.cn/uni_halo_love/diandian.png',
// title: '恋爱相册',
// desc: '定格了我们的那些小美好'
// },
{
key: 'list',
use: true,
iconImageUrl: 'https://b.925i.cn/uni_halo_love/diandian.png',
title: '恋爱清单',
desc: '你我之间的约定我们都在努力实现'
},
],
// 关于我们:支持富文本内容
journey: `
准备晚安啦,睡觉前讲个故事吧~<p>槐树庄的村口有一棵大槐树,树下的村口第一家就是猫奶奶的家。</p><p>猫奶奶是一位孤寡老人,因为她经常收留和救治周围的流浪猫,所以村民就都管她叫“猫奶奶”。</p><p>一个月圆之夜,猫奶奶走到院门口,忽然发现门口石级上放着一个红毯子,里面包着一个啼(tí)哭的女婴。</p><p>猫奶奶找不到女婴的父母,只好收留了她,并给她起了个名字叫樱红。</p><p>猫奶奶辛苦地抚育着樱红成长,转眼之间,樱红已经九岁,上小学三年级了。</p><p>从樱红懂事起,猫奶奶就爱给她讲一个睡前故事,那是当地一个古老的传说。</p><p>在浓郁的树影深处有一个百花园,百花园里生长着奇花异草,还住了一个会唱歌的花仙子。花仙子的歌声美丽动人,能治百病。但是那里有一条奇怪的规矩,寻找花仙子的人在进入百花园后,见到花仙子之前,都不能发出一点声音,不然花仙子就不会出来见他。</p><p>受这个故事的影响,樱红特别喜欢唱歌。</p><p>这天晚上,樱红放学回家,家家户户炊烟袅(niǎo)袅,而自家烟囱却连一丝一缕(lǚ)的炊烟都没有。</p><p>樱红一惊,冲进院门一看,果然出事了!只见猫奶奶呻吟着倒在灶台前,双目紧闭,两只小脚也在不停地抽搐(chù)。</p><p>樱红慌了,好在有邻居的帮助,猫奶奶被送到了医院。经过抢救,猫奶奶总算醒过来,但是却半身不遂(suí),说话也不利落了。</p><p>猫奶奶不能下地行走做家务,小小的樱红,一夜之间就挑起了家庭的重担。</p><p>樱红一面求助于村委会,四处寻医问药,让猫奶奶获得进一步的治疗;一面在课余学做家务,悉心照顾猫奶奶,端水喂饭,不辞辛苦。</p><p>自从猫奶奶病倒以后,樱红每天早晨推开院门就会看见门前放着一朵小花,有时还会有一两尾鲜活的鲑(guī)鱼。</p><p>这样过了三个月,好奇的樱红在一个夜晚悄悄躲在院门的后面,想看看到底是谁。</p><p>到了午夜十二点,只见一只花猫衔着一棵风铃草来到院门前,把风铃草放下,转身就走。(浪漫童话小故事)樱红认出这只小花猫曾经被猫奶奶救助过,于是,她悄悄地尾随小花猫往前走。</p><p>不一会儿,她就发现自己进入了一个从未见过的世界:蔚蓝的天空飘着七色的云,阳光千丝万缕地落下来,鲜花盛开,彩蝶飞舞,百鸟齐鸣。</p><p>这到底是什么地方?她忽然想起了那个传说,这该不会就是花仙子住的百花园吧?</p><p>樱红几乎惊叫起来,但她立即想起了那条在见到花仙子之前,不能发出一点声音的规矩。于是她捂紧了嘴巴。</p><p>这时,她发现百花园里除了自己还有一个面色苍白的男孩子,闭着眼睛,右手攥着一根竹竿摸索着前行,应该是眼睛看不见了。</p><p>只见男孩子慢慢地偏离了路径,马上就要掉进路边的水沟里了。</p><p>樱红下意识地大声呼喊:“站住,小心脚底下!”一张口,樱红才想起来,自己已经坏了规矩!</p><p>此时,“轰隆”一声巨响后,眼前的一切都消失了,樱红仍然站在自家院门前的大槐树下。</p><p>真遗憾啊!樱红深深叹了口气,可为了救人,她并不觉得后悔。</p><p>第二天早上,樱红被一种美妙的歌声唤醒。</p><p>唱歌的人就是美丽的花仙子,她乘坐着奇花异草编成的花篮,飘进了她家的院子里。</p><p>奇迹发生了,只见猫奶奶起身下床,像健康人一样走出房门。</p><p>猫奶奶看到了花仙子,不敢相信地揉着眼睛说:“你就是传说中的花仙子吗?是你治好了我的病?”</p><p>花仙子说:“是的!是这个小女孩的善良打动了我,连我那不能出声的规矩都要为她破例了。”</p><p>樱红高兴地看着猫奶奶。从此,她和猫奶奶继续幸福地生活着。</p>
`,
// 恋爱相册
albumKeyName: '恋爱相册', // 对应后台的图库分组名称
// 恋爱清单
loveList: {
useApi: false, // 是否启用api接口
api: '', // api 接口(如果使用api接口的方式,则下方的data可以留空,但是api接口必须按照对应的数据格式返回)
data: [{
index: 0, // 序号
finish: true, // 是否已完成
title: '偷偷记录对方熟睡的模样', // 事件名称
desc: '偷偷观察对方熟睡的模样,记录下来', // 事件描述
detail: {
start: '2022年05月20日', // 计划开始时间
desc: '偷偷观察对方熟睡的模样,记录下来', // 事件详细描述
end: '每天', // 完成时间,
moment: '', // 完成瞬间的记录
other: '', // 其他说明
}
}, {
index: 1,
finish: false,
title: '陪对方过生日',
desc: '陪对方一起过生日',
detail: {
start: '2023年05月20日',
desc: '陪对方一起过生日,他和我的生日',
end: '',
moment: '',
other: '他 生日5月20日 我生日9月25日',
}
},
{
index: 2,
finish: false,
title: '一起去旅行',
desc: '一起来一场说走就走的旅行,希望去的是大理',
detail: {
start: '',
desc: '',
end: '',
moment: '一起来一场说走就走的旅行,希望去的是大理',
other: '',
}
},
{
index: 3,
finish: false,
title: '一起穿情侣装逛街',
desc: '一起穿情侣装逛街',
detail: {
start: '',
desc: '',
end: '',
moment: '',
other: '',
}
},
{
index: 4,
finish: false,
title: '一起看日出',
desc: '一起看日出',
detail: {
start: '',
desc: '',
end: '',
moment: '',
other: '',
}
},
{
index: 5,
finish: false,
title: '一起看日落',
desc: '一起看日落',
detail: {
start: '',
desc: '',
end: '',
moment: '',
other: '', // 其他说明
}
},
{
index: 6,
finish: false,
title: '一起买菜、做饭、刷碗',
desc: '一起买菜、做饭、刷碗',
detail: {
start: '',
desc: '',
end: '',
moment: '',
other: '',
}
}
],
}
}
-142
View File
@@ -1,142 +0,0 @@
/**
* 恋爱日记配置
*/
export default {
waveImageUrl: 'https://b.925i.cn/uni_halo/uni_halo_about_wave.gif', // 波浪图片地址
bgImageUrl: 'https://b.925i.cn/uni_halo_love/love_bg1.png', // 背景图片
loveImageUrl: 'https://b.925i.cn/uni_halo_love/like.png', // 爱心图片
boy: {
name: '未知男主',
avatar: 'https://b.925i.cn/uni_halo_love/love_boy.png',
birthday: '2022-09-25', // 生日
},
girl: {
name: '未知女主',
avatar: 'https://b.925i.cn/uni_halo_love/love_girl.png',
birthday: '2022-07-25', // 生日
},
timeTitle: '这是我们一起走过的', // 恋爱时间标题
loveStartDate: '2022-05-20 13:14:20', // 恋爱开始时间
// 恋爱日记首页导航(除了 key 以外都可以修改)
nav: [{
key: 'journey',
use: true,
iconImageUrl: 'https://b.925i.cn/uni_halo_love/diandian.png',
title: '关于我们',
desc: '我们一起度过的那些经历'
},
{
key: 'list',
use: true,
iconImageUrl: 'https://b.925i.cn/uni_halo_love/diandian.png',
title: '恋爱清单',
desc: '你我之间的约定我们都在努力实现'
},
],
// 关于我们:支持富文本内容
journey: `
<p>有一只马,它的邻居是一只驴。</p><p>有一天,马和驴都被主人牵到外面晒太阳,马和驴聊起了天。</p><p>马说:“我叫马,你呢?”</p><p>驴说:“我叫驴。(哄小宝贝睡觉的甜甜睡前故事)”</p><p>马说:“为什么我俩的名字不一样呢?”</p><p>驴说:“因为我和你不一样。”</p><p>马说:“我们俩什么地方不一样呢?”</p><p>驴说:“我身材小巧,而你却比较粗壮,不如我耐看。”马看了看比自已矮小很多的驴,认为驴说的话有点道理。</p><p>马说:“我们俩除了身材不一样,还有什么不同呢?”</p><p>驴说:“我们俩的声音不一样,我的声音多动听呀!”说着驴伸长脖子叫了两声。“不信,你也叫两声试试。”马也伸长脖子嘶鸣了两声,的确和驴的声音有点不同,马不好意思地低下了头。</p><p>过了一会儿,马又说:“我们俩除了身材和声音不一样外,还有什么不同呢?”</p><p>驴说:“我的步伐多么优雅呀。”说着,驴迈开蹄子走了两步,“而你呢,却昂首阔步,一点儿也不优雅,(如何哄女朋友睡觉的睡前故事爱情浪漫)不信你走两步试试。”</p><p>马听驴这么一说,就高昂着头走了两步,旋即,马飞奔了起来,转了一圈回来后,驴得意地说:“怎么样,我没说错罢,你就是急性子,和优雅不沾边。”马听了驴的话,有点感到惭愧。</p><p>最后,马又鼓起勇气说:“我们俩还有什么不同呢?”</p><p>驴说:“我的家庭意识比你强,主人抽我一鞭子,我就跟着主人回家,而你呢?恐怕不会吧……”</p><p>马还没有来得及回答,马和驴的主人同时来到了马和驴的身边。只见驴的主人抽了驴一鞭子后,驴乖乖地跟着主人回家了。马把这一切都看在了眼里,它为自已和驴的诸多不同而感到惭愧,只见马的主人也抽了马一鞭子,马犹豫了一下,终于象驴一样乖乖地跟着主人回了家。</p><p>一个伯乐站在远处看到了这一幕后,叹口气离开了。</p>
`,
// 恋爱清单
loveList: {
useApi: false, // 是否启用api接口
api: '', // api 接口(如果使用api接口的方式,则下方的data可以留空,但是api接口必须按照对应的数据格式返回)
data: [{
index: 0, // 序号
finish: true, // 是否已完成
title: '偷偷记录对方熟睡的模样', // 事件名称
desc: '偷偷观察对方熟睡的模样,记录下来', // 事件描述
detail: {
start: '2022年05月20日', // 计划开始时间
desc: '偷偷观察对方熟睡的模样,记录下来', // 事件详细描述
end: '每天', // 完成时间,
moment: '', // 完成瞬间的记录
other: '', // 其他说明
}
}, {
index: 1,
finish: false,
title: '陪对方过生日',
desc: '陪对方一起过生日',
detail: {
start: '2023年05月20日',
desc: '陪对方一起过生日,他和我的生日',
end: '',
moment: '',
other: '他 生日5月20日 我生日9月25日',
}
},
{
index: 2,
finish: false,
title: '一起去旅行',
desc: '一起来一场说走就走的旅行,希望去的是大理',
detail: {
start: '',
desc: '',
end: '',
moment: '一起来一场说走就走的旅行,希望去的是大理',
other: '',
}
},
{
index: 3,
finish: false,
title: '一起穿情侣装逛街',
desc: '一起穿情侣装逛街',
detail: {
start: '',
desc: '',
end: '',
moment: '',
other: '',
}
},
{
index: 4,
finish: false,
title: '一起看日出',
desc: '一起看日出',
detail: {
start: '',
desc: '',
end: '',
moment: '',
other: '',
}
},
{
index: 5,
finish: false,
title: '一起看日落',
desc: '一起看日落',
detail: {
start: '',
desc: '',
end: '',
moment: '',
other: '', // 其他说明
}
},
{
index: 6,
finish: false,
title: '一起买菜、做饭、刷碗',
desc: '一起买菜、做饭、刷碗',
detail: {
start: '',
desc: '',
end: '',
moment: '',
other: '',
}
}
],
}
}
-24
View File
@@ -1,24 +0,0 @@
/** 插件相关配置 */
const PluginsConfig = Object.freeze({
// 友链提交配置
autoSubmitLink: {
// 可以考虑配置一个插件id,检测是否开启了友链提交插件
pluginId:"",
// 是否开启(可能不启用插件)
enabled: false,
// 我的友链信息
blogDetail: {
// 博客名称
name: "uni-halo 博客",
// 博客地址
url: "https://uni-halo.925i.cn/",
// 博客logo
logo: "https://uni-halo.925i.cn/logo.png",
// 博客简介
description: "一个基于Halo2.0 API 的博客小程序开源项目。",
}
}
})
export default PluginsConfig;
-30
View File
@@ -1,30 +0,0 @@
/** 插件相关配置 */
const PluginsConfig = Object.freeze({
// 友链提交配置
autoSubmitLink: {
// 可以考虑配置一个插件id,检测是否开启了友链提交插件(暂未使用)
pluginId: "",
// 是否开启(可能后台没有安装或未不启用插件)
enabled: true,
// 我的友链信息
blogDetail: {
// 博客名称
name: "",
// 博客地址
url: "",
// 博客logo
logo: "",
// 博客简介
description: "",
}
},
// tools工具箱插件配置
toolsPlugin: {
pluginId:"tools",
enabled: true,
Authorization: "Tools工具箱插件设置的认证token"
}
})
export default PluginsConfig;
-10
View File
@@ -62,18 +62,9 @@ Vue.prototype.$http = http;
import ApiManager from '@/api/index.js'
Vue.use(ApiManager);
import HaloConfig from '@/config/halo.config.js'
import HaloTokenConfig from '@/config/token.config.js'
Vue.prototype.$haloConfig = HaloConfig
Vue.prototype.$baseApiUrl = HaloTokenConfig.BASE_API
import HaloAdConfig from '@/config/ad.config.js'
Vue.prototype.$haloAdConfig = HaloAdConfig
import HaloPluginsConfig from '@/config/plugins.config.js'
Vue.prototype.$haloPluginsConfig = HaloPluginsConfig
// 由于微信小程序的运行机制问题,需声明如下一行,H5和APP非必填
Vue.prototype._i18n = i18n;
@@ -83,7 +74,6 @@ const app = new Vue({
i18n,
...App,
});
// app.$mount();
// #ifdef H5
RouterMount(app, router, '#app')
+41 -30
View File
@@ -1,35 +1,46 @@
<template>
<view class="app-page"></view>
<view class="app-page"></view>
</template>
<script>
export default {
onLoad() {
this.fnCheckShowStarted();
},
methods: {
// 检查是否需要跳转到启动页
fnCheckShowStarted() {
if (!getApp().globalData.start.use) {
uni.switchTab({
url: '/pages/tabbar/home/home'
});
return;
}
if (uni.getStorageSync('APP_HAS_STARTED')) {
uni.switchTab({
url: '/pages/tabbar/home/home'
});
// uni.navigateTo({
// url:'/pagesA/test-page/test-page'
// })
} else {
uni.redirectTo({
url: '/pagesA/start/start'
});
}
}
}
};
export default {
computed: {
configs() {
return this.$tm.vx.getters().getConfigs;
}
},
onLoad() {
uni.$tm.vx.actions('config/fetchConfigs').then((res) => {
console.log('正常:', res)
// #ifdef MP-WEIXIN
uni.$tm.vx.commit('setWxShare', res.shareConfig);
// #endif
this.fnCheckShowStarted();
}).catch((err) => {
console.log('异常:', err)
uni.switchTab({
url: '/pages/tabbar/home/home'
});
})
},
methods: {
fnCheckShowStarted() {
if (!this.configs.startConfig.enable) {
uni.switchTab({
url: '/pages/tabbar/home/home'
});
return;
}
if (uni.getStorageSync('APP_HAS_STARTED')) {
uni.switchTab({
url: '/pages/tabbar/home/home'
});
} else {
uni.redirectTo({
url: '/pagesA/start/start'
});
}
}
}
};
</script>
File diff suppressed because it is too large Load Diff
+4 -10
View File
@@ -7,20 +7,19 @@
</view>
<!-- 内容区域 -->
<view v-else class="app-page-content">
<view v-if="dataList.length == 0" class="content-empty flex flex-center">
<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 style="font-size: 32rpx;color: #ffffff;">{{ item.spec.displayName }}</view>
<view style="font-size: 24rpx;color: #ffffff;margin-top: 6rpx;">
{{item.postCount}} 篇文章
{{ item.postCount }} 篇文章
</view>
</view>
</view>
@@ -40,6 +39,7 @@
import MarkdownConfig from '@/common/markdown/markdown.config.js';
import mpHtml from '@/components/mp-html/components/mp-html/mp-html.vue';
export default {
components: {
tmSkeleton,
@@ -63,12 +63,6 @@
};
},
computed: {
bloggerInfo() {
return this.$tm.vx.getters().getBlogger;
},
},
onLoad() {
this.fnGetData();
},
+234 -234
View File
@@ -1,253 +1,253 @@
<template>
<view class="app-page">
<!-- 顶部切换 -->
<view class="e-fixed" v-if="category.list.length > 0">
<tm-tabs color="light-blue" v-model="category.activeIndex" range-key="displayName" :list="category.list"
align="left" @change="fnOnCategoryChange"></tm-tabs>
</view>
<!-- 占位区域 -->
<view v-if="category.list.length > 0" style="width: 100vw;height: 90rpx;"></view>
<!-- 加载区域 -->
<view v-if="loading != 'success'" class="loading-wrap">
<tm-skeleton model="card"></tm-skeleton>
<tm-skeleton model="card"></tm-skeleton>
<tm-skeleton model="card"></tm-skeleton>
<tm-skeleton model="card"></tm-skeleton>
</view>
<!-- 内容区域 -->
<view class="content" v-else>
<view v-if="dataList.length == 0" class="content-empty">
<!-- 空布局 -->
<tm-empty icon="icon-shiliangzhinengduixiang-" label="博主还没有分享图片~"></tm-empty>
</view>
<block v-else>
<block v-for="(item, index) in dataList" :key="index">
<tm-translate style="box-sizing: border-box;padding: 6rpx;width: 50%;height: 250rpx;"
animation-name="fadeUp" :wait="calcAniWait(index)">
<view style="border-radius: 12rpx;overflow: hidden;width: 100%;height: 250rpx;">
<image style="width: 100%;height: 100%;" mode="aspectFill" :src="item.spec.cover"
@click="fnPreview(index)" />
</view>
</tm-translate>
</block>
<view class="app-page">
<!-- 顶部切换 -->
<view class="e-fixed" v-if="category.list.length > 0">
<tm-tabs color="light-blue" v-model="category.activeIndex" range-key="displayName" :list="category.list"
align="left" @change="fnOnCategoryChange"></tm-tabs>
</view>
<!-- 占位区域 -->
<view v-if="category.list.length > 0" style="width: 100vw;height: 90rpx;"></view>
<!-- 加载区域 -->
<view v-if="loading != 'success'" class="loading-wrap">
<tm-skeleton model="card"></tm-skeleton>
<tm-skeleton model="card"></tm-skeleton>
<tm-skeleton model="card"></tm-skeleton>
<tm-skeleton model="card"></tm-skeleton>
</view>
<!-- 内容区域 -->
<view class="content" v-else>
<view v-if="dataList.length == 0" class="content-empty">
<!-- 空布局 -->
<tm-empty icon="icon-shiliangzhinengduixiang-" label="博主还没有分享图片~"></tm-empty>
</view>
<block v-else>
<block v-for="(item, index) in dataList" :key="index">
<tm-translate style="box-sizing: border-box;padding: 6rpx;width: 50%;height: 250rpx;"
animation-name="fadeUp" :wait="calcAniWait(index)">
<view style="border-radius: 12rpx;overflow: hidden;width: 100%;height: 250rpx;">
<image style="width: 100%;height: 100%;" mode="aspectFill" :src="item.spec.cover"
@click="fnPreview(index)"/>
</view>
</tm-translate>
</block>
<tm-flotbutton @click="fnToTopPage" color="light-blue" size="m" icon="icon-angle-up"></tm-flotbutton>
<view class="load-text">{{ loadMoreText }}</view>
</block>
</view>
</view>
<tm-flotbutton @click="fnToTopPage" color="light-blue" size="m" icon="icon-angle-up"></tm-flotbutton>
<view class="load-text">{{ loadMoreText }}</view>
</block>
</view>
</view>
</template>
<script>
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
import tmTags from '@/tm-vuetify/components/tm-tags/tm-tags.vue';
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
import tmIcons from '@/tm-vuetify/components/tm-icons/tm-icons.vue';
import tmImages from '@/tm-vuetify/components/tm-images/tm-images.vue';
import tmFlowLayout from '@/tm-vuetify/components/tm-flowLayout/tm-flowLayout.vue';
import tmTabs from '@/tm-vuetify/components/tm-tabs/tm-tabs.vue';
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
import tmTags from '@/tm-vuetify/components/tm-tags/tm-tags.vue';
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
import tmIcons from '@/tm-vuetify/components/tm-icons/tm-icons.vue';
import tmImages from '@/tm-vuetify/components/tm-images/tm-images.vue';
import tmFlowLayout from '@/tm-vuetify/components/tm-flowLayout/tm-flowLayout.vue';
import tmTabs from '@/tm-vuetify/components/tm-tabs/tm-tabs.vue';
export default {
components: {
tmSkeleton,
tmTranslate,
tmFlotbutton,
tmTags,
tmEmpty,
tmIcons,
tmImages,
tmFlowLayout,
tmTabs
},
data() {
return {
isBlackTheme: false,
loading: 'loading',
category: {
activeIndex: 0,
activeValue: '',
list: []
},
queryParams: {
size: 10,
page: 1,
group: ""
},
cache: {
dataList: [],
total: 0
},
isLoadMore: false,
loadMoreText: '',
hasNext: false,
dataList: []
};
},
filters: {
filterTakeTime(val) {
return uni.$tm.dayjs(val).format('DD/MM/YYYY');
}
},
onLoad() {
this.fnSetPageTitle('个人图库');
this.fnGetCategory();
},
onPullDownRefresh() {
this.dataList = []
this.isLoadMore = false;
this.queryParams.page = 1;
this.fnGetData();
},
onReachBottom(e) {
if (this.hasNext) {
this.queryParams.page += 1;
this.isLoadMore = true;
this.fnGetData();
} else {
uni.showToast({
icon: 'none',
title: '没有更多数据了'
});
}
},
methods: {
fnOnCategoryChange(index) {
this.fnResetSetAniWaitIndex();
this.cache.dataList = []
this.dataList = [];
this.queryParams.group = this.category.list[index].name;
this.queryParams.page = 1;
this.fnToTopPage();
this.fnGetData();
},
fnGetCategory() {
this.$httpApi.v2.getPhotoGroupList({
page: 1,
size: 9999
}).then(res => {
this.category.list = res.items.map(item => {
return {
name: item.metadata.name,
displayName: item.spec.displayName
}
});
if (this.category.list.length !== 0) {
this.queryParams.group = this.category.list[0].name;
this.fnGetData();
}
export default {
components: {
tmSkeleton,
tmTranslate,
tmFlotbutton,
tmTags,
tmEmpty,
tmIcons,
tmImages,
tmFlowLayout,
tmTabs
},
data() {
return {
isBlackTheme: false,
loading: 'loading',
category: {
activeIndex: 0,
activeValue: '',
list: []
},
queryParams: {
size: 10,
page: 1,
group: ""
},
cache: {
dataList: [],
total: 0
},
isLoadMore: false,
loadMoreText: '',
hasNext: false,
dataList: []
};
},
filters: {
filterTakeTime(val) {
return uni.$tm.dayjs(val).format('DD/MM/YYYY');
}
},
onLoad() {
this.fnSetPageTitle('个人图库');
this.fnGetCategory();
},
onPullDownRefresh() {
this.dataList = []
this.isLoadMore = false;
this.queryParams.page = 1;
this.fnGetData();
},
onReachBottom(e) {
if (this.hasNext) {
this.queryParams.page += 1;
this.isLoadMore = true;
this.fnGetData();
} else {
uni.showToast({
icon: 'none',
title: '没有更多数据了'
});
}
},
methods: {
fnOnCategoryChange(index) {
this.fnResetSetAniWaitIndex();
this.cache.dataList = []
this.dataList = [];
this.queryParams.group = this.category.list[index].name;
this.queryParams.page = 1;
this.fnToTopPage();
this.fnGetData();
},
fnGetCategory() {
this.$httpApi.v2.getPhotoGroupList({
page: 1,
size: 9999
}).then(res => {
this.category.list = res.items.map(item => {
return {
name: item.metadata.name,
displayName: item.spec.displayName
}
});
if (this.category.list.length !== 0) {
this.queryParams.group = this.category.list[0].name;
this.fnGetData();
}
});
},
fnGetData() {
// 设置状态为加载中
if (!this.isLoadMore) {
this.loading = 'loading';
}
this.loadMoreText = '';
this.$httpApi.v2
.getPhotoListByGroupName(this.queryParams)
.then(res => {
console.log("相册 res", res)
this.hasNext = res.hasNext;
this.loading = 'success';
if (res.items.length != 0) {
const _list = res.items.map((item, index) => {
item.spec.cover = this.$utils.checkImageUrl(item.spec.cover);
return item;
});
this.fnCacheDataList(_list);
if (this.isLoadMore) {
this.dataList = this.dataList.concat(_list);
} else {
this.dataList = _list;
}
}
this.loadMoreText = res.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
});
},
fnGetData() {
// 设置状态为加载中
if (!this.isLoadMore) {
this.loading = 'loading';
}
this.loadMoreText = '';
this.$httpApi.v2
.getPhotoListByGroupName(this.queryParams)
.then(res => {
console.log("相册 res", res)
this.hasNext = res.hasNext;
this.loading = 'success';
if (res.items.length != 0) {
const _list = res.items.map((item, index) => {
item.spec.cover = this.$utils.checkImageUrl(item.spec.cover);
return item;
});
this.fnCacheDataList(_list);
if (this.isLoadMore) {
this.dataList = this.dataList.concat(_list);
} else {
this.dataList = _list;
}
}
this.loadMoreText = res.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
})
.catch(err => {
console.error(err);
this.loading = 'error';
this.waterfall.loading = 'finish';
this.loadMoreText = '加载失败,请下拉刷新!';
})
.finally(() => {
setTimeout(() => {
uni.hideLoading();
uni.stopPullDownRefresh();
}, 500);
});
},
// 缓存数据
fnCacheDataList(dataList) {
if (this.queryParams.page == 1) {
this.cache.dataList = dataList;
} else {
this.cache.dataList = [...this.cache.dataList, ...dataList];
}
},
})
.catch(err => {
console.error(err);
this.loading = 'error';
this.waterfall.loading = 'finish';
this.loadMoreText = '加载失败,请下拉刷新!';
})
.finally(() => {
setTimeout(() => {
uni.hideLoading();
uni.stopPullDownRefresh();
}, 500);
});
},
// 缓存数据
fnCacheDataList(dataList) {
if (this.queryParams.page == 1) {
this.cache.dataList = dataList;
} else {
this.cache.dataList = [...this.cache.dataList, ...dataList];
}
},
// 瀑布流组件点击事件
fnOnClick(data) {
console.log('点击数据', data);
},
// 预览
fnPreview(index) {
uni.previewImage({
current: index,
urls: this.dataList.map(x => x.spec.cover),
indicator: 'number',
loop: true
});
}
}
};
// 瀑布流组件点击事件
fnOnClick(data) {
console.log('点击数据', data);
},
// 预览
fnPreview(index) {
uni.previewImage({
current: index,
urls: this.dataList.map(x => x.spec.cover),
indicator: 'number',
loop: true
});
}
}
};
</script>
<style lang="scss" scoped>
.app-page {
width: 100vw;
min-height: 100vh;
display: flex;
flex-direction: column;
padding-bottom: 24rpx;
background-color: #fafafa;
.app-page {
width: 100vw;
min-height: 100vh;
display: flex;
flex-direction: column;
padding-bottom: 24rpx;
background-color: #fafafa;
&.is-balck {
background-color: #212121;
}
}
&.is-balck {
background-color: #212121;
}
}
.content {
display: flex;
flex-wrap: wrap;
box-sizing: border-box;
padding: 0 24rpx;
padding-top: 24rpx;
gap: 12rpx 0;
.content {
display: flex;
flex-wrap: wrap;
box-sizing: border-box;
padding: 0 24rpx;
padding-top: 24rpx;
gap: 12rpx 0;
.content-empty {
width: 100%;
height: 60vh;
display: flex;
align-items: center;
justify-content: center;
}
}
.content-empty {
width: 100%;
height: 70vh;
display: flex;
align-items: center;
justify-content: center;
}
}
.loading-wrap {
box-sizing: border-box;
padding: 24rpx;
}
.loading-wrap {
box-sizing: border-box;
padding: 24rpx;
}
.card {
box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.03);
}
.card {
box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.03);
}
.load-text {
width: 100%;
text-align: center;
}
.load-text {
width: 100%;
text-align: center;
}
</style>
+411 -405
View File
@@ -1,446 +1,452 @@
<template>
<view class="app-page">
<tm-menubars iconColor="white" color="white" :flat="true" :showback="false">
<image slot="left" class="logo ml-24 round-24" :src="bloggerInfo.avatar" mode="scaleToFill"></image>
<view class="search-input round-12 pt-12 pb-12 flex pl-24" @click="fnToSearch">
<text class="search-input_icon iconfont text-size-m icon-search text-grey"></text>
<view class="search-input_text pl-12 text-size-m text-grey">搜索文章...</view>
</view>
<!-- #ifdef APP-PLUS || H5 -->
<view slot="right" class="mr-24 text-size-m text-grey">uni-halo</view>
<!-- #endif -->
</tm-menubars>
<view v-if="loading != 'success' && articleList.length===0" class="loading-wrap">
<tm-skeleton model="card"></tm-skeleton>
<tm-skeleton model="cardActions"></tm-skeleton>
<tm-skeleton model="list"></tm-skeleton>
<tm-skeleton model="listAvatr"></tm-skeleton>
<tm-skeleton model="listAvatr"></tm-skeleton>
<tm-skeleton model="listAvatr"></tm-skeleton>
</view>
<block v-else>
<view class="bg-white pb-24">
<view class="banner bg-white ml-24 mr-24 mt-12 round-3" v-if="bannerList.length != 0">
<e-swiper :dotPosition="globalAppSettings.banner.dotPosition" :autoplay="true"
:useDot="globalAppSettings.banner.useDot" :list="bannerList"
@on-click="fnOnBannerClick"></e-swiper>
</view>
</view>
<view class="flex flex-between mt-16 mb-24 pl-24 pr-24">
<view class="page-item_title text-weight-b ">精品分类</view>
<view class="show-more flex flex-center bg-white round-3" @click="fnToCategoryPage">
<text class="iconfont icon-angle-right text-size-s text-grey-darken-1"></text>
</view>
<view v-if="false" class="flex flex-center text-size-s text-grey-darken-1" @click="fnToCategoryPage">
<text class=" text-size-m">查看更多</text>
<text class="iconfont icon-angle-right text-size-s "></text>
</view>
</view>
<scroll-view class="category" scroll-x="true">
<view v-if="categoryList.length == 0" class="cate-empty round-3 mr-5 flex flex-center text-grey">
还没有任何文章分类~</view>
<block v-else>
<view class="content" v-for="(category, index) in categoryList" :key="category.metadata.name"
@click="fnToCategoryBy(category)">
<category-mini-card :category="category"></category-mini-card>
</view>
</block>
</scroll-view>
<view class="app-page">
<tm-menubars iconColor="white" color="white" :flat="true" :showback="false">
<image slot="left" class="logo ml-24 round-24" :src="bloggerInfo.avatar" mode="scaleToFill"></image>
<view class="search-input round-12 pt-12 pb-12 flex pl-24" @click="fnToSearch">
<text class="search-input_icon iconfont text-size-m icon-search text-grey"></text>
<view class="search-input_text pl-12 text-size-m text-grey">搜索文章...</view>
</view>
<!-- #ifdef APP-PLUS || H5 -->
<view slot="right" class="mr-24 text-size-m text-grey">uni-halo</view>
<!-- #endif -->
</tm-menubars>
<view v-if="loading !== 'success' && articleList.length===0" class="loading-wrap">
<tm-skeleton model="card"></tm-skeleton>
<tm-skeleton model="cardActions"></tm-skeleton>
<tm-skeleton model="list"></tm-skeleton>
<tm-skeleton model="listAvatr"></tm-skeleton>
<tm-skeleton model="listAvatr"></tm-skeleton>
<tm-skeleton model="listAvatr"></tm-skeleton>
</view>
<block v-else>
<view class="bg-white pb-24">
<view class="banner bg-white ml-24 mr-24 mt-12 round-3" v-if="bannerList.length != 0">
<e-swiper :dotPosition="globalAppSettings.banner.dotPosition" :autoplay="true"
:useDot="globalAppSettings.banner.useDot" :list="bannerList"
@on-click="fnOnBannerClick"></e-swiper>
</view>
</view>
<view class="flex flex-between mt-16 mb-24 pl-24 pr-24">
<view class="page-item_title text-weight-b ">精品分类</view>
<view class="show-more flex flex-center bg-white round-3" @click="fnToCategoryPage">
<text class="iconfont icon-angle-right text-size-s text-grey-darken-1"></text>
</view>
<view v-if="false" class="flex flex-center text-size-s text-grey-darken-1" @click="fnToCategoryPage">
<text class=" text-size-m">查看更多</text>
<text class="iconfont icon-angle-right text-size-s "></text>
</view>
</view>
<scroll-view class="category" scroll-x="true">
<view v-if="categoryList.length == 0" class="cate-empty round-3 mr-5 flex flex-center text-grey">
还没有任何文章分类~
</view>
<block v-else>
<view class="content" v-for="(category, index) in categoryList" :key="category.metadata.name"
@click="fnToCategoryBy(category)">
<category-mini-card :category="category"></category-mini-card>
</view>
</block>
</scroll-view>
<!-- 最新文章 -->
<view class="flex flex-between mt-24 mb-24 pl-24 pr-24">
<view class="page-item_title text-weight-b">文章列表</view>
<view class="show-more flex flex-center bg-white round-3" @click="fnToArticlesPage">
<text class="iconfont icon-angle-right text-size-s text-grey-darken-1"></text>
</view>
<view v-if="false" class="flex flex-center text-size-s text-grey-darken-1" @click="fnToArticlesPage">
<text class=" text-size-m ">查看更多</text>
<text class="iconfont icon-angle-right text-size-s "></text>
</view>
</view>
<view v-if="articleList.length == 0" class="article-empty"><tm-empty icon="icon-shiliangzhinengduixiang-"
label="博主还没有发表任何文章~"></tm-empty></view>
<block v-else>
<view :class="globalAppSettings.layout.home">
<tm-translate v-for="(article, index) in articleList" :key="index" class="ani-item"
animation-name="fadeUp" :wait="calcAniWait(index)">
<article-card from="home" :article="article" :post="article"
@on-click="fnToArticleDetail"></article-card>
</tm-translate>
</view>
<view class="load-text mt-12">{{ loadMoreText }}</view>
<tm-flotbutton v-if="articleList.length > 10" color="light-blue" @click="fnToTopPage" size="m"
icon="icon-angle-up"></tm-flotbutton>
</block>
</block>
</view>
<!-- 最新文章 -->
<view class="flex flex-between mt-24 mb-24 pl-24 pr-24">
<view class="page-item_title text-weight-b">文章列表</view>
<view class="show-more flex flex-center bg-white round-3" @click="fnToArticlesPage">
<text class="iconfont icon-angle-right text-size-s text-grey-darken-1"></text>
</view>
<view v-if="false" class="flex flex-center text-size-s text-grey-darken-1" @click="fnToArticlesPage">
<text class=" text-size-m ">查看更多</text>
<text class="iconfont icon-angle-right text-size-s "></text>
</view>
</view>
<view v-if="articleList.length == 0" class="article-empty">
<tm-empty icon="icon-shiliangzhinengduixiang-"
label="博主还没有发表任何文章~"></tm-empty>
</view>
<block v-else>
<view :class="globalAppSettings.layout.home">
<tm-translate v-for="(article, index) in articleList" :key="index" class="ani-item"
animation-name="fadeUp" :wait="calcAniWait(index)">
<article-card from="home" :article="article" :post="article"
@on-click="fnToArticleDetail"></article-card>
</tm-translate>
</view>
<view class="load-text mt-12">{{ loadMoreText }}</view>
<tm-flotbutton v-if="articleList.length > 10" color="light-blue" @click="fnToTopPage" size="m"
icon="icon-angle-up"></tm-flotbutton>
</block>
</block>
</view>
</template>
<script>
import tmMenubars from '@/tm-vuetify/components/tm-menubars/tm-menubars.vue';
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
import tmIcons from '@/tm-vuetify/components/tm-icons/tm-icons.vue';
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
import tmMenubars from '@/tm-vuetify/components/tm-menubars/tm-menubars.vue';
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
import tmIcons from '@/tm-vuetify/components/tm-icons/tm-icons.vue';
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
import eSwiper from '@/components/e-swiper/e-swiper.vue';
import qs from 'qs'
import eSwiper from '@/components/e-swiper/e-swiper.vue';
import qs from 'qs'
export default {
components: {
tmMenubars,
tmSkeleton,
tmTranslate,
tmFlotbutton,
tmIcons,
tmEmpty,
eSwiper
},
data() {
return {
loading: 'loading',
queryParams: {
size: 5,
page: 1,
sort: ['spec.pinned,desc', 'spec.publishTime,desc']
},
result: {},
isLoadMore: false,
loadMoreText: '加载中...',
bannerCurrent: 0,
bannerList: [],
noticeList: [],
articleList: [],
categoryList: [],
};
},
export default {
components: {
tmMenubars,
tmSkeleton,
tmTranslate,
tmFlotbutton,
tmIcons,
tmEmpty,
eSwiper
},
data() {
return {
loading: 'loading',
queryParams: {
size: 5,
page: 1,
sort: ['spec.pinned,desc', 'spec.publishTime,desc']
},
result: {},
isLoadMore: false,
loadMoreText: '加载中...',
bannerCurrent: 0,
bannerList: [],
noticeList: [],
articleList: [],
categoryList: [],
};
},
computed: {
bloggerInfo() {
let blogger = this.$tm.vx.getters().getBlogger;
blogger.avatar = this.$utils.checkAvatarUrl(blogger.avatar, true);
return blogger;
},
computed: {
bloggerInfo() {
let blogger = this.$tm.vx.getters().getConfigs.authorConfig.blogger;
console.log('blogger----------------', blogger)
blogger.avatar = this.$utils.checkAvatarUrl(blogger.avatar, true);
return blogger;
},
},
onLoad() {
this.fnSetPageTitle();
},
},
onLoad() {
this.fnSetPageTitle();
},
created() {
this.fnQuery();
},
onPullDownRefresh() {
this.isLoadMore = false;
this.queryParams.page = 1;
this.fnQuery();
},
created() {
this.fnQuery();
},
onPullDownRefresh() {
this.isLoadMore = false;
this.queryParams.page = 1;
this.fnQuery();
},
onReachBottom(e) {
if (this.result.hasNext) {
this.queryParams.page += 1;
this.isLoadMore = true;
this.fnGetArticleList();
} else {
uni.showToast({
icon: 'none',
title: '没有更多数据了'
});
}
},
methods: {
fnQuery() {
this.fnGetBanner();
this.fnGetArticleList();
this.fnGetCategoryList();
},
onReachBottom(e) {
if (this.result.hasNext) {
this.queryParams.page += 1;
this.isLoadMore = true;
this.fnGetArticleList();
} else {
uni.showToast({
icon: 'none',
title: '没有更多数据了'
});
}
},
methods: {
fnQuery() {
this.fnGetBanner();
this.fnGetArticleList();
this.fnGetCategoryList();
},
fnGetCategoryList() {
this.$httpApi.v2
.getCategoryList({})
.then(res => {
this.categoryList = res.items.sort((a, b) => {
return b.postCount - a.postCount;
});
fnGetCategoryList() {
this.$httpApi.v2
.getCategoryList({})
.then(res => {
this.categoryList = res.items.sort((a, b) => {
return b.postCount - a.postCount;
});
setTimeout(() => {
this.loading = 'success';
}, 500);
})
.catch(err => {
console.error(err);
this.loading = 'error';
})
.finally(() => {
setTimeout(() => {
uni.hideLoading();
uni.stopPullDownRefresh();
}, 500);
});
},
// 获取轮播图
fnGetBanner() {
const _this = this;
const _format = function (list) {
return list.map((item, index) => {
return {
mp4: '',
id: item.metadata.name,
nickname: item.owner.displayName,
avatar: _this.$utils.checkImageUrl(item.owner.avatar),
address: '',
createTime: uni.$tm.dayjs(item.spec.publishTime).fromNow(),
title: item.spec.title,
src: _this.$utils.checkImageUrl(item.spec.cover),
image: _this.$utils.checkImageUrl(item.spec.cover)
};
});
};
setTimeout(() => {
this.loading = 'success';
}, 500);
})
.catch(err => {
console.error(err);
this.loading = 'error';
})
.finally(() => {
setTimeout(() => {
uni.hideLoading();
uni.stopPullDownRefresh();
}, 500);
});
},
// 获取轮播图
fnGetBanner() {
const _this = this;
const _format = function(list) {
return list.map((item, index) => {
return {
mp4: '',
id: item.metadata.name,
nickname: item.owner.displayName,
avatar: _this.$utils.checkImageUrl(item.owner.avatar),
address: '',
createTime: uni.$tm.dayjs(item.spec.publishTime).fromNow(),
title: item.spec.title,
src: _this.$utils.checkImageUrl(item.spec.cover),
image: _this.$utils.checkImageUrl(item.spec.cover)
};
});
};
const paramsStr = qs.stringify(this.queryParams, {
allowDots: true,
encodeValuesOnly: true,
skipNulls: true,
encode: true,
arrayFormat: 'repeat'
})
uni.request({
url: this.$baseApiUrl + '/apis/api.content.halo.run/v1alpha1/posts?' + paramsStr,
method: 'GET',
params: this.queryParams,
success: (res) => {
this.bannerList = _format(res.data.items);
},
fail: (err) => {
}
})
const paramsStr = qs.stringify(this.queryParams, {
allowDots: true,
encodeValuesOnly: true,
skipNulls: true,
encode: true,
arrayFormat: 'repeat'
})
uni.request({
url: this.$baseApiUrl + '/apis/api.content.halo.run/v1alpha1/posts?' + paramsStr,
method: 'GET',
params: this.queryParams,
success: (res) => {
this.bannerList = _format(res.data.items);
},
fail: (err) => {}
})
},
fnOnBannerChange(e) {
this.bannerCurrent = e.current;
},
fnOnBannerClick(item) {
if (item.id == '') return;
this.fnToArticleDetail({
metadata: {
name: item.id
}
});
},
// 文章列表
fnGetArticleList() {
// uni.showLoading({
// mask: true,
// title: '加载中...'
// });
// 设置状态为加载中
if (!this.isLoadMore) {
this.loading = 'loading';
}
this.loadMoreText = '加载中...';
},
fnOnBannerChange(e) {
this.bannerCurrent = e.current;
},
fnOnBannerClick(item) {
if (item.id == '') return;
this.fnToArticleDetail({
metadata: {
name: item.id
}
});
},
// 文章列表
fnGetArticleList() {
// uni.showLoading({
// mask: true,
// title: '加载中...'
// });
// 设置状态为加载中
if (!this.isLoadMore) {
this.loading = 'loading';
}
this.loadMoreText = '加载中...';
const paramsStr = qs.stringify(this.queryParams, {
allowDots: true,
encodeValuesOnly: true,
skipNulls: true,
encode: true,
arrayFormat: 'repeat'
})
uni.request({
url: this.$baseApiUrl + '/apis/api.content.halo.run/v1alpha1/posts?' + paramsStr,
method: 'GET',
params: this.queryParams,
success: (res) => {
const data = res.data;
this.result.hasNext = data.hasNext;
if (this.isLoadMore) {
this.articleList = this.articleList.concat(data.items);
} else {
this.articleList = data.items;
}
this.loading = 'success';
this.loadMoreText = data.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
uni.hideLoading();
uni.stopPullDownRefresh();
},
fail: (err) => {
this.loading = 'error';
this.loadMoreText = '加载失败,请下拉刷新!';
uni.$tm.toast(err.message || '数据加载失败!');
uni.stopPullDownRefresh();
}
})
},
const paramsStr = qs.stringify(this.queryParams, {
allowDots: true,
encodeValuesOnly: true,
skipNulls: true,
encode: true,
arrayFormat: 'repeat'
})
uni.request({
url: this.$baseApiUrl + '/apis/api.content.halo.run/v1alpha1/posts?' + paramsStr,
method: 'GET',
params: this.queryParams,
success: (res) => {
const data = res.data;
this.result.hasNext = data.hasNext;
if (this.isLoadMore) {
this.articleList = this.articleList.concat(data.items);
} else {
this.articleList = data.items;
}
this.loading = 'success';
this.loadMoreText = data.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
uni.hideLoading();
uni.stopPullDownRefresh();
},
fail: (err) => {
this.loading = 'error';
this.loadMoreText = '加载失败,请下拉刷新!';
uni.$tm.toast(err.message || '数据加载失败!');
uni.stopPullDownRefresh();
}
})
},
//跳转文章详情
fnToArticleDetail(article) {
uni.navigateTo({
url: '/pagesA/article-detail/article-detail?name=' + article.metadata.name,
animationType: 'slide-in-right'
});
},
// 快捷导航页面跳转
fnToNavPage(item) {
switch (item.type) {
case 'tabbar':
uni.switchTab({
url: item.path
});
break;
case 'page':
uni.navigateTo({
url: item.path
});
break;
}
},
// 分类页面
fnToCategoryPage() {
uni.switchTab({
url: '/pages/tabbar/category/category'
});
},
// 所有的文章列表页面
fnToArticlesPage() {
uni.navigateTo({
url: '/pagesA/articles/articles'
});
},
//跳转文章详情
fnToArticleDetail(article) {
uni.navigateTo({
url: '/pagesA/article-detail/article-detail?name=' + article.metadata.name,
animationType: 'slide-in-right'
});
},
// 快捷导航页面跳转
fnToNavPage(item) {
switch (item.type) {
case 'tabbar':
uni.switchTab({
url: item.path
});
break;
case 'page':
uni.navigateTo({
url: item.path
});
break;
}
},
// 分类页面
fnToCategoryPage() {
uni.switchTab({
url: '/pages/tabbar/category/category'
});
},
// 所有的文章列表页面
fnToArticlesPage() {
uni.navigateTo({
url: '/pagesA/articles/articles'
});
},
// 根据slug查询分类下的文章
fnToCategoryBy(category) {
uni.navigateTo({
url: `/pagesA/category-detail/category-detail?name=${category.metadata.name}&title=${category.spec.displayName}`
});
},
// 根据slug查询分类下的文章
fnToCategoryBy(category) {
uni.navigateTo({
url: `/pagesA/category-detail/category-detail?name=${category.metadata.name}&title=${category.spec.displayName}`
});
},
fnChangeMode() {
const isBlackTheme = this.$tm.vx.state().tmVuetify.black;
this.$tm.theme.setBlack(!isBlackTheme);
uni.setNavigationBarColor({
backgroundColor: !isBlackTheme ? '#0a0a0a' : '#ffffff',
frontColor: !isBlackTheme ? '#ffffff' : '#0a0a0a'
});
},
fnChangeMode() {
const isBlackTheme = this.$tm.vx.state().tmVuetify.black;
this.$tm.theme.setBlack(!isBlackTheme);
uni.setNavigationBarColor({
backgroundColor: !isBlackTheme ? '#0a0a0a' : '#ffffff',
frontColor: !isBlackTheme ? '#ffffff' : '#0a0a0a'
});
},
fnToSearch() {
uni.navigateTo({
url: '/pagesA/articles/articles'
});
}
}
};
fnToSearch() {
uni.navigateTo({
url: '/pagesA/articles/articles'
});
}
}
};
</script>
<style lang="scss" scoped>
.app-page {
width: 100vw;
min-height: 100vh;
display: flex;
flex-direction: column;
// background-color: #ffffff;
.app-page {
width: 100vw;
min-height: 100vh;
display: flex;
flex-direction: column;
// background-color: #ffffff;
.logo {
width: 60rpx;
height: 60rpx;
box-sizing: border-box;
}
.logo {
width: 60rpx;
height: 60rpx;
box-sizing: border-box;
}
::v-deep {
.tm-menubars .body .body_wk .left {
min-width: initial;
}
}
}
::v-deep {
.tm-menubars .body .body_wk .left {
min-width: initial;
}
}
}
.loading-wrap {
padding: 24rpx;
}
.loading-wrap {
padding: 24rpx;
}
.search-input {
background-color: #f5f5f5;
align-items: center;
/* #ifdef MP-WEIXIN */
margin-right: 24rpx;
.search-input {
background-color: #f5f5f5;
align-items: center;
/* #ifdef MP-WEIXIN */
margin-right: 24rpx;
/* #endif */
&_icon {}
/* #endif */
&_icon {
}
&_text {}
}
&_text {
}
}
.show-more {
width: 42rpx;
height: 42rpx;
box-sizing: border-box;
box-shadow: 0rpx 0rpx 24rpx rgba(0, 0, 0, 0.03);
}
.show-more {
width: 42rpx;
height: 42rpx;
box-sizing: border-box;
box-shadow: 0rpx 0rpx 24rpx rgba(0, 0, 0, 0.03);
}
.banner {
overflow: hidden;
}
.banner {
overflow: hidden;
}
.quick-nav {
background-color: #fff;
box-sizing: border-box;
.quick-nav {
background-color: #fff;
box-sizing: border-box;
// box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.03);
.name {
color: var(--main-text-color);
}
}
// box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.03);
.name {
color: var(--main-text-color);
}
}
.category {
width: 94vw;
display: flex;
height: 200rpx;
white-space: nowrap;
margin: 0 24rpx;
.category {
width: 94vw;
display: flex;
height: 200rpx;
white-space: nowrap;
margin: 0 24rpx;
.content {
display: inline-block;
padding-left: 24rpx;
.content {
display: inline-block;
padding-left: 24rpx;
&:first-child {
padding-left: 0;
}
}
&:first-child {
padding-left: 0;
}
}
.cate-empty {
height: inherit;
}
}
.cate-empty {
height: inherit;
}
}
.page-item {
&_title {
position: relative;
padding-left: 24rpx;
font-size: 32rpx;
z-index: 1;
color: var(--main-text-color);
.page-item {
&_title {
position: relative;
padding-left: 24rpx;
font-size: 32rpx;
z-index: 1;
color: var(--main-text-color);
&:before {
content: '';
position: absolute;
left: 0rpx;
top: 8rpx;
width: 8rpx;
height: 30rpx;
background-color: rgba(33, 150, 243, 1);
border-radius: 6rpx;
z-index: 0;
}
}
}
&:before {
content: '';
position: absolute;
left: 0rpx;
top: 8rpx;
width: 8rpx;
height: 30rpx;
background-color: rgba(33, 150, 243, 1);
border-radius: 6rpx;
z-index: 0;
}
}
}
.h_row_col2 {
display: flex;
flex-wrap: wrap;
box-sizing: border-box;
padding: 0 12rpx;
.h_row_col2 {
display: flex;
flex-wrap: wrap;
box-sizing: border-box;
padding: 0 12rpx;
.ani-item {
width: 50%;
}
}
.ani-item {
width: 50%;
}
}
</style>
+218 -214
View File
@@ -1,236 +1,240 @@
<template>
<view class="app-page">
<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-if="dataList.length == 0" class="content-empty flex flex-center">
<!-- 空布局 -->
<tm-empty icon="icon-shiliangzhinengduixiang-" label="暂无数据"></tm-empty>
</view>
<block v-else>
<block v-for="(moment, index) in dataList" :key="index">
<!-- 卡片 -->
<tm-translate animation-name="fadeUp" :wait="calcAniWait()">
<view class="moment-card">
<view class="head" style="display: flex;align-items: center;">
<view class="avatar" style="flex-shrink: 0;">
<image style="width: 66rpx;height: 66rpx;border-radius: 50%;"
:src="moment.spec.user.avatar" />
</view>
<view class="nickname" style="margin-left: 12rpx;">
<view style="font-size: 30rpx;font-weight: bold;color: #333333;">
{{moment.spec.user.displayName}}
</view>
<view style="margin-top: 6rpx;font-size: 24rpx;color: #666;">
{{ { d: moment.spec.releaseTime, f: 'yyyy年MM月dd日 星期w' } | formatTime }}
</view>
</view>
</view>
<view class="content">
<mp-html class="evan-markdown" lazy-load :domain="markdownConfig.domain"
:loading-img="markdownConfig.loadingGif" :scroll-table="true" :selectable="true"
:tag-style="markdownConfig.tagStyle" :container-style="markdownConfig.containStyle"
:content="moment.spec.content.html" :markdown="true" :showLineNumber="true"
:showLanguageName="true" :copyByLongPress="true" />
</view>
<view v-if="moment.spec.content.medium.length!==0" class="images"
:class="['images-'+moment.spec.content.medium.length]">
<view class="image-item" v-for="(image,mediumIndex) in moment.spec.content.medium"
:key="mediumIndex">
<image mode="aspectFill" style="width: 100%;height: 100%;border-radius: 6rpx;"
:src="image.url" @click="handlePreview(mediumIndex,moment.spec.content.medium)" />
</view>
</view>
</view>
</tm-translate>
</block>
<tm-flotbutton @click="fnToTopPage" size="m" color="light-blue" icon="icon-angle-up"></tm-flotbutton>
<view class="load-text">{{ loadMoreText }}</view>
</block>
</view>
</view>
<view class="app-page">
<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-if="dataList.length == 0" class="content-empty flex flex-center" style="min-height: 70vh;">
<!-- 空布局 -->
<tm-empty icon="icon-shiliangzhinengduixiang-" label="暂无数据"></tm-empty>
</view>
<block v-else>
<block v-for="(moment, index) in dataList" :key="index">
<!-- 卡片 -->
<tm-translate animation-name="fadeUp" :wait="calcAniWait()">
<view class="moment-card">
<view class="head" style="display: flex;align-items: center;">
<view class="avatar" style="flex-shrink: 0;">
<image style="width: 66rpx;height: 66rpx;border-radius: 50%;"
:src="moment.spec.user.avatar"/>
</view>
<view class="nickname" style="margin-left: 12rpx;">
<view style="font-size: 30rpx;font-weight: bold;color: #333333;">
{{ moment.spec.user.displayName }}
</view>
<view style="margin-top: 6rpx;font-size: 24rpx;color: #666;">
{{ {d: moment.spec.releaseTime, f: 'yyyy年MM月dd日 星期w'} | formatTime }}
</view>
</view>
</view>
<view class="content">
<mp-html class="evan-markdown" lazy-load :domain="markdownConfig.domain"
:loading-img="markdownConfig.loadingGif" :scroll-table="true" :selectable="true"
:tag-style="markdownConfig.tagStyle" :container-style="markdownConfig.containStyle"
:content="moment.spec.content.html" :markdown="true" :showLineNumber="true"
:showLanguageName="true" :copyByLongPress="true"/>
</view>
<view v-if="moment.spec.content.medium.length!==0" class="images"
:class="['images-'+moment.spec.content.medium.length]">
<view class="image-item" v-for="(image,mediumIndex) in moment.spec.content.medium"
:key="mediumIndex">
<image mode="aspectFill" style="width: 100%;height: 100%;border-radius: 6rpx;"
:src="image.url"
@click="handlePreview(mediumIndex,moment.spec.content.medium)"/>
</view>
</view>
</view>
</tm-translate>
</block>
<tm-flotbutton @click="fnToTopPage" size="m" color="light-blue" icon="icon-angle-up"></tm-flotbutton>
<view class="load-text">{{ loadMoreText }}</view>
</block>
</view>
</view>
</template>
<script>
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.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';
export default {
components: {
tmSkeleton,
tmFlotbutton,
tmTranslate,
tmEmpty,
mpHtml
},
data() {
return {
markdownConfig: MarkdownConfig,
loading: 'loading',
queryParams: {
size: 10,
page: 1
},
hasNext: false,
dataList: [],
isLoadMore: false,
loadMoreText: '加载中...'
};
},
import MarkdownConfig from '@/common/markdown/markdown.config.js';
import mpHtml from '@/components/mp-html/components/mp-html/mp-html.vue';
computed: {
bloggerInfo() {
return this.$tm.vx.getters().getBlogger;
},
},
export default {
components: {
tmSkeleton,
tmFlotbutton,
tmTranslate,
tmEmpty,
mpHtml
},
data() {
return {
markdownConfig: MarkdownConfig,
loading: 'loading',
queryParams: {
size: 10,
page: 1
},
hasNext: false,
dataList: [],
isLoadMore: false,
loadMoreText: '加载中...'
};
},
onLoad() {
this.fnGetData();
},
onPullDownRefresh() {
this.isLoadMore = false;
this.queryParams.page = 0;
this.fnGetData();
},
computed: {
bloggerInfo() {
let blogger = this.$tm.vx.getters().getConfigs.authorConfig.blogger;
blogger.avatar = this.$utils.checkAvatarUrl(blogger.avatar, true);
return blogger;
}
},
onReachBottom(e) {
if (this.hasNext) {
this.queryParams.page += 1;
this.isLoadMore = true;
this.fnGetData();
} else {
uni.showToast({
icon: 'none',
title: '没有更多数据了'
});
}
},
methods: {
fnGetData() {
uni.showLoading({
mask: true,
title: '加载中...'
});
// 设置状态为加载中
if (!this.isLoadMore) {
this.loading = 'loading';
}
this.loadMoreText = '加载中...';
this.$httpApi.v2
.getMomentList(this.queryParams)
.then(res => {
console.log('请求结果:');
console.log(res);
onLoad() {
this.fnGetData();
},
onPullDownRefresh() {
this.isLoadMore = false;
this.queryParams.page = 0;
this.fnGetData();
},
this.loading = 'success';
this.loadMoreText = res.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
this.hasNext = res.hasNext;
onReachBottom(e) {
if (this.hasNext) {
this.queryParams.page += 1;
this.isLoadMore = true;
this.fnGetData();
} else {
uni.showToast({
icon: 'none',
title: '没有更多数据了'
});
}
},
methods: {
fnGetData() {
uni.showLoading({
mask: true,
title: '加载中...'
});
// 设置状态为加载中
if (!this.isLoadMore) {
this.loading = 'loading';
}
this.loadMoreText = '加载中...';
this.$httpApi.v2
.getMomentList(this.queryParams)
.then(res => {
console.log('请求结果:');
console.log(res);
const tempItems = res.items.map(item => {
item.spec.user = {
displayName: this.bloggerInfo.nickname,
avatar: this.$utils.checkAvatarUrl(this.bloggerInfo.avatar)
}
item.spec.content.medium
.filter(x => x.type === 'PHOTO')
.map(medium => {
medium.url = this.$utils.checkThumbnailUrl(medium.url, true)
})
return item;
})
this.loading = 'success';
this.loadMoreText = res.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
this.hasNext = res.hasNext;
if (this.isLoadMore) {
this.dataList = this.dataList.concat(tempItems);
} else {
this.dataList = tempItems;
}
})
.catch(err => {
console.error(err);
this.loading = 'error';
this.loadMoreText = '加载失败,请下拉刷新!';
})
.finally(() => {
setTimeout(() => {
uni.hideLoading();
uni.stopPullDownRefresh();
}, 500);
});
},
handlePreview(index, list) {
uni.previewImage({
current: index,
urls: list.map(item => item.url)
})
}
}
};
const tempItems = res.items.map(item => {
item.spec.user = {
displayName: this.bloggerInfo.nickname,
avatar: this.$utils.checkAvatarUrl(this.bloggerInfo.avatar)
}
item.spec.content.medium
.filter(x => x.type === 'PHOTO')
.map(medium => {
medium.url = this.$utils.checkThumbnailUrl(medium.url, true)
})
return item;
})
if (this.isLoadMore) {
this.dataList = this.dataList.concat(tempItems);
} else {
this.dataList = tempItems;
}
})
.catch(err => {
console.error(err);
this.loading = 'error';
this.loadMoreText = '加载失败,请下拉刷新!';
})
.finally(() => {
setTimeout(() => {
uni.hideLoading();
uni.stopPullDownRefresh();
}, 500);
});
},
handlePreview(index, list) {
uni.previewImage({
current: index,
urls: list.map(item => item.url)
})
}
}
};
</script>
<style lang="scss" scoped>
.app-page {
width: 100vw;
display: flex;
flex-direction: column;
padding: 24rpx 0;
}
.app-page {
width: 100vw;
display: flex;
flex-direction: column;
padding: 24rpx 0;
}
.loading-wrap {
padding: 24rpx;
}
.loading-wrap {
padding: 24rpx;
}
.moment-card {
display: flex;
flex-direction: column;
box-sizing: border-box;
margin: 0 24rpx;
border-radius: 12rpx;
background-color: #ffff;
box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.03);
overflow: hidden;
margin-bottom: 24rpx;
}
.moment-card {
display: flex;
flex-direction: column;
box-sizing: border-box;
margin: 0 24rpx;
border-radius: 12rpx;
background-color: #ffff;
box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.03);
overflow: hidden;
margin-bottom: 24rpx;
}
.head {
padding: 24rpx;
padding-bottom: 0;
}
.head {
padding: 24rpx;
padding-bottom: 0;
}
.images {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
padding: 24rpx;
padding-top: 0;
.images {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
padding: 24rpx;
padding-top: 0;
.image-item {
box-sizing: border-box;
border-radius: 24rpx;
padding: 6rpx;
width: 33%;
height: 200rpx
}
.image-item {
box-sizing: border-box;
border-radius: 24rpx;
padding: 6rpx;
width: 33%;
height: 200rpx
}
&-1 {
>.image-item {
width: 100%;
height: 350rpx
}
}
&-1 {
> .image-item {
width: 100%;
height: 350rpx
}
}
&-2 {
>.image-item {
width: 50%;
height: 250rpx
}
}
}
&-2 {
> .image-item {
width: 50%;
height: 250rpx
}
}
}
</style>
+80 -75
View File
@@ -1,94 +1,99 @@
<template>
<view class="app-page bg-white flex flex-col">
<view v-if="uni_halo_logo" class="logo mt-40 pt-40"><image class="logo-img round-3" :src="uni_halo_logo" mode="aspectFill"></image></view>
<view class="mt-12 text-weight-b text-size-lg" :class="{ 'mt-40 pt-40': !uni_halo_logo }">uni-halo</view>
<view class="mt-12 text-size-s text-grey-darken-3"></view>
<view class="list-group mt-48" style="width: 100%;">
<tm-grouplist :shadow="0" :margin="0" :borderBottom="true">
<tm-listitem title="开源组织" :font-size="28" @click="$utils.copyText('https://www.ialley.cn', '巷子工坊官网已复制成功!')">
<text class="text-size-s" slot="rightValue">巷子工坊</text>
</tm-listitem>
<tm-listitem title="开源作者" :font-size="28" @click="$utils.copyText('https://b.925i.cn', '作者博客地址已复制')">
<text class="text-size-s" slot="rightValue">小莫唐尼</text>
</tm-listitem>
<tm-listitem title="作者博客" :font-size="28" @click="$utils.copyText('https://b.925i.cn', '作者博客地址已复制')">
<text class="text-size-s text-overflow" slot="rightValue">https://b.925i.cn</text>
</tm-listitem>
<tm-listitem title="文档地址" :font-size="28" @click="$utils.copyText('https://uni-halo.925i.cn', '项目码云仓库已复制')">
<text class="text-size-s text-overflow" slot="rightValue">https://uni-halo.925i.cn</text>
</tm-listitem>
<tm-listitem title="码云仓库" :font-size="28" @click="$utils.copyText('https://gitee.com/ialley-workshop-open/uni-halo', '码云仓库地址已复制')">
<text class="text-size-s text-overflow" slot="rightValue">https://gitee.com/ialley-workshop-open/uni-halo</text>
</tm-listitem>
<tm-listitem title="Github" :font-size="28" @click="$utils.copyText('https://github.com/ialley-workshop-open/uni-halo', 'Github地址已复制')">
<text class="text-size-s text-overflow" slot="rightValue">https://github.com/ialley-workshop-open/uni-halo</text>
</tm-listitem>
</tm-grouplist>
</view>
<view class="copyright bg-white text-size-xs text-align-center text-grey-darken-1 pa-36">
<view class="">根据 AGPL-3.0 协议开源</view>
<view class="mt-8"> 2022 uni-halo 开源项目丨巷子工坊@小莫唐尼 </view>
</view>
</view>
<view class="app-page bg-white flex flex-col">
<view class="logo mt-40 pt-40">
<image class="logo-img round-3" src="https://uni-halo.925i.cn/logo.png" mode="aspectFill"></image>
</view>
<view class="mt-12 text-weight-b text-size-lg">uni-halo</view>
<view class="mt-12 text-size-s text-grey-darken-3"></view>
<view class="list-group mt-48" style="width: 100%;">
<tm-grouplist :shadow="0" :margin="0" :borderBottom="true">
<tm-listitem title="开源组织" :font-size="28" @click="$utils.copyText('https://www.ialley.cn', '巷子工坊官网已复制成功!')">
<text class="text-size-s" slot="rightValue">巷子工坊</text>
</tm-listitem>
<tm-listitem title="开源作者" :font-size="28" @click="$utils.copyText('https://b.925i.cn', '作者博客地址已复制')">
<text class="text-size-s" slot="rightValue">小莫唐尼</text>
</tm-listitem>
<tm-listitem title="作者博客" :font-size="28" @click="$utils.copyText('https://b.925i.cn', '作者博客地址已复制')">
<text class="text-size-s text-overflow" slot="rightValue">https://b.925i.cn</text>
</tm-listitem>
<tm-listitem title="文档地址" :font-size="28" @click="$utils.copyText('https://uni-halo.925i.cn', '项目码云仓库已复制')">
<text class="text-size-s text-overflow" slot="rightValue">https://uni-halo.925i.cn</text>
</tm-listitem>
<tm-listitem title="码云仓库" :font-size="28"
@click="$utils.copyText('https://gitee.com/ialley-workshop-open/uni-halo', '码云仓库地址已复制')">
<text class="text-size-s text-overflow" slot="rightValue">https://gitee.com/ialley-workshop-open/uni-halo</text>
</tm-listitem>
<tm-listitem title="Github" :font-size="28"
@click="$utils.copyText('https://github.com/ialley-workshop-open/uni-halo', 'Github地址已复制')">
<text class="text-size-s text-overflow" slot="rightValue">https://github.com/ialley-workshop-open/uni-halo</text>
</tm-listitem>
</tm-grouplist>
</view>
<view class="copyright bg-white text-size-xs text-align-center text-grey-darken-1 pa-36">
<view class="">根据 AGPL-3.0 协议开源</view>
<view class="mt-8"> 2022 uni-halo 开源项目丨巷子工坊@小莫唐尼 </view>
</view>
</view>
</template>
<script>
import tmGrouplist from '@/tm-vuetify/components/tm-grouplist/tm-grouplist.vue';
import tmListitem from '@/tm-vuetify/components/tm-listitem/tm-listitem.vue';
export default {
components: {
tmGrouplist,
tmListitem
},
computed: {
uni_halo_logo() {
return getApp().globalData.uni_halo_logo;
}
},
onLoad() {
this.fnSetPageTitle('关于项目');
},
methods: {}
components: {
tmGrouplist,
tmListitem
},
onLoad() {
this.fnSetPageTitle('关于项目');
},
methods: {}
};
</script>
<style scoped lang="scss">
.app-page {
width: 100vw;
height: 100vh;
box-sizing: border-box;
align-items: center;
.logo-img {
width: 160rpx;
height: 160rpx;
}
.info {
margin-left: 90rpx;
margin-right: 90rpx;
}
.copyright {
width: 100vw;
position: fixed;
bottom: 0;
left: 0;
box-sizing: border-box;
}
width: 100vw;
height: 100vh;
box-sizing: border-box;
align-items: center;
.label {
display: inline-block;
min-width: 140rpx;
}
.logo-img {
width: 160rpx;
height: 160rpx;
}
.info {
margin-left: 90rpx;
margin-right: 90rpx;
}
.copyright {
width: 100vw;
position: fixed;
bottom: 0;
left: 0;
box-sizing: border-box;
}
.label {
display: inline-block;
min-width: 140rpx;
}
}
.text-overflow {
width: calc(100vw - 300rpx);
text-align: right;
width: calc(100vw - 300rpx);
text-align: right;
}
.list-group {
::v-deep {
.left {
width: 160rpx;
min-width: 160rpx;
}
}
::v-deep {
.left {
width: 160rpx;
min-width: 160rpx;
}
}
}
</style>
+7 -6
View File
@@ -54,6 +54,11 @@ export default {
}
}
},
computed: {
adConfigs() {
return this.$tm.vx.getters().getConfigs.adConfig;
}
},
onLoad(options) {
// #ifdef MP-WEIXIN
wx.hideShareMenu();
@@ -71,7 +76,7 @@ export default {
adLoad() {
if (wx.createRewardedVideoAd) {
videoAd = wx.createRewardedVideoAd({
adUnitId: this.$haloAdConfig.rewardedVideoAd //广key
adUnitId: this.adConfigs.rewardedVideoAdId //广key
})
videoAd.onError(err => {
})
@@ -86,7 +91,7 @@ export default {
}
},
openVideoAd: function () {
if (videoAd && this.$haloAdConfig.rewardedVideoAd != '') {
if (videoAd && this.adConfigs.rewardedVideoAdId != '') {
videoAd.show().catch(err => {
//
console.log("广告拉取失败")
@@ -138,7 +143,3 @@ export default {
}
}
</script>
<style>
</style>
+327 -315
View File
@@ -1,367 +1,379 @@
<template>
<view class="app-page">
<view class="e-fixed"><tm-tabs color="light-blue" v-model="tab.activeIndex" :list="tab.list" align="center" @change="fnOnTabChange"></tm-tabs></view>
<!-- 占位区域 -->
<view style="width: 100vw;height: 90rpx;"></view>
<view class="app-page">
<view class="e-fixed">
<tm-tabs color="light-blue" v-model="tab.activeIndex" :list="tab.list" align="center" @change="fnOnTabChange"></tm-tabs>
</view>
<!-- 占位区域 -->
<view style="width: 100vw;height: 90rpx;"></view>
<!-- 骨架屏加载区域 -->
<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-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>
<!-- 加载完成区域 -->
<block v-else>
<view v-if="dataList.length == 0" class="list-empty flex flex-center"><tm-empty icon="icon-shiliangzhinengduixiang-" label="暂无归档的文章"></tm-empty></view>
<view v-else class="e-timeline tm-timeline mt-24">
<block v-for="(item, index) in dataList" :key="index">
<view class="tm-timeline-item tm-timeline-item--leftDir">
<view style="width: 160rpx;">
<view :style="{ width: '24rpx', height: '24rpx' }" :class="[black_tmeme ? 'bk' : '']" class="flex-center rounded tm-timeline-jidian border-white-a-2 grey-lighten-2 light-blue shadow-primary-4"></view>
<view :style="{ marginTop: '-24rpx' }" :class="[index !== dataList.length - 1 ? 'tm-timeline-item-boder' : '', black_tmeme ? 'bk' : '']" class="grey-lighten-2"></view>
</view>
<view class="tm-timeline-item-content relative">
<view class="tm-timeline-item-left">
<view class="time text-weight-b mb-24">
{{ item.year }}
<block v-if="tab.activeIndex == 0">{{ item.month }}</block>
<text class="text-size-s text-grey-darken-1 ml-24">共发布 {{ item.posts.length }} 篇文章</text>
</view>
<block v-if="item.posts.length != 0">
<block v-for="(post, postIndex) in item.posts" :key="post.id">
<tm-translate animation-name="fadeUp" :wait="calcAniWait(postIndex)">
<view class="flex post shadow-3 pa-24 mb-24" :class="[globalAppSettings.layout.cardType]" @click="fnToArticleDetail(post)">
<image class="post-thumbnail" :src="$utils.checkThumbnailUrl(post.thumbnail)" mode="aspectFill"></image>
<view class="post-info pl-20">
<view class="post-info_title text-overflow">{{ post.title }}</view>
<view class="post-info_summary text-overflow-2 mt-12 text-size-s text-grey-darken-1">{{ post.summary }}</view>
<view class="post-info_time mt-12 text-size-s text-grey-darken-1">
<text class="iconfont icon-clock text-size-s mr-6"></text>
<text class="time-label">发布时间</text>
{{ { d: post.createTime, f: 'yyyy年MM月dd日 星期w' } | formatTime }}
</view>
</view>
</view>
</tm-translate>
</block>
</block>
<view v-else class="post-empty text-size-m text-grey-darken-1">该日期下暂无归档文章</view>
</view>
</view>
</view>
</block>
</view>
<!-- 返回顶部 -->
<tm-flotbutton @click="fnToTopPage" size="m" color="bg-gradient-light-blue-accent" icon="icon-angle-up"></tm-flotbutton>
</block>
</view>
<!-- 加载完成区域 -->
<block v-else>
<view v-if="dataList.length == 0" class="list-empty flex flex-center">
<tm-empty icon="icon-shiliangzhinengduixiang-" label="暂无归档的文章"></tm-empty>
</view>
<view v-else class="e-timeline tm-timeline mt-24">
<block v-for="(item, index) in dataList" :key="index">
<view class="tm-timeline-item tm-timeline-item--leftDir">
<view style="width: 160rpx;">
<view :style="{ width: '24rpx', height: '24rpx' }" :class="[black_tmeme ? 'bk' : '']"
class="flex-center rounded tm-timeline-jidian border-white-a-2 grey-lighten-2 light-blue shadow-primary-4"></view>
<view :style="{ marginTop: '-24rpx' }"
:class="[index !== dataList.length - 1 ? 'tm-timeline-item-boder' : '', black_tmeme ? 'bk' : '']"
class="grey-lighten-2"></view>
</view>
<view class="tm-timeline-item-content relative">
<view class="tm-timeline-item-left">
<view class="time text-weight-b mb-24">
{{ item.year }}
<block v-if="tab.activeIndex == 0">{{ item.month }}</block>
<text class="text-size-s text-grey-darken-1 ml-24">共发布 {{ item.posts.length }} 篇文章</text>
</view>
<block v-if="item.posts.length != 0">
<block v-for="(post, postIndex) in item.posts" :key="post.id">
<tm-translate animation-name="fadeUp" :wait="calcAniWait(postIndex)">
<view class="flex post shadow-3 pa-24 mb-24" :class="[globalAppSettings.layout.cardType]"
@click="fnToArticleDetail(post)">
<image class="post-thumbnail" :src="$utils.checkThumbnailUrl(post.thumbnail)"
mode="aspectFill"></image>
<view class="post-info pl-20">
<view class="post-info_title text-overflow">{{ post.title }}</view>
<view class="post-info_summary text-overflow-2 mt-12 text-size-s text-grey-darken-1">
{{ post.summary }}
</view>
<view class="post-info_time mt-12 text-size-s text-grey-darken-1">
<text class="iconfont icon-clock text-size-s mr-6"></text>
<text class="time-label">发布时间</text>
{{ {d: post.createTime, f: 'yyyy年MM月dd日 星期w'} | formatTime }}
</view>
</view>
</view>
</tm-translate>
</block>
</block>
<view v-else class="post-empty text-size-m text-grey-darken-1">该日期下暂无归档文章</view>
</view>
</view>
</view>
</block>
</view>
<!-- 返回顶部 -->
<tm-flotbutton @click="fnToTopPage" size="m" color="bg-gradient-light-blue-accent" icon="icon-angle-up"></tm-flotbutton>
</block>
</view>
</template>
<script>
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
import tmTabs from '@/tm-vuetify/components/tm-tabs/tm-tabs.vue';
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
import tmTabs from '@/tm-vuetify/components/tm-tabs/tm-tabs.vue';
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
export default {
components: {
tmSkeleton,
tmTranslate,
tmFlotbutton,
tmTabs,
tmEmpty
},
data() {
return {
loading: 'loading',
tab: {
activeIndex: 0,
list: ['按月份查看', '按年份查看']
},
queryParams: {
size: 10,
page: 0
},
result: null,
dataList: [],
api: 'getMonthArchives'
};
},
computed: {
black_tmeme: function() {
return this.$tm.vx.state().tmVuetify.black;
},
color_tmeme: function() {
return this.$tm.vx.state().tmVuetify.color;
}
},
created() {
this.fnGetData();
},
onPullDownRefresh() {
this.fnGetData();
this.queryParams.page = 0;
},
export default {
components: {
tmSkeleton,
tmTranslate,
tmFlotbutton,
tmTabs,
tmEmpty
},
data() {
return {
loading: 'loading',
tab: {
activeIndex: 0,
list: ['按月份查看', '按年份查看']
},
queryParams: {
size: 10,
page: 0
},
result: null,
dataList: [],
api: 'getMonthArchives'
};
},
computed: {
black_tmeme: function () {
return this.$tm.vx.state().tmVuetify.black;
},
color_tmeme: function () {
return this.$tm.vx.state().tmVuetify.color;
}
},
created() {
this.fnGetData();
},
onPullDownRefresh() {
this.fnGetData();
this.queryParams.page = 0;
},
methods: {
fnOnTabChange(index) {
this.fnResetSetAniWaitIndex();
const _api = ['getMonthArchives', 'getYearArchives'];
this.api = _api[index];
this.queryParams.page = 0;
this.fnGetData();
},
fnGetData() {
this.loading = 'loading';
// uni.showLoading({
// mask: true,
// title: '...'
// });
this.$httpApi[this.api](this.queryParams)
.then(res => {
this.result = res.data;
this.dataList = res.data;
setTimeout(() => {
this.loading = 'success';
}, 500);
})
.catch(err => {
console.error(err);
this.loading = 'error';
})
.finally(() => {
setTimeout(() => {
uni.hideLoading();
uni.stopPullDownRefresh();
}, 500);
});
},
//
fnToArticleDetail(article) {
uni.navigateTo({
url: '/pagesA/article-detail/article-detail?articleId=' + article.id,
animationType: 'slide-in-right'
});
}
}
};
methods: {
fnOnTabChange(index) {
this.fnResetSetAniWaitIndex();
const _api = ['getMonthArchives', 'getYearArchives'];
this.api = _api[index];
this.queryParams.page = 0;
this.fnGetData();
},
fnGetData() {
this.loading = 'loading';
// uni.showLoading({
// mask: true,
// title: '...'
// });
this.$httpApi[this.api](this.queryParams)
.then(res => {
this.result = res.data;
this.dataList = res.data;
setTimeout(() => {
this.loading = 'success';
}, 500);
})
.catch(err => {
console.error(err);
this.loading = 'error';
})
.finally(() => {
setTimeout(() => {
uni.hideLoading();
uni.stopPullDownRefresh();
}, 500);
});
},
//
fnToArticleDetail(article) {
uni.navigateTo({
url: '/pagesA/article-detail/article-detail?articleId=' + article.id,
animationType: 'slide-in-right'
});
}
}
};
</script>
<style lang="scss" scoped>
.app-page {
width: 100vw;
min-height: 100vh;
display: flex;
flex-direction: column;
background-color: #fafafd;
}
.app-page {
width: 100vw;
min-height: 100vh;
display: flex;
flex-direction: column;
background-color: #fafafd;
}
.loading-wrap {
padding: 24rpx;
}
.loading-wrap {
padding: 24rpx;
}
.list-empty {
width: 100vw;
height: 100vh;
}
.list-empty {
width: 100vw;
height: 100vh;
}
.statistics {
background-color: #ffffff;
}
.statistics {
background-color: #ffffff;
}
.e-timeline {
::v-deep {
.tm-timeline-item>view:first-child {
width: 110rpx !important;
}
.e-timeline {
::v-deep {
.tm-timeline-item > view:first-child {
width: 110rpx !important;
}
.tm-timeline-item-left {
max-width: 580rpx !important;
width: 100% !important;
}
}
}
.tm-timeline-item-left {
max-width: 580rpx !important;
width: 100% !important;
}
}
}
.tm-timeline {
.tm-timeline-item {
.tm-timeline {
.tm-timeline-item {
.tm-timeline-item-left,
.tm-timeline-item-right {
width: 200rpx;
flex-shrink: 0;
}
.tm-timeline-item-left,
.tm-timeline-item-right {
width: 200rpx;
flex-shrink: 0;
}
.tm-timeline-item-content {
display: flex;
justify-content: center;
align-items: flex-start;
align-content: flex-start;
}
.tm-timeline-item-content {
display: flex;
justify-content: center;
align-items: flex-start;
align-content: flex-start;
}
.tm-timeline-jidian {
margin: auto;
}
.tm-timeline-jidian {
margin: auto;
}
&.tm-timeline-item--leftDir {
display: flex;
flex-flow: row;
&.tm-timeline-item--leftDir {
display: flex;
flex-flow: row;
&.endright {
justify-content: flex-end;
}
&.endright {
justify-content: flex-end;
}
.tm-timeline-item-left,
.tm-timeline-item-right {
width: auto;
max-width: 400rpx;
}
.tm-timeline-item-left,
.tm-timeline-item-right {
width: auto;
max-width: 400rpx;
}
.tm-timeline-item-boder {
height: 100%;
width: 1px;
margin: auto;
}
.tm-timeline-item-boder {
height: 100%;
width: 1px;
margin: auto;
}
.tm-timeline-jidian {
position: relative;
margin: auto;
z-index: 2;
}
.tm-timeline-jidian {
position: relative;
margin: auto;
z-index: 2;
}
.tm-timeline-item-content {
display: flex;
justify-content: flex-start;
align-items: flex-start;
align-content: flex-start;
}
}
}
}
.tm-timeline-item-content {
display: flex;
justify-content: flex-start;
align-items: flex-start;
align-content: flex-start;
}
}
}
}
.post {
width: 560rpx;
border-radius: 12rpx;
background-color: #fff;
.post {
width: 560rpx;
border-radius: 12rpx;
background-color: #fff;
&.lr_image_text {}
&.lr_image_text {
}
&.lr_text_image {
.post-thumbnail {
order: 2;
}
&.lr_text_image {
.post-thumbnail {
order: 2;
}
.post-info {
order: 1;
padding-left: 0;
padding-right: 24rpx;
}
}
.post-info {
order: 1;
padding-left: 0;
padding-right: 24rpx;
}
}
&.tb_image_text {
flex-direction: column;
&.tb_image_text {
flex-direction: column;
.post-thumbnail {
width: 100%;
height: 220rpx;
}
.post-thumbnail {
width: 100%;
height: 220rpx;
}
.post-info {
width: 100%;
padding-left: 0;
.post-info {
width: 100%;
padding-left: 0;
&_title {
margin-top: 12rpx;
}
&_title {
margin-top: 12rpx;
}
&_time {
.iconfont {
display: none;
}
&_time {
.iconfont {
display: none;
}
.time-label {
display: inline-block;
}
}
}
}
.time-label {
display: inline-block;
}
}
}
}
&.tb_text_image {
flex-direction: column;
&.tb_text_image {
flex-direction: column;
.post-thumbnail {
order: 2;
width: 100%;
height: 220rpx;
margin-top: 12rpx;
}
.post-thumbnail {
order: 2;
width: 100%;
height: 220rpx;
margin-top: 12rpx;
}
.post-info {
order: 1;
width: 100%;
padding-left: 0;
.post-info {
order: 1;
width: 100%;
padding-left: 0;
&_time {
.iconfont {
display: none;
}
&_time {
.iconfont {
display: none;
}
.time-label {
display: inline-block;
}
}
}
}
.time-label {
display: inline-block;
}
}
}
}
&.only_text {
.post-info {
padding: 6rpx;
&.only_text {
.post-info {
padding: 6rpx;
&_time {
margin-top: 20rpx;
&_time {
margin-top: 20rpx;
.iconfont {
display: none;
}
.iconfont {
display: none;
}
.time-label {
display: inline-block;
}
}
}
.time-label {
display: inline-block;
}
}
}
.post-thumbnail {
display: none;
}
}
}
.post-thumbnail {
display: none;
}
}
}
.post-thumbnail {
border-radius: 6rpx;
width: 200rpx;
height: 170rpx;
}
.post-thumbnail {
border-radius: 6rpx;
width: 200rpx;
height: 170rpx;
}
.post-info {
width: 0;
flex-grow: 1;
.post-info {
width: 0;
flex-grow: 1;
&_title {
color: #303133;
font-size: 28rpx;
font-weight: bold;
}
&_title {
color: #303133;
font-size: 28rpx;
font-weight: bold;
}
&_summary {
display: -webkit-box;
line-height: 1.6;
}
&_summary {
display: -webkit-box;
line-height: 1.6;
}
&_time {
.time-label {
display: none;
}
}
}
&_time {
.time-label {
display: none;
}
}
}
</style>
+71 -91
View File
@@ -65,12 +65,10 @@
<view v-if="originalURL" class="mt-18 category-type original-url">
<view class="original-url_left text-weight-b">原文</view>
<view class="original-url_right text-grey">
<text class="original-url_right__link"
@click.stop="fnToOriginal(originalURL)">{{ originalURL }}
<text class="original-url_right__link" @click.stop="fnToOriginal(originalURL)">{{ originalURL }}
</text>
<text class="original-url_right__btn" @click.stop="fnToOriginal(originalURL)">阅读原文
<text
class="iconfont icon-angle-right ml-5 text-size-s"></text>
<text class="iconfont icon-angle-right ml-5 text-size-s"></text>
</text>
</view>
</view>
@@ -82,8 +80,8 @@
<mp-html class="evan-markdown" lazy-load :domain="markdownConfig.domain"
:loading-img="markdownConfig.loadingGif" :scroll-table="true" :selectable="true"
:tag-style="markdownConfig.tagStyle" :container-style="markdownConfig.containStyle"
:content="result.content.raw" :markdown="true" :showLineNumber="true"
:showLanguageName="true" :copyByLongPress="true"/>
:content="result.content.raw" :markdown="true" :showLineNumber="true" :showLanguageName="true"
:copyByLongPress="true"/>
<tm-more v-if="showValidVisitMore" :disabled="true" :maxHeight="1" :isRemovBar="true"
@click="showValidVisitMorePop()">
<view class="text-size-n pa-24">
@@ -97,44 +95,32 @@
</template>
</tm-more>
</view>
<!-- 广告区域自定义广告位 -->
<view class="ad-card mt-24" v-if="haloAdConfig.articleDetail.use">
<text class="ad-card_tip">广告</text>
<image class="ad-card_cover" :src="haloAdConfig.articleDetail.cover" mode="scaleToFill">
</image>
<view class="ad-card_info">
<view class="ad-card_info-title">{{ haloAdConfig.articleDetail.title }}</view>
<view class="ad-card_info-desc">{{ haloAdConfig.articleDetail.content }}</view>
<view v-if="haloAdConfig.articleDetail.url" class="ad-card_info-link"
@click="fnToWebview(haloAdConfig.articleDetail)">
立即查看
</view>
</view>
</view>
<!-- 版权声明 -->
<view v-if="copyright.use" class="copyright-wrap bg-white mt-24 pa-24 round-4">
<view v-if="postDetailConfig && postDetailConfig.copyrightEnabled" class="copyright-wrap bg-white mt-24 pa-24 round-4">
<view class="copyright-title text-weight-b">版权声明</view>
<view
class="copyright-content mt-12 grey-lighten-5 text-grey-darken-2 round-4 pt-12 pb-12 pl-24 pr-24 ">
<view v-if="copyright.author" class="copyright-text text-size-s ">
版权归属{{ copyright.author }}
<view v-if="postDetailConfig.copyrightAuthor" class="copyright-text text-size-s ">
版权归属{{ postDetailConfig.copyrightAuthor }}
</view>
<view v-if="copyright.description" class="copyright-text text-size-s mt-12">
版权说明{{ copyright.description }}
<view v-if="postDetailConfig.copyrightDesc" class="copyright-text text-size-s mt-12">
版权说明{{ postDetailConfig.copyrightDesc }}
</view>
<view v-if="copyright.violation" class="copyright-text text-size-s mt-12 text-red">
侵权处理{{ copyright.violation }}
<view v-if="postDetailConfig.copyrightViolation" class="copyright-text text-size-s mt-12 text-red">
侵权处理{{ postDetailConfig.copyrightViolation }}
</view>
</view>
</view>
<!-- 评论展示区域 -->
<view v-if="result" class="comment-wrap bg-white mt-24 pa-24 round-4">
<commentList :disallowComment="!result.spec.allowComment" :postName="result.metadata.name"
:post="result" @on-comment-detail="fnOnShowCommentDetail" @on-loaded="fnOnCommentLoaded">
</commentList>
</view>
<block v-if="postDetailConfig && postDetailConfig.showComment">
<view v-if="result" class="comment-wrap bg-white mt-24 pa-24 round-4">
<commentList :disallowComment="!result.spec.allowComment" :postName="result.metadata.name"
:post="result" @on-comment-detail="fnOnShowCommentDetail" @on-loaded="fnOnCommentLoaded">
</commentList>
</view>
</block>
</view>
<!-- 弹幕效果 -->
@@ -238,9 +224,7 @@ import commentItem from '@/components/comment-item/comment-item.vue';
import rCanvas from '@/components/r-canvas/r-canvas.vue';
import barrage from '@/components/barrage/barrage.vue';
import {
haloWxShareMixin
} from '@/common/mixins/wxshare.mixin.js';
import {haloWxShareMixin} from '@/common/mixins/wxshare.mixin.js';
export default {
components: {
@@ -311,8 +295,11 @@ export default {
};
},
computed: {
copyright() {
return getApp().globalData.copyright;
haloConfigs() {
return this.$tm.vx.getters().getConfigs;
},
postDetailConfig() {
return this.$tm.vx.getters().getConfigs.postDetailConfig;
},
calcUrl() {
return url => {
@@ -324,10 +311,11 @@ export default {
},
//
bloggerInfo() {
let blogger = this.$tm.vx.getters().getBlogger;
let blogger = this.$tm.vx.getters().getConfigs.authorConfig.blogger;
blogger.avatar = this.$utils.checkAvatarUrl(blogger.avatar, true);
return blogger;
},
// =
originalURL() {
if ('unihalo_originalURL' in this.result?.metadata?.annotations) {
@@ -357,14 +345,15 @@ export default {
this.result = res;
const openid = uni.getStorageSync('openid');
if (openid == '' || openid == null) {
if (openid === '' || openid === null) {
this.fnGetOpenid();
}
const visitFlag = uni.getStorageSync('visit_' + this.result?.metadata?.name);
if (!visitFlag) {
const annotationsMap = res?.metadata?.annotations;
if (('restrictReadEnable' in annotationsMap) && annotationsMap.restrictReadEnable === 'true') {
if (('restrictReadEnable' in annotationsMap) && annotationsMap.restrictReadEnable ===
'true') {
this.visitType = 1;
this.showValidVisitMorePop();
} else if ('unihalo_useVisitMorePwd' in annotationsMap) {
@@ -375,9 +364,10 @@ export default {
this.visitType = 3;
this.visitPwd = annotationsMap.unihalo_useVisitPwd;
this.showValidVisitPop();
} else if (('restrictReadEnable' in annotationsMap) && annotationsMap.restrictReadEnable === 'password') {
this.visitType = 4;
this.showValidVisitPop();
} else if (('restrictReadEnable' in annotationsMap) && annotationsMap
.restrictReadEnable === 'password') {
this.visitType = 4;
this.showValidVisitPop();
} else {
this.visitType = 0;
this.showValidVisitMore = false;
@@ -425,6 +415,9 @@ export default {
},
fnToComment() {
if (!this.haloConfig.basicConfig.postDetailConfig.showComment) {
return;
}
if (!this.result.spec.allowComment) {
return uni.$tm.toast('文章已开启禁止评论!');
}
@@ -615,7 +608,7 @@ export default {
//
await this.$refs.rCanvas
.drawImage({
url: this.$haloConfig.miniCodeImageUrl,
url: this.haloConfig.imagesConfig.miniCodeImageUrl,
x: 20,
y: 360,
w: 80,
@@ -681,23 +674,6 @@ export default {
// #ifdef MP-WEIXIN
uni.$tm.toast('点击右上角分享给好友!');
// #endif
// #ifdef APP-PLUS
uni.share({
provider: 'weixin',
scene: 'WXSceneSession',
type: 0,
href: this.$baseApiUrl,
title: this.result.spec.title,
summary: this.result.content.raw,
imageUrl: this.poster.res.tempFilePath,
success: function (res) {
console.log('success:' + JSON.stringify(res));
},
fail: function (err) {
console.log('fail:' + JSON.stringify(err));
}
});
// #endif
},
fnOnShowCommentDetail(data) {
const {
@@ -723,7 +699,7 @@ export default {
this.commentDetail.list = res.items;
})
.catch(err => {
console.log('getPostChildrenCommentList err', error);
console.log('getPostChildrenCommentList err', err);
this.commentDetail.loading = 'error';
});
},
@@ -742,12 +718,12 @@ export default {
const _list = [];
const _handleData = list => {
return new Promise(resolve => {
if (list.length == 0) {
if (list.length === 0) {
resolve();
} else {
list.forEach(item => {
_list.push(item);
if (item.replies && item.replies.length != 0) {
if (item.replies && item.replies.length !== 0) {
_handleData(item.replies.items);
}
resolve();
@@ -833,6 +809,7 @@ export default {
},
// openid
fnGetOpenid() {
// #ifdef MP-WEIXIN
uni.login({
provider: 'weixin',
success: function (loginRes) {
@@ -844,6 +821,7 @@ export default {
}
}
})
// #endif
},
//
fnHideContent() {
@@ -872,18 +850,19 @@ export default {
case 0:
return;
case 1:
this.$httpApi.v2.checkPostVerifyCode(this.validVisitModal.value, this.result?.metadata?.name).then(res => {
if (res.code === 200) {
uni.setStorageSync('visit_' + this.result?.metadata?.name, true)
this.closeAllPop();
this.fnGetData();
} else {
uni.showToast({
title: '密码错误',
icon: 'none'
});
}
}).catch(err => {
this.$httpApi.v2.checkPostVerifyCode(this.validVisitModal.value, this.result?.metadata?.name).then(
res => {
if (res.code === 200) {
uni.setStorageSync('visit_' + this.result?.metadata?.name, true)
this.closeAllPop();
this.fnGetData();
} else {
uni.showToast({
title: '密码错误',
icon: 'none'
});
}
}).catch(err => {
console.log(err);
});
return;
@@ -900,22 +879,23 @@ export default {
});
}
return;
case 4:
this.$httpApi.v2.checkPostPasswordAccess(this.validVisitModal.value, this.result?.metadata?.name).then(res => {
if (res.code === 200) {
uni.setStorageSync('visit_' + this.result?.metadata?.name, true)
this.closeAllPop();
this.fnGetData();
} else {
uni.showToast({
title: '密码错误',
icon: 'none'
case 4:
this.$httpApi.v2.checkPostPasswordAccess(this.validVisitModal.value, this.result?.metadata?.name)
.then(res => {
if (res.code === 200) {
uni.setStorageSync('visit_' + this.result?.metadata?.name, true)
this.closeAllPop();
this.fnGetData();
} else {
uni.showToast({
title: '密码错误',
icon: 'none'
});
}
}).catch(err => {
console.log(err);
});
}
}).catch(err => {
console.log(err);
});
return;
return;
default:
return;
}
+197 -197
View File
@@ -1,214 +1,214 @@
<template>
<view class="app-page" :class="{ 'is-balck grey-darken-6': isBlackTheme }">
<!-- 顶部切换 -->
<view class="e-fixed shadow-2">
<tm-search v-model="queryParams.keyword" :round="24" :shadow="0" color="light-blue"
insert-color="light-blue" :clear="true" @input="fnOnSearch" @confirm="fnOnSearch"></tm-search>
<tm-tabs v-if="false" color="light-blue" :shadow="0" v-model="tab.activeIndex" :list="tab.list"
align="center" @change="fnOnTabChange"></tm-tabs>
</view>
<!-- 占位区域 -->
<view style="width: 100vw;height: 100rpx;"></view>
<!-- 加载区域 -->
<view v-if="loading != 'success'" class="loading-wrap pa-24">
<tm-skeleton model="listAvatr"></tm-skeleton>
<tm-skeleton model="listAvatr"></tm-skeleton>
<tm-skeleton model="listAvatr"></tm-skeleton>
<tm-skeleton model="listAvatr"></tm-skeleton>
</view>
<!-- 内容区域 -->
<view v-else class="content">
<view v-if="dataList.length == 0" class="content-empty flex flex-center">
<!-- 空布局 -->
<tm-empty v-if="!queryParams.keyword" icon="icon-shiliangzhinengduixiang-" label="请输入关键词搜索"></tm-empty>
<tm-empty v-else icon="icon-shiliangzhinengduixiang-"
:label="`未搜到 ${queryParams.keyword} 相关文章`"></tm-empty>
</view>
<block v-else>
<!-- 文章卡片 -->
<tm-translate v-for="(article, index) in dataList" :key="article.name" animation-name="fadeUp"
:wait="calcAniWait(index)">
<view class="article-card" @click="fnToArticleDetail(article)">
<rich-text style="font-size: 32rpx;font-weight: bold;color: #333;"
:nodes="article.title"> </rich-text>
<rich-text style="font-size: 28rpx;margin-top: 16rpx;color: #555;"
:nodes="article.content"> </rich-text>
<text style="font-size: 24rpx;margin-top: 24rpx;color:#888">
发布日期{{ { d: article.publishTimestamp, f: 'yyyy年MM月dd日' } | formatTime }}
</text>
</view>
</tm-translate>
<view class="app-page" :class="{ 'is-balck grey-darken-6': isBlackTheme }">
<!-- 顶部切换 -->
<view class="e-fixed shadow-2">
<tm-search v-model="queryParams.keyword" :round="24" :shadow="0" color="light-blue"
insert-color="light-blue" :clear="true" @input="fnOnSearch" @confirm="fnOnSearch"></tm-search>
<tm-tabs v-if="false" color="light-blue" :shadow="0" v-model="tab.activeIndex" :list="tab.list"
align="center" @change="fnOnTabChange"></tm-tabs>
</view>
<!-- 占位区域 -->
<view style="width: 100vw;height: 100rpx;"></view>
<!-- 加载区域 -->
<view v-if="loading != 'success'" class="loading-wrap pa-24">
<tm-skeleton model="listAvatr"></tm-skeleton>
<tm-skeleton model="listAvatr"></tm-skeleton>
<tm-skeleton model="listAvatr"></tm-skeleton>
<tm-skeleton model="listAvatr"></tm-skeleton>
</view>
<!-- 内容区域 -->
<view v-else class="content">
<view v-if="dataList.length == 0" class="content-empty flex flex-center">
<!-- 空布局 -->
<tm-empty v-if="!queryParams.keyword" icon="icon-shiliangzhinengduixiang-" label="请输入关键词搜索"></tm-empty>
<tm-empty v-else icon="icon-shiliangzhinengduixiang-"
:label="`未搜到 ${queryParams.keyword} 相关文章`"></tm-empty>
</view>
<block v-else>
<!-- 文章卡片 -->
<tm-translate v-for="(article, index) in dataList" :key="article.name" animation-name="fadeUp"
:wait="calcAniWait(index)">
<view class="article-card" @click="fnToArticleDetail(article)">
<rich-text style="font-size: 32rpx;font-weight: bold;color: #333;"
:nodes="article.title"></rich-text>
<rich-text style="font-size: 28rpx;margin-top: 16rpx;color: #555;"
:nodes="article.content"></rich-text>
<text style="font-size: 24rpx;margin-top: 24rpx;color:#888">
发布日期{{ {d: article.publishTimestamp, f: 'yyyy年MM月dd日'} | formatTime }}
</text>
</view>
</tm-translate>
<tm-flotbutton @click="fnToTopPage" size="m" color="light-blue" icon="icon-angle-up"></tm-flotbutton>
<view class="load-text">{{ loadMoreText }}</view>
</block>
</view>
</view>
<tm-flotbutton @click="fnToTopPage" size="m" color="light-blue" icon="icon-angle-up"></tm-flotbutton>
<view class="load-text">{{ loadMoreText }}</view>
</block>
</view>
</view>
</template>
<script>
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmSearch from '@/tm-vuetify/components/tm-search/tm-search.vue';
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
import tmTabs from '@/tm-vuetify/components/tm-tabs/tm-tabs.vue';
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmSearch from '@/tm-vuetify/components/tm-search/tm-search.vue';
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
import tmTabs from '@/tm-vuetify/components/tm-tabs/tm-tabs.vue';
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
export default {
components: {
tmSkeleton,
tmSearch,
tmTranslate,
tmTabs,
tmFlotbutton,
tmEmpty
},
data() {
return {
isBlackTheme: false,
loading: 'loading',
tab: {
activeIndex: 0,
list: ['全部', '最新文章', '热门文章', '最近更新', '最多点赞']
},
queryParams: {
keyword: "",
limit: 5,
highlightPreTag: "<text>",
highlightPostTag: "</text>"
},
cache: {
dataList: [],
total: 0
},
hasNext: false,
isLoadMore: false,
loadMoreText: '加载中...',
dataList: []
};
},
onLoad() {
this.fnSetPageTitle('文章列表');
},
created() {
if (!this.queryParams.keyword) {
this.loading = 'success'
} else {
this.fnGetData();
}
},
onPullDownRefresh() {
this.fnResetSetAniWaitIndex();
this.isLoadMore = false;
this.fnGetData();
},
export default {
components: {
tmSkeleton,
tmSearch,
tmTranslate,
tmTabs,
tmFlotbutton,
tmEmpty
},
data() {
return {
isBlackTheme: false,
loading: 'loading',
tab: {
activeIndex: 0,
list: ['全部', '最新文章', '热门文章', '最近更新', '最多点赞']
},
queryParams: {
keyword: "",
limit: 5,
highlightPreTag: "<text>",
highlightPostTag: "</text>"
},
cache: {
dataList: [],
total: 0
},
hasNext: false,
isLoadMore: false,
loadMoreText: '加载中...',
dataList: []
};
},
onLoad() {
this.fnSetPageTitle('文章列表');
},
created() {
if (!this.queryParams.keyword) {
this.loading = 'success'
} else {
this.fnGetData();
}
},
onPullDownRefresh() {
this.fnResetSetAniWaitIndex();
this.isLoadMore = false;
this.fnGetData();
},
methods: {
fnOnTabChange(index) {
this.fnResetSetAniWaitIndex();
this.dataList = [];
const _sorts = {
0: '',
1: 'topPriority,createTime,desc',
2: 'topPriority,visits,desc',
3: 'topPriority,updateTime,desc',
4: 'topPriority,likes,desc'
};
this.queryParams.sort = _sorts[index];
this.dataList = [];
this.fnToTopPage();
this.fnGetData();
},
fnOnSearch() {
this.fnResetSetAniWaitIndex();
this.isLoadMore = false;
if (!this.queryParams.keyword) {
this.dataList = []
} else {
this.fnGetData();
}
},
fnGetData() {
// uni.showLoading({
// mask: true,
// title: '...'
// });
//
if (!this.isLoadMore) {
this.loading = 'loading';
}
this.loadMoreText = '加载中...';
this.$httpApi.v2
.getPostListByKeyword(this.queryParams)
.then(res => {
console.log('请求结果:');
console.log(res);
methods: {
fnOnTabChange(index) {
this.fnResetSetAniWaitIndex();
this.dataList = [];
const _sorts = {
0: '',
1: 'topPriority,createTime,desc',
2: 'topPriority,visits,desc',
3: 'topPriority,updateTime,desc',
4: 'topPriority,likes,desc'
};
this.queryParams.sort = _sorts[index];
this.dataList = [];
this.fnToTopPage();
this.fnGetData();
},
fnOnSearch() {
this.fnResetSetAniWaitIndex();
this.isLoadMore = false;
if (!this.queryParams.keyword) {
this.dataList = []
} else {
this.fnGetData();
}
},
fnGetData() {
// uni.showLoading({
// mask: true,
// title: '...'
// });
//
if (!this.isLoadMore) {
this.loading = 'loading';
}
this.loadMoreText = '加载中...';
this.$httpApi.v2
.getPostListByKeyword(this.queryParams)
.then(res => {
console.log('请求结果:');
console.log(res);
this.loading = 'success';
this.loadMoreText = res.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
this.hasNext = res.hasNext;
if (this.isLoadMore) {
this.dataList = this.dataList.concat(res.hits);
} else {
this.dataList = res.hits;
}
})
.catch(err => {
console.error(err);
this.loading = 'error';
this.loadMoreText = '加载失败,请下拉刷新!';
})
.finally(() => {
setTimeout(() => {
uni.hideLoading();
uni.stopPullDownRefresh();
}, 800);
});
},
this.loading = 'success';
this.loadMoreText = res.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
this.hasNext = res.hasNext;
if (this.isLoadMore) {
this.dataList = this.dataList.concat(res.hits);
} else {
this.dataList = res.hits;
}
})
.catch(err => {
console.error(err);
this.loading = 'error';
this.loadMoreText = '加载失败,请下拉刷新!';
})
.finally(() => {
setTimeout(() => {
uni.hideLoading();
uni.stopPullDownRefresh();
}, 800);
});
},
//
fnToArticleDetail(article) {
uni.navigateTo({
url: '/pagesA/article-detail/article-detail?name=' + article.name,
animationType: 'slide-in-right'
});
}
}
};
//
fnToArticleDetail(article) {
uni.navigateTo({
url: '/pagesA/article-detail/article-detail?name=' + article.name,
animationType: 'slide-in-right'
});
}
}
};
</script>
<style lang="scss" scoped>
.app-page {
width: 100vw;
min-height: 100vh;
display: flex;
flex-direction: column;
padding-bottom: 24rpx;
background-color: #fafafd;
.app-page {
width: 100vw;
min-height: 100vh;
display: flex;
flex-direction: column;
padding-bottom: 24rpx;
background-color: #fafafd;
&.is-balck {
background-color: #212121;
}
}
&.is-balck {
background-color: #212121;
}
}
.content {
padding-top: 24rpx;
.content {
padding-top: 24rpx;
.content-empty {
height: 60vh;
}
}
.content-empty {
height: 60vh;
}
}
.article-card {
display: flex;
flex-direction: column;
box-sizing: border-box;
margin: 0 24rpx;
padding: 24rpx;
border-radius: 12rpx;
background-color: #ffff;
box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.03);
overflow: hidden;
margin-bottom: 24rpx;
}
.article-card {
display: flex;
flex-direction: column;
box-sizing: border-box;
margin: 0 24rpx;
padding: 24rpx;
border-radius: 12rpx;
background-color: #ffff;
box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.03);
overflow: hidden;
margin-bottom: 24rpx;
}
</style>
+142 -137
View File
@@ -1,149 +1,154 @@
<template>
<view class="app-page">
<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>
<tm-skeleton model="listAvatr"></tm-skeleton>
</view>
<block v-else>
<view class="empty" v-if="dataList.length == 0"><tm-empty icon="icon-shiliangzhinengduixiang-"
label="该分类下暂无文章"></tm-empty></view>
<block v-else>
<block v-for="(article, index) in dataList" :key="article.createTime">
<!-- 文章卡片 -->
<tm-translate animation-name="fadeUp" :wait="calcAniWait(index)"><article-card :article="article"
@on-click="fnToArticleDetail"></article-card></tm-translate>
</block>
<view class="load-text">{{ loadMoreText }}</view>
</block>
<view class="app-page">
<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>
<tm-skeleton model="listAvatr"></tm-skeleton>
</view>
<block v-else>
<view class="empty" v-if="dataList.length == 0">
<tm-empty icon="icon-shiliangzhinengduixiang-"
label="该分类下暂无文章"></tm-empty>
</view>
<block v-else>
<block v-for="(article, index) in dataList" :key="article.createTime">
<!-- 文章卡片 -->
<tm-translate animation-name="fadeUp" :wait="calcAniWait(index)">
<article-card :article="article"
@on-click="fnToArticleDetail"></article-card>
</tm-translate>
</block>
<view class="load-text">{{ loadMoreText }}</view>
</block>
<tm-flotbutton @click="fnToTopPage" color="light-blue" size="m" icon="icon-angle-up"></tm-flotbutton>
</block>
</view>
<tm-flotbutton @click="fnToTopPage" color="light-blue" size="m" icon="icon-angle-up"></tm-flotbutton>
</block>
</view>
</template>
<script>
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
import ArticleCard from '@/components/article-card/article-card.vue';
export default {
components: {
tmSkeleton,
tmTranslate,
tmFlotbutton,
tmEmpty,
ArticleCard
},
data() {
return {
loading: 'loading',
queryParams: {
size: 10,
page: 0
},
name: '',
pageTitle: '加载中...',
hasNext: false,
dataList: [],
isLoadMore: false,
loadMoreText: ''
};
},
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
import ArticleCard from '@/components/article-card/article-card.vue';
onLoad(e) {
this.name = e.name;
this.pageTitle = e.title;
this.fnGetData();
},
onPullDownRefresh() {
this.isLoadMore = false;
this.queryParams.page = 0;
this.fnGetData();
},
onReachBottom(e) {
if (this.hasNext) {
this.queryParams.page += 1;
this.isLoadMore = true;
this.fnGetData();
} else {
uni.showToast({
icon: 'none',
title: '没有更多数据了'
});
}
},
methods: {
fnGetData() {
// uni.showLoading({
// mask: true,
// title: '...'
// });
//
if (!this.isLoadMore) {
this.loading = 'loading';
}
this.loadMoreText = '加载中...';
this.$httpApi.v2
.getCategoryPostList(this.name, this.queryParams)
.then(res => {
console.log("请求成功:", res)
this.fnSetPageTitle(`${this.pageTitle} (共${res.total}篇)`);
this.hasNext = res.hasNext;
if (this.isLoadMore) {
this.dataList = this.dataList.concat(res.items);
} else {
this.dataList = res.items;
}
this.loadMoreText = res.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
setTimeout(() => {
this.loading = 'success';
}, 500);
})
.catch(err => {
console.error(err);
this.loading = 'error';
this.loadMoreText = '加载失败,请下拉刷新!';
})
.finally(() => {
setTimeout(() => {
uni.hideLoading();
uni.stopPullDownRefresh();
}, 500);
});
},
//
fnToArticleDetail(article) {
uni.navigateTo({
url: '/pagesA/article-detail/article-detail?name=' + article.metadata.name,
animationType: 'slide-in-right'
});
}
}
};
export default {
components: {
tmSkeleton,
tmTranslate,
tmFlotbutton,
tmEmpty,
ArticleCard
},
data() {
return {
loading: 'loading',
queryParams: {
size: 10,
page: 0
},
name: '',
pageTitle: '加载中...',
hasNext: false,
dataList: [],
isLoadMore: false,
loadMoreText: ''
};
},
onLoad(e) {
this.name = e.name;
this.pageTitle = e.title;
this.fnGetData();
},
onPullDownRefresh() {
this.isLoadMore = false;
this.queryParams.page = 0;
this.fnGetData();
},
onReachBottom(e) {
if (this.hasNext) {
this.queryParams.page += 1;
this.isLoadMore = true;
this.fnGetData();
} else {
uni.showToast({
icon: 'none',
title: '没有更多数据了'
});
}
},
methods: {
fnGetData() {
// uni.showLoading({
// mask: true,
// title: '...'
// });
//
if (!this.isLoadMore) {
this.loading = 'loading';
}
this.loadMoreText = '加载中...';
this.$httpApi.v2
.getCategoryPostList(this.name, this.queryParams)
.then(res => {
console.log("请求成功:", res)
this.fnSetPageTitle(`${this.pageTitle} (共${res.total}篇)`);
this.hasNext = res.hasNext;
if (this.isLoadMore) {
this.dataList = this.dataList.concat(res.items);
} else {
this.dataList = res.items;
}
this.loadMoreText = res.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
setTimeout(() => {
this.loading = 'success';
}, 500);
})
.catch(err => {
console.error(err);
this.loading = 'error';
this.loadMoreText = '加载失败,请下拉刷新!';
})
.finally(() => {
setTimeout(() => {
uni.hideLoading();
uni.stopPullDownRefresh();
}, 500);
});
},
//
fnToArticleDetail(article) {
uni.navigateTo({
url: '/pagesA/article-detail/article-detail?name=' + article.metadata.name,
animationType: 'slide-in-right'
});
}
}
};
</script>
<style lang="scss">
.app-page {
width: 100vw;
min-height: 100vh;
display: flex;
flex-direction: column;
padding: 24rpx 0;
background-color: #fafafd;
}
.app-page {
width: 100vw;
min-height: 100vh;
display: flex;
flex-direction: column;
padding: 24rpx 0;
background-color: #fafafd;
}
.loading-wrap {
padding: 0 24rpx;
min-height: 100vh;
}
.loading-wrap {
padding: 0 24rpx;
min-height: 100vh;
}
.empty {
height: 60vh;
display: flex;
align-items: center;
justify-content: center;
}
.empty {
height: 60vh;
display: flex;
align-items: center;
justify-content: center;
}
</style>
+185 -181
View File
@@ -1,197 +1,201 @@
<template>
<view class="app-page pa-6">
<view class="content pt-24 pb-24 round-4">
<!-- 表单区域 -->
<tm-form @submit="fnOnSubmit">
<tm-input :auto-focus="true" name="content" :vertical="true" required :height="220"
input-type="textarea" bg-color="grey-lighten-5" :maxlength="200" :borderBottom="false"
placeholder="请输入内容,不超过200字符..." v-model="form.content"></tm-input>
<tm-input name="author" align="right" required title="我的昵称" placeholder="请输入您的昵称..."
v-model="form.author"></tm-input>
<tm-input name="avatar" align="right" required title="我的头像" placeholder="请输入您的头像..."
v-model="form.avatar"></tm-input>
<tm-input name="email" align="right" required title="邮箱地址" placeholder="请输入您的邮箱..."
v-model="form.email"></tm-input>
<tm-input name="authorUrl" align="right" required title="我的网站" placeholder="请输入您的网址..."
v-model="form.authorUrl"></tm-input>
<view class="pa-24 pl-30 pr-30"><tm-button navtie-type="form" theme="bg-gradient-blue-accent"
block>提交</tm-button></view>
</tm-form>
</view>
</view>
<view class="app-page pa-6">
<view class="content pt-24 pb-24 round-4">
<!-- 表单区域 -->
<tm-form @submit="fnOnSubmit">
<tm-input :auto-focus="true" name="content" :vertical="true" required :height="220"
input-type="textarea" bg-color="grey-lighten-5" :maxlength="200" :borderBottom="false"
placeholder="请输入内容,不超过200字符..." v-model="form.content"></tm-input>
<tm-input name="author" align="right" required title="我的昵称" placeholder="请输入您的昵称..."
v-model="form.author"></tm-input>
<tm-input name="avatar" align="right" required title="我的头像" placeholder="请输入您的头像..."
v-model="form.avatar"></tm-input>
<tm-input name="email" align="right" required title="邮箱地址" placeholder="请输入您的邮箱..."
v-model="form.email"></tm-input>
<tm-input name="authorUrl" align="right" required title="我的网站" placeholder="请输入您的网址..."
v-model="form.authorUrl"></tm-input>
<view class="pa-24 pl-30 pr-30">
<tm-button navtie-type="form" theme="bg-gradient-blue-accent"
block>提交
</tm-button>
</view>
</tm-form>
</view>
</view>
</template>
<script>
import tmForm from '@/tm-vuetify/components/tm-form/tm-form.vue';
import tmInput from '@/tm-vuetify/components/tm-input/tm-input.vue';
import tmSwitch from '@/tm-vuetify/components/tm-switch/tm-switch.vue';
import tmButton from '@/tm-vuetify/components/tm-button/tm-button.vue';
import tmForm from '@/tm-vuetify/components/tm-form/tm-form.vue';
import tmInput from '@/tm-vuetify/components/tm-input/tm-input.vue';
import tmSwitch from '@/tm-vuetify/components/tm-switch/tm-switch.vue';
import tmButton from '@/tm-vuetify/components/tm-button/tm-button.vue';
export default {
components: {
tmForm,
tmInput,
tmSwitch,
tmButton
},
data() {
return {
isComment: true,
params: {
postName: '',
title: '', // type=user =
form: '',
formPage: '', //
type: 'post' // / user=
},
form: {
allowNotification: true,
author: '', //
avatar: '',
authorUrl: '', //
content: '', //
email: '', //
postName: ""
}
};
},
onLoad() {
this.params = this.$Route.query;
this.isComment = this.params.isComment;
this.form.postName = this.params.postName;
export default {
components: {
tmForm,
tmInput,
tmSwitch,
tmButton
},
data() {
return {
isComment: true,
params: {
postName: '',
title: '', // type=user =
form: '',
formPage: '', //
type: 'post' // / user=
},
form: {
allowNotification: true,
author: '', //
avatar: '',
authorUrl: '', //
content: '', //
email: '', //
postName: ""
}
};
},
onLoad() {
this.params = this.$Route.query;
this.isComment = this.params.isComment;
this.form.postName = this.params.postName;
if (!this.isComment) {
this.fnSetPageTitle('回复用户:' + this.params.title);
} else {
this.fnSetPageTitle(this.params.title);
}
if (!this.isComment) {
this.fnSetPageTitle('回复用户:' + this.params.title);
} else {
this.fnSetPageTitle(this.params.title);
}
try {
let visitor = uni.getStorageSync('Visitor')
if (visitor) {
visitor = JSON.parse(visitor)
this.form.author = visitor.author;
this.form.avatar = visitor.avatar;
this.form.email = visitor.email;
this.form.authorUrl = visitor.authorUrl;
}
} catch (e) {}
},
methods: {
fnOnSubmit(e) {
if (e === false) {
return uni.$tm.toast('请检查所有的必填项是否填写完整!');
}
if (!this.form.email) {
return uni.$tm.toast('未填写邮箱地址,将无法接收提醒!');
}
if (this.form.email && !uni.$tm.test.email(this.form.email)) {
return uni.$tm.toast('请填写正确的邮箱地址!');
}
if (this.form.authorUrl && !uni.$tm.test.url(this.form.authorUrl)) {
return uni.$tm.toast('请输入正确的Url地址!');
}
this.fnHandle();
},
handleSetVisitor() {
uni.setStorageSync('Visitor', JSON.stringify({
author: this.form.author,
avatar: this.form.avatar,
email: this.form.email,
authorUrl: this.form.authorUrl,
}))
},
fnHandle() {
uni.showLoading({
title: '正在提交...'
});
try {
let visitor = uni.getStorageSync('Visitor')
if (visitor) {
visitor = JSON.parse(visitor)
this.form.author = visitor.author;
this.form.avatar = visitor.avatar;
this.form.email = visitor.email;
this.form.authorUrl = visitor.authorUrl;
}
} catch (e) {
}
},
methods: {
fnOnSubmit(e) {
if (e === false) {
return uni.$tm.toast('请检查所有的必填项是否填写完整!');
}
if (!this.form.email) {
return uni.$tm.toast('未填写邮箱地址,将无法接收提醒!');
}
if (this.form.email && !uni.$tm.test.email(this.form.email)) {
return uni.$tm.toast('请填写正确的邮箱地址!');
}
if (this.form.authorUrl && !uni.$tm.test.url(this.form.authorUrl)) {
return uni.$tm.toast('请输入正确的Url地址!');
}
this.fnHandle();
},
handleSetVisitor() {
uni.setStorageSync('Visitor', JSON.stringify({
author: this.form.author,
avatar: this.form.avatar,
email: this.form.email,
authorUrl: this.form.authorUrl,
}))
},
fnHandle() {
uni.showLoading({
title: '正在提交...'
});
//
if (this.isComment) {
const commentForm = {
allowNotification: true,
raw: this.form.content,
content: this.form.content,
owner: {
avatar: this.form.avatar,
displayName: this.form.author,
email: this.form.email,
website: this.form.authorUrl,
},
subjectRef: {
group: "content.halo.run",
kind: "Post",
name: this.form.postName,
version: "v1alpha1",
}
}
this.$httpApi.v2.addPostComment(commentForm)
.then(res => {
uni.$tm.toast('提交成功!');
//
this.handleSetVisitor();
setTimeout(() => {
uni.navigateBack()
}, 1500)
})
.catch(err => {
uni.$tm.toast("评论失败");
});
return;
}
//
if (this.isComment) {
const commentForm = {
allowNotification: true,
raw: this.form.content,
content: this.form.content,
owner: {
avatar: this.form.avatar,
displayName: this.form.author,
email: this.form.email,
website: this.form.authorUrl,
},
subjectRef: {
group: "content.halo.run",
kind: "Post",
name: this.form.postName,
version: "v1alpha1",
}
}
this.$httpApi.v2.addPostComment(commentForm)
.then(res => {
uni.$tm.toast('提交成功!');
//
this.handleSetVisitor();
setTimeout(() => {
uni.navigateBack()
}, 1500)
})
.catch(err => {
uni.$tm.toast("评论失败");
});
return;
}
//
const replyForm = {
allowNotification: true,
raw: this.form.content,
content: this.form.content,
owner: {
avatar: this.form.avatar,
displayName: this.form.author,
email: this.form.email,
website: this.form.authorUrl,
},
quoteReply: this.form.postName
}
this.$httpApi.v2.addPostCommentReply(this.form.postName, replyForm)
.then(res => {
uni.$tm.toast('提交成功!');
//
this.handleSetVisitor();
setTimeout(() => {
uni.navigateBack()
}, 1500)
})
.catch(err => {
uni.$tm.toast("回复失败");
});
}
}
};
//
const replyForm = {
allowNotification: true,
raw: this.form.content,
content: this.form.content,
owner: {
avatar: this.form.avatar,
displayName: this.form.author,
email: this.form.email,
website: this.form.authorUrl,
},
quoteReply: this.form.postName
}
this.$httpApi.v2.addPostCommentReply(this.form.postName, replyForm)
.then(res => {
uni.$tm.toast('提交成功!');
//
this.handleSetVisitor();
setTimeout(() => {
uni.navigateBack()
}, 1500)
})
.catch(err => {
uni.$tm.toast("回复失败");
});
}
}
};
</script>
<style scoped lang="scss">
.app-page {
width: 100vw;
min-height: 100vh;
box-sizing: border-box;
// background-color: #fafafd;
background-color: #ffffff;
.app-page {
width: 100vw;
min-height: 100vh;
box-sizing: border-box;
// background-color: #fafafd;
background-color: #ffffff;
.content {
overflow: hidden;
background-color: #fff;
// box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.05);
}
}
.content {
overflow: hidden;
background-color: #fff;
// box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.05);
}
}
.poup-content {
width: 500rpx;
.poup-content {
width: 500rpx;
::v-deep {
.slider_id {
width: 100% !important;
}
}
}
::v-deep {
.slider_id {
width: 100% !important;
}
}
}
</style>
+251 -238
View File
@@ -1,256 +1,269 @@
<template>
<view class="app-page flex flex-col felx-center bg-white">
<!-- 信息 -->
<view class="profile flex flex-col flex-center pa-36">
<view class="avatar"><image class="avatar-img" :src="bloggerInfo.avatar" mode="aspectFill"></image></view>
<view class="nickname mt-24 text-weight-b text-size-g">{{ bloggerInfo.nickname }}</view>
<view class="desc mt-24 text-size-m text-grey-darken-3">
{{ bloggerInfo.description || '这个博主很懒,竟然没写介绍~' }}
</view>
<!-- 联系图标 -->
<view class="mt-24 contact-icons">
<!-- 放全部似乎显得有点拥挤 -->
<!-- <block v-for="(item, index) in result" :key="index"><text v-if="item.value" class="halocoloricon" :class="[item.icon, { 'ml-12': index != 0 }]"></text></block> -->
<!-- 考虑放几个常用的就行 -->
<text class="halocoloricon halocoloricon-qq"></text>
<!-- #ifndef MP-QQ -->
<text class="ml-12 halocoloricon halocoloricon-wechat"></text>
<!-- #endif -->
<text class="ml-12 halocoloricon halocoloricon-GitHub"></text>
<text class="ml-12 halocoloricon halocoloricon-gitee"></text>
<text class="ml-12 halocoloricon halocoloricon-ic_email_round"></text>
</view>
<view v-if="false" class="mt-24 ">
<tm-button theme="bg-gradient-light-blue-accent" size="m" openType="contact">在线客服联系</tm-button>
<tm-button theme="bg-gradient-orange-accent" size="m" @click="fnOnToWeb">访问PC端博客</tm-button>
</view>
</view>
<!-- 社交联系方式列表 -->
<view class="contact ma-50 mt-0 pt-12">
<block v-for="(item, index) in result" :key="index">
<view v-if="item.value" class="item mt-24 flex" @click="fnOnClick(item)">
<view class="left">
<text class="icon halocoloricon" :class="[item.icon]"></text>
<text class="name">{{ item.name }}</text>
</view>
<view class="right flex-1">{{ item.value }}</view>
</view>
</block>
</view>
</view>
<view class="app-page flex flex-col felx-center bg-white">
<!-- 信息 -->
<view class="profile flex flex-col flex-center pa-36">
<view class="avatar">
<image class="avatar-img" :src="bloggerInfo.avatar" mode="aspectFill"></image>
</view>
<view class="nickname mt-24 text-weight-b text-size-g">{{ bloggerInfo.nickname }}</view>
<view class="desc mt-24 text-size-m text-grey-darken-3">
{{ bloggerInfo.description || '这个博主很懒,竟然没写介绍~' }}
</view>
<!-- 联系图标 -->
<view class="mt-24 contact-icons">
<!-- 放全部似乎显得有点拥挤 -->
<!-- <block v-for="(item, index) in result" :key="index"><text v-if="item.value" class="halocoloricon" :class="[item.icon, { 'ml-12': index != 0 }]"></text></block> -->
<!-- 考虑放几个常用的就行 -->
<text class="halocoloricon halocoloricon-qq"></text>
<!-- #ifndef MP-QQ -->
<text class="ml-12 halocoloricon halocoloricon-wechat"></text>
<!-- #endif -->
<text class="ml-12 halocoloricon halocoloricon-GitHub"></text>
<text class="ml-12 halocoloricon halocoloricon-gitee"></text>
<text class="ml-12 halocoloricon halocoloricon-ic_email_round"></text>
</view>
</view>
<!-- 社交联系方式列表 -->
<view class="contact ma-50 mt-0 pt-12">
<block v-if="calcIsNotEmpty">
<block v-for="(item, index) in result" :key="index">
<view v-if="item.value" class="item mt-24 flex" @click="fnOnClick(item)">
<view class="left">
<text class="icon halocoloricon" :class="[item.icon]"></text>
<text class="name">{{ item.name }}</text>
</view>
<view class="right flex-1">{{ item.value }}</view>
</view>
</block>
</block>
<view v-else class="mt-12 pt-12">
<tm-empty icon="icon-shiliangzhinengduixiang-" label="暂无联系方式"/>
</view>
</view>
</view>
</template>
<script>
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmButton from '@/tm-vuetify/components/tm-button/tm-button.vue';
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
export default {
components: {
tmSkeleton,
tmButton
},
data() {
return {
loading: 'loading',
queryParams: {
size: 10,
page: 0
},
result: [
{
key: 'qq',
icon: 'halocoloricon-qq',
name: '企鹅号',
value: ''
},
{
key: 'wechat',
icon: 'halocoloricon-wechat',
name: '微信号',
value: ''
},
{
key: 'github',
icon: 'halocoloricon-GitHub',
name: 'Github',
value: ''
},
{
key: 'gitee',
icon: 'halocoloricon-gitee',
name: 'Gitee',
value: ''
},
{
key: 'bilibili',
icon: 'halocoloricon-bilibili',
name: 'Bilibili',
value: ''
},
{
key: 'csdn',
icon: 'halocoloricon-csdn1',
name: 'CSDN',
value: ''
},
{
key: 'blog',
icon: 'halocoloricon-url-monitor',
name: '博客地址',
value: ''
},
{
key: 'juejin',
icon: 'halocoloricon-juejin',
name: '掘金地址',
value: ''
},
components: {
tmSkeleton,
tmButton,
tmEmpty
},
data() {
return {
loading: 'loading',
queryParams: {
size: 10,
page: 0
},
result: [
{
key: 'qq',
icon: 'halocoloricon-qq',
name: '企鹅号',
value: ''
},
{
key: 'wechat',
icon: 'halocoloricon-wechat',
name: '微信号',
value: ''
},
{
key: 'github',
icon: 'halocoloricon-GitHub',
name: 'Github',
value: ''
},
{
key: 'gitee',
icon: 'halocoloricon-gitee',
name: 'Gitee',
value: ''
},
{
key: 'bilibili',
icon: 'halocoloricon-bilibili',
name: 'Bilibili',
value: ''
},
{
key: 'csdn',
icon: 'halocoloricon-csdn1',
name: 'CSDN',
value: ''
},
{
key: 'blog',
icon: 'halocoloricon-url-monitor',
name: '博客地址',
value: ''
},
{
key: 'juejin',
icon: 'halocoloricon-juejin',
name: '掘金地址',
value: ''
},
{
key: 'weibo',
icon: 'halocoloricon-social-weibo',
name: '微博地址',
value: ''
},
{
key: 'email',
icon: 'halocoloricon-ic_email_round',
name: '邮箱地址',
value: ''
}
]
};
},
computed: {
//
bloggerInfo() {
let blogger = this.$tm.vx.getters().getBlogger;
blogger.avatar = this.$utils.checkAvatarUrl(blogger.avatar, true);
return blogger;
}
},
onLoad() {
this.fnSetPageTitle('联系博主');
},
created() {
this.fnGetData();
},
methods: {
fnGetData() {
for (let key in this.$haloConfig.social) {
this.result.find(x => x.key == key).value = this.$haloConfig.social[key];
}
},
fnOnToWeb() {
uni.navigateTo({
url:
'/pagesC/website/website?data=' +
JSON.stringify({
title: this.$haloConfig.title,
url: this.$haloConfig.social.blog
})
});
},
fnOnClick(item) {
if (this.globalAppSettings.contact.isLinkCopy && this.$utils.checkIsUrl(item.value)) {
uni.navigateTo({
url:
'/pagesC/website/website?data=' +
JSON.stringify({
title: item.name,
url: item.value
})
});
} else {
this.$utils.copyText(item.value, item.name + ' 已复制!');
}
}
}
{
key: 'weibo',
icon: 'halocoloricon-social-weibo',
name: '微博地址',
value: ''
},
{
key: 'email',
icon: 'halocoloricon-ic_email_round',
name: '邮箱地址',
value: ''
}
]
};
},
computed: {
authorConfig() {
return this.$tm.vx.getters().getConfigs.authorConfig;
},
bloggerInfo() {
let blogger = this.authorConfig.blogger;
blogger.avatar = this.$utils.checkAvatarUrl(blogger.avatar, true);
return blogger;
},
socialConfig() {
return this.authorConfig.social
},
calcIsNotEmpty() {
return this.result.some((item) => item.value !== "");
}
},
onLoad() {
this.fnSetPageTitle('联系博主');
},
created() {
this.fnGetData();
},
methods: {
fnGetData() {
for (let key in this.socialConfig) {
this.result.find(x => x.key === key).value = this.socialConfig[key];
}
},
fnOnClick(item) {
if (this.globalAppSettings.contact.isLinkCopy && this.$utils.checkIsUrl(item.value)) {
uni.navigateTo({
url: '/pagesC/website/website?data=' +
JSON.stringify({
title: item.name,
url: item.value
})
});
} else {
this.$utils.copyText(item.value, item.name + ' 已复制!');
}
}
}
};
</script>
<style lang="scss" scoped>
.app-page {
width: 100vw;
min-height: 100vh;
box-sizing: border-box;
padding-top: 160rpx;
width: 100vw;
min-height: 100vh;
box-sizing: border-box;
padding-top: 160rpx;
}
.profile {
.avatar {
width: 170rpx;
height: 170rpx;
position: relative;
box-sizing: border-box;
border-radius: 50%;
border: 6rpx solid #fff;
box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.07);
overflow: hidden;
&-img {
width: 100%;
height: 100%;
}
}
.nickname {
font-size: 38rpx;
}
}
.contact-icons {
.halocoloricon {
font-size: 42rpx;
}
}
.contact {
box-sizing: border-box;
border-top: 2rpx solid #f2f2f2;
.item {
box-sizing: border-box;
border-radius: 12rpx;
background-color: #fafafa;
// background-color: rgba(0, 0, 0, 0.05);
// padding-bottom: 12rpx;
// border-bottom: 2rpx solid #eee;
padding: 16rpx;
.left {
position: relative;
width: 140rpx;
display: flex;
align-items: center;
box-sizing: border-box;
// background-color: rgba(0, 0, 0, 0.03);
border-radius: 12rpx 0 0 12rpx;
&::after {
display: none;
content: ':';
position: absolute;
right: 18rpx;
top: 50%;
transform: translateY(-50%);
font-size: 24rpx;
color: #666;
}
.icon {
font-size: 24rpx;
}
.name {
margin-left: 10rpx;
color: #555;
font-size: 24rpx;
}
}
.right {
width: 0;
display: flex;
align-items: center;
flex-wrap: wrap;
box-sizing: border-box;
word-wrap: break-word;
word-break: break-all;
font-size: 24rpx;
box-sizing: border-box;
padding-left: 12rpx;
}
}
.profile {
.avatar {
width: 170rpx;
height: 170rpx;
position: relative;
box-sizing: border-box;
border-radius: 50%;
border: 6rpx solid #fff;
box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.07);
overflow: hidden;
&-img {
width: 100%;
height: 100%;
}
}
.nickname {
font-size: 38rpx;
}
}
.contact-icons {
.halocoloricon {
font-size: 42rpx;
}
}
.contact {
box-sizing: border-box;
border-top: 2rpx solid #f2f2f2;
.item {
box-sizing: border-box;
border-radius: 12rpx;
background-color: #fafafa;
// background-color: rgba(0, 0, 0, 0.05);
// padding-bottom: 12rpx;
// border-bottom: 2rpx solid #eee;
padding: 16rpx;
.left {
position: relative;
width: 140rpx;
display: flex;
align-items: center;
box-sizing: border-box;
// background-color: rgba(0, 0, 0, 0.03);
border-radius: 12rpx 0 0 12rpx;
&::after {
display: none;
content: ':';
position: absolute;
right: 18rpx;
top: 50%;
transform: translateY(-50%);
font-size: 24rpx;
color: #666;
}
.icon {
font-size: 24rpx;
}
.name {
margin-left: 10rpx;
color: #555;
font-size: 24rpx;
}
}
.right {
width: 0;
display: flex;
align-items: center;
flex-wrap: wrap;
box-sizing: border-box;
word-wrap: break-word;
word-break: break-all;
font-size: 24rpx;
box-sizing: border-box;
padding-left: 12rpx;
}
}
}
</style>
+39 -30
View File
@@ -1,42 +1,51 @@
<template>
<view class="app-page bg-white round-3 pa-46">
<view class="text-weight-b text-size-lg text-align-center"> 本博客免责声明 </view>
<view v-if="false" class="text-size-s text-align-center mt-12 text-grey-darken-1"> 博主{{ bloggerInfo.nickname }} </view>
<view class="mt-32">1本博客属于个人非赢利性质的网站所有转载的文章都以遵循原作者的版权声明注明了文章来源</view>
<view class="mt-24">2如果原文没有版权声明按照目前互联网开放的原则本博客将在不通知作者的情况下转载文章</view>
<view class="mt-24">3如果原文明确注明禁止转载本博客将不会转载</view>
<view class="mt-24">
4如果本博客转载的文章不符合作者的版权声明或者作者不想让本博客转载您的文章请邮件告知
<text class="text-bg-gradient-light-blue-accent ml-12 mr-12 " @click="$utils.copyText(bloggerInfo.email, '邮箱复制成功!')">
<text class="iconfont icon-mail-fill text-size-m mr-6"></text>
{{ bloggerInfo.email }}
</text>
博主将会在第一时间删除相关信息
</view>
<view class="mt-24">5本博客转载文章仅为留作备份和知识点分享的目的</view>
<view class="mt-24">6本博客将尽力确保所提供信息的准确性及可靠性但不保证信息的正确性和完整性且不对因信息的不正确或遗漏导致的任何损失或损害承担相关责任</view>
<view class="mt-24">
7本博客所发布转载的文章其版权均归原作者所有如其他自媒体网站或个人从本博客下载使用请在转载有关文章时务必尊重该文章的著作权保留本博客注明的原文来源或者自行去原文处复制版权声明并自负版权等法律责任
</view>
<view class="mt-24">8本博客的所有原创文章皆可以任意转载但转载时务必请注明出处</view>
<view class="mt-24">9尊重原创知识共享</view>
</view>
<view class="app-page bg-white round-3 pa-46">
<!-- 通过配置 -->
<view style="min-height: 100%;" v-html="disclaimersContent"></view>
<!-- 静态写法 -->
<block v-if="false">
<view class="text-weight-b text-size-lg text-align-center"> 本博客免责声明 </view>
<view v-if="false" class="text-size-s text-align-center mt-12 text-grey-darken-1"> 博主{{ bloggerInfo.nickname }} </view>
<view class="mt-32">1本博客属于个人非赢利性质的网站所有转载的文章都以遵循原作者的版权声明注明了文章来源</view>
<view class="mt-24">2如果原文没有版权声明按照目前互联网开放的原则本博客将在不通知作者的情况下转载文章</view>
<view class="mt-24">3如果原文明确注明禁止转载本博客将不会转载</view>
<view class="mt-24">
4如果本博客转载的文章不符合作者的版权声明或者作者不想让本博客转载您的文章请邮件告知
<text class="text-bg-gradient-light-blue-accent ml-12 mr-12 ">
<text class="iconfont icon-mail-fill text-size-m mr-6"></text>
studio@925i.cn
</text>
博主将会在第一时间删除相关信息
</view>
<view class="mt-24">5本博客转载文章仅为留作备份和知识点分享的目的</view>
<view class="mt-24">
6本博客将尽力确保所提供信息的准确性及可靠性但不保证信息的正确性和完整性且不对因信息的不正确或遗漏导致的任何损失或损害承担相关责任
</view>
<view class="mt-24">
7本博客所发布转载的文章其版权均归原作者所有如其他自媒体网站或个人从本博客下载使用请在转载有关文章时务必尊重该文章的著作权保留本博客注明的原文来源或者自行去原文处复制版权声明并自负版权等法律责任
</view>
<view class="mt-24">8本博客的所有原创文章皆可以任意转载但转载时务必请注明出处</view>
<view class="mt-24">9尊重原创知识共享</view>
</block>
</view>
</template>
<script>
export default {
computed: {
bloggerInfo() {
return this.$tm.vx.getters().getBlogger;
}
}
computed: {
disclaimersContent() {
const configs = this.$tm.vx.getters().getAppConfigs;
return configs.basicConfig.disclaimers.content
}
}
};
</script>
<style scoped lang="scss">
.app-page {
line-height: 1.65;
font-size: 30rpx;
color: var(--main-text-color);
line-height: 1.65;
font-size: 30rpx;
color: var(--main-text-color);
}
</style>
+21 -13
View File
@@ -26,8 +26,8 @@
</view>
<view class="flex flex-col pl-30 info-detail">
<view class="link-card_name text-size-l text-weight-b text-red">
<tm-tags style="margin-right: 12rpx;margin-left: -2rpx;" color="bg-gradient-light-blue-lighten"
:shadow="0" size="s" model="fill">
<tm-tags style="margin-right: 12rpx;margin-left: -2rpx;"
color="bg-gradient-light-blue-lighten" :shadow="0" size="s" model="fill">
{{ link.spec.groupName || '暂未分组' }}
</tm-tags>
{{ link.spec.displayName }}
@@ -120,7 +120,8 @@
<!-- 返回顶部 -->
<tm-flotbutton color="light-blue" @click="fnToTopPage" size="m" icon="icon-angle-up"></tm-flotbutton>
<tm-flotbutton v-if="haloPluginsConfig.autoSubmitLink.enabled" :offset="[16,80]" label="申请" actions-pos="left" :show-text="true" color="bg-gradient-orange-accent"
<tm-flotbutton v-if="haloPluginConfigs.submitLink.enabled" :offset="[16,80]" label="申请"
actions-pos="left" :show-text="true" color="bg-gradient-orange-accent"
@click="toSubmitLinkPage"></tm-flotbutton>
<!-- 详情弹窗 -->
<tm-poup v-model="detail.show" :width="640" height="auto" position="center" :round="6">
@@ -152,7 +153,7 @@
<!-- 博客预览图 -->
<view class="mt-24">
<tm-images :width="568" :round="2" :src="caclSiteThumbnail(detail.data.url)"
<tm-images :width="568" :round="2" :src="calcSiteThumbnail(detail.data.url)"
mode="aspectFill"></tm-images>
</view>
</view>
@@ -172,7 +173,6 @@ import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
import tmImages from '@/tm-vuetify/components/tm-images/tm-images.vue';
import tmPoup from '@/tm-vuetify/components/tm-poup/tm-poup.vue';
import {GetRandomNumberByRange} from '@/utils/random.js';
export default {
@@ -200,14 +200,25 @@ export default {
isLoadMore: false,
loadMoreText: '',
dataList: [],
cacheDataList: []
cacheDataList: [],
colors: [
'#39B449',
'#E44C41',
'#8698A2',
'#0080FE',
'#1CBCB4',
'#6638B5'
]
};
},
computed: {
caclSiteThumbnail(val) {
haloPluginConfigs(){
return this.$tm.vx.getters().getConfigs.pluginConfig;
},
calcSiteThumbnail(val) {
return val => {
if (!val) return '';
if (val.charAt(val.length - 1) != '/') {
if (val.charAt(val.length - 1) !== '/') {
val = val + '/';
}
return 'https://image.thum.io/get/width/1000/crop/800/' + val;
@@ -239,8 +250,8 @@ export default {
},
methods: {
fnRandomColor() {
const _r = GetRandomNumberByRange(0, this.$haloConfig.colors.length - 1);
return this.$haloConfig.colors[_r];
const _r = GetRandomNumberByRange(0, this.colors.length - 1);
return this.colors[_r];
},
fnGetData() {
if (!this.isLoadMore) {
@@ -259,9 +270,6 @@ export default {
return item;
})
this.dataList = this.dataList.concat(list);
// this.cacheDataList = this.cacheDataList.concat(list);
// this.dataList = this.handleGroup(this.cacheDataList).reverse();
setTimeout(() => {
this.loading = 'success';
this.loadMoreText = res.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
+121 -119
View File
@@ -1,135 +1,137 @@
<template>
<view class="app-page">
<view v-if="loading != 'success'" class="loading-wrap pa-24">
<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 pa-24">
<view v-if="dataList.length == 0" class="content-empty flex flex-center">
<!-- 空布局 -->
<tm-empty icon="icon-shiliangzhinengduixiang-" label="博主还没有写任何日记"></tm-empty>
</view>
<block v-else>
<block v-for="(journal, index) in dataList" :key="index">
<tm-translate animation-name="fadeUp" :wait="calcAniWait(index)">
<!-- 日记卡片 -->
<journal-card :journal="journal" :useLike="true"></journal-card>
</tm-translate>
</block>
<view class="app-page">
<view v-if="loading != 'success'" class="loading-wrap pa-24">
<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 pa-24">
<view v-if="dataList.length == 0" class="content-empty flex flex-center">
<!-- 空布局 -->
<tm-empty icon="icon-shiliangzhinengduixiang-" label="博主还没有写任何日记"></tm-empty>
</view>
<block v-else>
<block v-for="(journal, index) in dataList" :key="index">
<tm-translate animation-name="fadeUp" :wait="calcAniWait(index)">
<!-- 日记卡片 -->
<journal-card :journal="journal" :useLike="true"></journal-card>
</tm-translate>
</block>
<tm-flotbutton @click="fnToTopPage" color="light-blue" size="m" icon="icon-angle-up"></tm-flotbutton>
<view class="load-text">{{ loadMoreText }}</view>
</block>
</view>
</view>
<tm-flotbutton @click="fnToTopPage" color="light-blue" size="m" icon="icon-angle-up"></tm-flotbutton>
<view class="load-text">{{ loadMoreText }}</view>
</block>
</view>
</view>
</template>
<script>
import MarkdownConfig from '@/common/markdown/markdown.config.js';
import mpHtml from '@/components/mp-html/components/mp-html/mp-html.vue';
import journalCard from '@/components/journal-card/journal-card.vue';
import MarkdownConfig from '@/common/markdown/markdown.config.js';
import mpHtml from '@/components/mp-html/components/mp-html/mp-html.vue';
import journalCard from '@/components/journal-card/journal-card.vue';
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
export default {
components: { mpHtml, tmSkeleton, tmEmpty, tmTranslate, tmFlotbutton, journalCard },
data() {
return {
loading: 'loading',
markdownConfig: MarkdownConfig,
queryParams: {
size: 10,
page: 0
},
export default {
components: {mpHtml, tmSkeleton, tmEmpty, tmTranslate, tmFlotbutton, journalCard},
data() {
return {
loading: 'loading',
markdownConfig: MarkdownConfig,
queryParams: {
size: 10,
page: 0
},
dataList: [],
hasNext:false,
isLoadMore: false,
loadMoreText: '加载中...'
};
},
dataList: [],
hasNext: false,
isLoadMore: false,
loadMoreText: '加载中...'
};
},
onLoad() {
this.fnSetPageTitle('个人日记');
},
created() {
this.fnGetData();
},
onPullDownRefresh() {
this.isLoadMore = false;
this.queryParams.page = 0;
this.fnGetData();
},
onReachBottom(e) {
if (this.hasNext) {
this.queryParams.page += 1;
this.isLoadMore = true;
this.fnGetData();
} else {
uni.showToast({
icon: 'none',
title: '没有更多数据了'
});
}
},
methods: {
fnGetData() {
// uni.showLoading({
// mask: true,
// title: '...'
// });
//
if (!this.isLoadMore) {
this.loading = 'loading';
}
this.loadMoreText = '加载中...';
this.$httpApi
.getJournals(this.queryParams)
.then(res => {
this.loading = 'success';
this.loadMoreText = res.data.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
//
this.result = res.data;
if (this.isLoadMore) {
this.dataList = this.dataList.concat(res.data.content);
} else {
this.dataList = res.data.content;
}
this.loading = 'success';
})
.catch(err => {
console.error(err);
this.loading = 'error';
this.loadMoreText = '加载失败,请下拉刷新!';
})
.finally(() => {
setTimeout(() => {
uni.hideLoading();
uni.stopPullDownRefresh();
}, 500);
});
}
}
};
onLoad() {
this.fnSetPageTitle('个人日记');
},
created() {
this.fnGetData();
},
onPullDownRefresh() {
this.isLoadMore = false;
this.queryParams.page = 0;
this.fnGetData();
},
onReachBottom(e) {
if (this.hasNext) {
this.queryParams.page += 1;
this.isLoadMore = true;
this.fnGetData();
} else {
uni.showToast({
icon: 'none',
title: '没有更多数据了'
});
}
},
methods: {
fnGetData() {
// uni.showLoading({
// mask: true,
// title: '...'
// });
//
if (!this.isLoadMore) {
this.loading = 'loading';
}
this.loadMoreText = '加载中...';
this.$httpApi
.getJournals(this.queryParams)
.then(res => {
this.loading = 'success';
this.loadMoreText = res.data.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
//
this.result = res.data;
if (this.isLoadMore) {
this.dataList = this.dataList.concat(res.data.content);
} else {
this.dataList = res.data.content;
}
this.loading = 'success';
})
.catch(err => {
console.error(err);
this.loading = 'error';
this.loadMoreText = '加载失败,请下拉刷新!';
})
.finally(() => {
setTimeout(() => {
uni.hideLoading();
uni.stopPullDownRefresh();
}, 500);
});
}
}
};
</script>
<style lang="scss" scoped>
.app-page {
width: 100vw;
display: flex;
flex-direction: column;
}
.app-page {
width: 100vw;
display: flex;
flex-direction: column;
}
.loading-wrap {}
.loading-wrap {
}
.app-page-content {}
.app-page-content {
}
.content-empty {
height: 60vh;
}
.content-empty {
height: 60vh;
}
</style>
+340 -333
View File
@@ -1,78 +1,69 @@
<template>
<view class="app-page">
<view v-if="loading != 'success'" class="loading-wrap">
<view v-if="loading == 'loading'" class="loading">
<view class="loading-icon flex flex-center"><text class="e-loading-icon iconfont icon-loading"></text></view>
<view class="loadig-text ">相册正在努力加载中啦~</view>
</view>
<tm-empty v-else icon="icon-shiliangzhinengduixiang-" color="red" label="啊偶,加载失败了呢~">
<tm-button theme="red" :shadow="0" size="m" @click="fnRefresh()">刷新试试</tm-button>
</tm-empty>
</view>
<!-- 内容区域 -->
<view v-else class="app-page-content">
<view v-if="dataList.length == 0" color="light-blue" class="content-empty flex flex-center">
<tm-empty icon="icon-shiliangzhinengduixiang-" label="相册暂时还没有数据~">
<tm-button :shadow="0" size="m" theme="light-blue" @click="fnRefresh()">刷新试试</tm-button>
</tm-empty>
</view>
<block v-else>
<swiper
class="swiper-album"
:current="swiperIndex"
:acceleration="true"
:circular="true"
:vertical="false"
:indicator-dots="false"
:autoplay="false"
@change="fnOnChange"
>
<block v-for="(item, index) in dataList" :key="index">
<swiper-item class="swiper-album-item">
<view class="scroll-wrap">
<view class="card">
<cache-image
class="card-image"
width="100%"
height="46vh"
radius="12rpx"
:url="item.image"
:fileMd5="item.image"
mode="aspectFill"
@on-click="fnOnPreview(item)"
></cache-image>
<view v-if="item.description" class="card-desc">{{ item.description }}</view>
<view v-else class="card-desc is-empty flex flex-col">
<view class="text-grey-darken-1">该照片没有记录任何信息</view>
<view class="text-size-m mt-24 text-grey-darken-1">记录一下拍照的瞬间会更精彩哟</view>
</view>
</view>
</view>
</swiper-item>
</block>
</swiper>
<view class="tabbar">
<view class="pre" @click="fnChange(false)">
<text class="icon"><text class="iconfont icon-arrow-left"></text></text>
<text class="text">上一张</text>
</view>
<view class="refresh" @click="fnRefresh()">
<text class="refresh-text">点击</text>
<text class="refresh-heart iconfont icon-diagnose"></text>
<text class="refresh-text">刷新</text>
</view>
<view class="next" @click="fnChange(true)">
<text class="text">下一张</text>
<text class="icon"><text class="iconfont icon-arrow-right"></text></text>
</view>
</view>
</block>
</view>
</view>
<view class="app-page">
<view v-if="loading !== 'success'" class="loading-wrap">
<view v-if="loading === 'loading'" class="loading">
<view class="loading-icon flex flex-center">
<text class="e-loading-icon iconfont icon-loading"></text>
</view>
<view class="loadig-text ">相册正在努力加载中啦~</view>
</view>
<tm-empty v-else icon="icon-shiliangzhinengduixiang-" color="red" label="啊偶,加载失败了呢~">
<tm-button theme="red" :shadow="0" size="m" @click="fnRefresh()">刷新试试</tm-button>
</tm-empty>
</view>
<!-- 内容区域 -->
<view v-else class="app-page-content">
<view v-if="dataList.length === 0" color="light-blue" class="content-empty flex flex-center">
<tm-empty icon="icon-shiliangzhinengduixiang-" label="相册暂时还没有数据~">
<tm-button :shadow="0" size="m" theme="light-blue" @click="fnRefresh()">刷新试试</tm-button>
</tm-empty>
</view>
<block v-else>
<swiper class="swiper-album" :current="swiperIndex" :acceleration="true" :circular="true"
:vertical="false" :indicator-dots="false" :autoplay="false" @change="fnOnChange">
<block v-for="(item, index) in dataList" :key="index">
<swiper-item class="swiper-album-item">
<view class="scroll-wrap">
<view class="card">
<cache-image class="card-image" width="100%" height="46vh" radius="12rpx"
:url="item.image" :fileMd5="item.image" mode="aspectFill"
@on-click="fnOnPreview(item)"></cache-image>
<view v-if="item.spec.description" class="card-desc">{{ item.spec.description }}
</view>
<view v-else class="card-desc is-empty flex flex-col">
<view class="text-grey-darken-1">该照片没有记录任何信息</view>
<view class="text-size-m mt-24 text-grey-darken-1">记录一下拍照的瞬间会更精彩哟</view>
</view>
</view>
</view>
</swiper-item>
</block>
</swiper>
<view class="tabbar">
<view class="pre" @click="fnChange(false)">
<text class="icon">
<text class="iconfont icon-arrow-left"></text>
</text>
<text class="text">上一张</text>
</view>
<view class="refresh" @click="fnRefresh()">
<text class="refresh-text">点击</text>
<text class="refresh-heart iconfont icon-diagnose"></text>
<text class="refresh-text">刷新</text>
</view>
<view class="next" @click="fnChange(true)">
<text class="text">下一张</text>
<text class="icon">
<text class="iconfont icon-arrow-right"></text>
</text>
</view>
</view>
</block>
</view>
</view>
</template>
<script>
import LoveConfig from '@/config/love.config.js';
import throttle from '@/utils/throttle.js';
import tmButton from '@/tm-vuetify/components/tm-button/tm-button.vue';
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
@@ -80,298 +71,314 @@ import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
export default {
components: {
tmButton,
tmFlotbutton,
tmTranslate,
tmEmpty
},
data() {
return {
loading: 'loading',
loveConfig: LoveConfig,
queryParams: {
size: 99,
page: 0,
sort: 'takeTime',
team: LoveConfig.albumKeyName
},
result: {},
dataList: [],
cache: {
dataList: [],
total: 0
},
swiperIndex: 0,
tabbar: {
list: []
}
};
},
components: {
tmButton,
tmFlotbutton,
tmTranslate,
tmEmpty
},
data() {
return {
loading: 'loading',
queryParams: {
size: 100,
page: 1,
group: ""
},
result: {},
dataList: [],
swiperIndex: 0,
tabbar: {
list: []
}
};
},
computed: {
loveConfig() {
return this.$tm.vx.getters().getConfigs.loveConfig;
}
},
watch: {
loveConfig: {
deep: true,
immediate: true,
handler(newVal, oldVal) {
this.fnGetData()
}
}
},
onLoad() {
this.fnSetPageTitle('恋爱相册');
},
onLoad() {
this.fnSetPageTitle('恋爱相册');
},
created() {
this.fnGetData();
},
onPullDownRefresh() {
this.fnRefresh();
},
onPullDownRefresh() {
this.fnRefresh();
},
methods: {
fnRefresh() {
this.queryParams.page = 0;
this.fnGetData();
},
fnGetData() {
this.loading = 'loading';
this.$httpApi
.getPhotoListByPage(this.queryParams)
.then(res => {
if (res.status == 200) {
this.loading = 'success';
if (res.data.content.length != 0) {
const _list = res.data.content.map((item, index) => {
item['image'] = this.$utils.checkImageUrl(item.thumbnail);
item['takeTime'] = this.$tm.dayjs(item['takeTime']).format('DD/MM/YYYY');
return item;
});
this.dataList = _list;
this.swiperIndex = 0;
}
} else {
this.loading = 'error';
uni.$tm.toast('加载失败,请下拉刷新重试!');
}
})
.catch(err => {
console.error(err);
this.loading = 'error';
uni.$tm.toast('加载失败,请下拉刷新重试!');
})
.finally(() => {
setTimeout(() => {
uni.stopPullDownRefresh();
}, 200);
});
},
//
fnCacheDataList(dataList) {
if (this.queryParams.page == 0) {
this.cache.dataList = dataList;
} else {
this.cache.dataList = [...this.cache.dataList, ...dataList];
}
},
fnOnPreview(item) {
uni.previewImage({
current: item.image,
urls: this.dataList.map(x => x.image)
});
},
fnOnChange(e) {
this.swiperIndex = e.detail.current;
},
fnChange(isNext) {
throttle(() => {
if (isNext) {
if (this.swiperIndex == this.dataList.length - 1) {
this.swiperIndex = 0;
} else {
this.swiperIndex += 1;
}
} else {
if (this.swiperIndex == 0) {
this.swiperIndex = this.dataList.length - 1;
} else {
this.swiperIndex -= 1;
}
}
});
}
}
methods: {
fnRefresh() {
this.queryParams.page = 0;
this.fnGetData();
},
fnGetData() {
this.loading = 'loading';
this.queryParams.group = this.loveConfig.lovePhoto.groupName
console.log('this.loveConfig------------',this.loveConfig)
this.$httpApi.v2
.getPhotoListByGroupName(this.queryParams)
.then(res => {
console.log("相册 res", res)
this.loading = 'success';
this.dataList = res.items.map((item, index) => {
item['image'] = this.$utils.checkImageUrl(item.spec.cover);
item['takeTime'] = this.$tm.dayjs(item.metadata.creationTimestamp).format(
'DD/MM/YYYY');
return item;
});
this.swiperIndex = 0;
})
.catch(err => {
console.error(err);
this.loading = 'error';
uni.$tm.toast('加载失败,请下拉刷新重试!');
})
.finally(() => {
setTimeout(() => {
uni.stopPullDownRefresh();
}, 200);
});
},
fnOnPreview(item) {
uni.previewImage({
current: item.image,
urls: this.dataList.map(x => x.image)
});
},
fnOnChange(e) {
this.swiperIndex = e.detail.current;
},
fnChange(isNext) {
throttle(() => {
if (isNext) {
if (this.swiperIndex == this.dataList.length - 1) {
this.swiperIndex = 0;
} else {
this.swiperIndex += 1;
}
} else {
if (this.swiperIndex == 0) {
this.swiperIndex = this.dataList.length - 1;
} else {
this.swiperIndex -= 1;
}
}
});
}
}
};
</script>
<style lang="scss" scoped>
.app-page {
width: 100vw;
min-height: 100vh;
display: flex;
flex-direction: column;
box-sizing: border-box;
padding: 24rpx 0;
padding-bottom: 144rpx;
background: linear-gradient(
-135deg,
rgba(247, 149, 51, 0.1),
rgba(243, 112, 85, 0.1) 15%,
rgba(239, 78, 123, 0.1) 30%,
rgba(161, 102, 171, 0.1) 44%,
rgba(80, 115, 184, 0.1) 58%,
rgba(16, 152, 173, 0.1) 72%,
rgba(7, 179, 155, 0.1) 86%,
rgba(109, 186, 130, 0.1)
);
width: 100vw;
min-height: 100vh;
display: flex;
flex-direction: column;
box-sizing: border-box;
padding: 24rpx 0;
padding-bottom: 144rpx;
background: linear-gradient(-135deg,
rgba(247, 149, 51, 0.1),
rgba(243, 112, 85, 0.1) 15%,
rgba(239, 78, 123, 0.1) 30%,
rgba(161, 102, 171, 0.1) 44%,
rgba(80, 115, 184, 0.1) 58%,
rgba(16, 152, 173, 0.1) 72%,
rgba(7, 179, 155, 0.1) 86%,
rgba(109, 186, 130, 0.1));
}
.app-page-content {
}
.loading-wrap {
width: 100vw;
height: 60vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
padding: 36rpx;
::v-deep {
.tm-icons {
margin-right: -20rpx;
}
}
.loading-wrap {
width: 100vw;
height: 60vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
padding: 36rpx;
::v-deep {
.tm-icons {
margin-right: -20rpx;
}
}
}
.e-loading-icon {
font-size: 120rpx;
// color: #f88ca2;
color: #56bbf9;
font-size: 120rpx;
// color: #f88ca2;
color: #56bbf9;
}
.loadig-text {
margin-top: 28rpx;
font-size: 28rpx;
// color: #f88ca2;
color: #56bbf9;
margin-top: 28rpx;
font-size: 28rpx;
// color: #f88ca2;
color: #56bbf9;
}
.content-empty {
width: 100%;
height: 60vh;
width: 100%;
height: 60vh;
}
.swiper-album {
width: 100vw;
height: calc(100vh - 24rpx - 144rpx);
width: 100vw;
height: calc(100vh - 24rpx - 144rpx);
}
.swiper-album-item {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
padding: 36rpx;
/* #ifdef H5 */
padding-bottom: 110rpx;
/* #endif */
/* #ifndef H5 */
padding-bottom: 60rpx;
/* #endif */
height: 100%;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
padding: 36rpx;
/* #ifdef H5 */
padding-bottom: 110rpx;
/* #endif */
/* #ifndef H5 */
padding-bottom: 60rpx;
/* #endif */
}
.scroll-wrap {
width: 100%;
height: 100%;
box-sizing: border-box;
padding: 36rpx;
background-color: #ffffff;
border-radius: 12rpx;
box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.03);
width: 100%;
height: 100%;
box-sizing: border-box;
padding: 36rpx;
background-color: #ffffff;
border-radius: 12rpx;
box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.03);
}
.card {
display: flex;
flex-direction: column;
width: 100%;
// height: 65vh;
height: 100%;
max-height: 100%;
border-radius: 12rpx;
background-color: #ffffff;
box-sizing: border-box;
// box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.03);
overflow: hidden;
overflow-y: auto;
::v-deep {
.cache-image {
height: initial !important;
}
}
&-image {
width: 100%;
height: initial !important;
border-radius: 12rpx;
}
&-desc {
margin-top: 24rpx;
line-height: 1.6;
font-size: 30rpx;
color: rgba(26, 26, 26, 0.9);
&.is-empty {
display: flex;
align-items: center;
justify-content: center;
flex-grow: 1;
font-size: 32rpx;
}
}
display: flex;
flex-direction: column;
width: 100%;
// height: 65vh;
height: 100%;
max-height: 100%;
border-radius: 12rpx;
background-color: #ffffff;
box-sizing: border-box;
// box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.03);
overflow: hidden;
overflow-y: auto;
::v-deep {
.cache-image {
height: initial !important;
}
}
&-image {
width: 100%;
height: initial !important;
border-radius: 12rpx;
}
&-desc {
margin-top: 24rpx;
line-height: 1.6;
font-size: 30rpx;
color: rgba(26, 26, 26, 0.9);
&.is-empty {
display: flex;
align-items: center;
justify-content: center;
flex-grow: 1;
font-size: 32rpx;
}
}
}
.tabbar {
width: 90vw;
position: fixed;
left: 50%;
bottom: 40rpx;
transform: translateX(-50%);
border-radius: 25rpx;
box-sizing: border-box;
padding: 24rpx;
display: flex;
align-items: center;
justify-content: space-between;
// background-color: rgba(0, 0, 0, 0.5);
background-color: #ffffff;
color: #333;
box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.05);
.refresh {
animation: refreshAni 6s ease-in-out infinite;
color: #56bbf9;
&-heart {
font-size: 42rpx;
color: inherit;
margin: 0 6rpx;
}
&-text {
font-size: 24rpx;
}
}
.pre {
color: #56bbf9;
transition: transform 0.1s ease-in-out;
&:hover {
transform: scale(1.05);
}
.text {
padding-left: 12rpx;
}
}
.next {
color: #f88ca2;
transition: transform 0.1s ease-in-out;
&:hover {
transform: scale(1.03);
}
.text {
padding-right: 12rpx;
}
}
width: 90vw;
position: fixed;
left: 50%;
bottom: 40rpx;
transform: translateX(-50%);
border-radius: 25rpx;
box-sizing: border-box;
padding: 24rpx;
display: flex;
align-items: center;
justify-content: space-between;
// background-color: rgba(0, 0, 0, 0.5);
background-color: #ffffff;
color: #333;
box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.05);
.refresh {
animation: refreshAni 6s ease-in-out infinite;
color: #56bbf9;
&-heart {
font-size: 42rpx;
color: inherit;
margin: 0 6rpx;
}
&-text {
font-size: 24rpx;
}
}
.pre {
color: #56bbf9;
transition: transform 0.1s ease-in-out;
&:hover {
transform: scale(1.05);
}
.text {
padding-left: 12rpx;
}
}
.next {
color: #f88ca2;
transition: transform 0.1s ease-in-out;
&:hover {
transform: scale(1.03);
}
.text {
padding-right: 12rpx;
}
}
}
@keyframes refreshAni {
0% {
color: #f88ca2;
}
50% {
color: #56bbf9;
}
100% {
color: #f88ca2;
}
0% {
color: #f88ca2;
}
50% {
color: #56bbf9;
}
100% {
color: #f88ca2;
}
}
</style>
+88 -74
View File
@@ -1,92 +1,106 @@
<template>
<view class="app-page">
<view class="page-title">我们的故事</view>
<view class="html-typed" v-html="html">内容渲染</view>
<view class="app-page">
<view class="page-title">我们的故事</view>
<view class="html-typed" v-html="html">内容渲染</view>
<scroll-btn bottom="160rpx" :scrollTop.sync="scrollTop"></scroll-btn>
</view>
<scroll-btn bottom="160rpx" :scrollTop.sync="scrollTop"></scroll-btn>
</view>
</template>
<script>
import LoveConfig from '@/config/love.config.js';
import ScrollBtn from '@/components/scroll-btn/scroll-btn.vue';
export default {
components: { ScrollBtn },
data() {
return {
scrollTop: 0,
html: '',
timer: null
};
},
created() {
this.fnInit();
},
onPageScroll(e) {
this.scrollTop = e.scrollTop;
},
onBackPress() {
clearTimeout(this.timer);
},
methods: {
fnInit() {
clearTimeout(this.timer);
const _html = LoveConfig.journey;
let _index = 0;
const _typing = () => {
this.timer = setTimeout(() => {
if (_index >= _html.length) {
clearTimeout(this.timer);
} else {
this.html += _html.substring(_index, _index + 1);
_index += 1;
_typing();
}
}, 100);
};
_typing();
}
}
components: {
ScrollBtn
},
data() {
return {
scrollTop: 0,
html: '',
timer: null
};
},
computed: {
loveConfig() {
return this.$tm.vx.getters().getConfigs.loveConfig;
}
},
watch: {
loveConfig: {
deep: true,
immediate: true,
handler(newVal, oldVal) {
if (!newVal) return;
this.fnInit();
}
}
},
onPageScroll(e) {
this.scrollTop = e.scrollTop;
},
onBackPress() {
clearTimeout(this.timer);
},
methods: {
fnInit() {
clearTimeout(this.timer);
const _html = this.loveConfig.ourStory.content;
let _index = 0;
const _typing = () => {
this.timer = setTimeout(() => {
if (_index >= _html.length) {
clearTimeout(this.timer);
} else {
this.html += _html.substring(_index, _index + 1);
_index += 1;
_typing();
}
}, 100);
};
_typing();
}
}
};
</script>
<style scoped lang="scss">
.app-page {
width: 100vw;
min-height: 100vh;
box-sizing: border-box;
padding: 36rpx;
/* #ifdef APP-PLUS */
padding-top: 100rpx;
/* #endif */
/* #ifdef H5 */
padding-top: 80rpx;
/* #endif */
/* #ifdef MP-WEIXIN */
padding-top: 120rpx;
/* #endif */
background: linear-gradient(
-45deg,
rgba(247, 149, 51, 0.1),
rgba(243, 112, 85, 0.1) 15%,
rgba(239, 78, 123, 0.1) 30%,
rgba(161, 102, 171, 0.1) 44%,
rgba(80, 115, 184, 0.1) 58%,
rgba(16, 152, 173, 0.1) 72%,
rgba(7, 179, 155, 0.1) 86%,
rgba(109, 186, 130, 0.1)
);
color: rgba(26, 26, 26, 1);
width: 100vw;
min-height: 100vh;
box-sizing: border-box;
padding: 36rpx;
/* #ifdef APP-PLUS */
padding-top: 100rpx;
/* #endif */
/* #ifdef H5 */
padding-top: 80rpx;
/* #endif */
/* #ifdef MP-WEIXIN */
padding-top: 120rpx;
/* #endif */
background: linear-gradient(-45deg,
rgba(247, 149, 51, 0.1),
rgba(243, 112, 85, 0.1) 15%,
rgba(239, 78, 123, 0.1) 30%,
rgba(161, 102, 171, 0.1) 44%,
rgba(80, 115, 184, 0.1) 58%,
rgba(16, 152, 173, 0.1) 72%,
rgba(7, 179, 155, 0.1) 86%,
rgba(109, 186, 130, 0.1));
color: rgba(26, 26, 26, 1);
}
.page-title {
font-size: 42rpx;
font-weight: bold;
text-align: center;
text-shadow: 0rpx 4rpx 24rpx #bfe9ef;
font-size: 42rpx;
font-weight: bold;
text-align: center;
text-shadow: 0rpx 4rpx 24rpx #bfe9ef;
}
.html-typed {
margin-top: 52rpx;
line-height: 1.8;
font-size: 30rpx;
margin-top: 52rpx;
line-height: 1.8;
font-size: 30rpx;
}
</style>
+394 -385
View File
@@ -1,421 +1,430 @@
<template>
<view class="app-page" @touchstart="fnOnTouchstart" @touchend="fnOnTouchend" @touchcancel="fnOnTouchend">
<view class="love-card" :class="{ ani: isDoAni }">
<view class="head">
<image class="avatar" :src="loveConfig.boy.avatar" mode="scaleToFill"></image>
<view class="love-days">
<view class="tip-text">相恋</view>
<view class="number">
<text class="boy">-</text>
<text class="days">{{ calcLoveDays }}</text>
<text class="girl">-</text>
</view>
<view class="tip-text"></view>
</view>
<image class="avatar" :src="loveConfig.girl.avatar" mode="scaleToFill"></image>
</view>
<view class="foot">
<view class="text" v-if="false">
我们已经相恋
<text class="number">- {{ calcLoveDays }} -</text>
天啦
</view>
看看我们的恋爱清单都完成了哪些吧
</view>
</view>
<view v-if="list.length == 0" class="list empty">
<view class="card">
<image class="empty-image" :src="loveConfig.loveImageUrl" mode="scaleToFill"></image>
<view class="empty-text">暂时还没有恋爱清单快去制定你们的恋爱清单吧~</view>
</view>
</view>
<view v-else class="list">
<block v-for="(item, index) in list" :key="index">
<view class="card" :class="{ ani: isDoAni }" :style="{ '--delay': calcCardDelay(index) }">
<view class="head">
<view class="status">
<view v-if="!item.finish" class="text">进行中</view>
<view v-else class="text finish">已完成</view>
</view>
<view class="title">
<view class="title-name">{{ item.title }}</view>
<view class="title-desc">{{ item.desc }}</view>
</view>
<view class="actions" @click="fnOnItemOpen(item)">
<text class="icon">{{ item.open ? '-' : '+' }}</text>
</view>
</view>
<view v-if="item.open" class="body">
<view class="desc">
<view class="desc-label">开始时间</view>
<view class="desc-value">{{ item.detail.start || '暂无计划' }}</view>
</view>
<view class="desc" v-if="item.detail.desc">
<view class="desc-label">事件描述</view>
<view class="desc-value">{{ item.detail.desc }}</view>
</view>
<view class="desc">
<view class="desc-label">完成时间</view>
<view class="desc-value">{{ item.detail.end || '未开始或正在进行中...' }}</view>
</view>
<view class="desc">
<view class="desc-label">完成打卡</view>
<view class="desc-value">{{ item.detail.moment || '未开始或正在进行中...' }}</view>
</view>
<view class="desc" v-if="item.detail.other">
<view class="desc-label">爱心备注</view>
<view class="desc-value">{{ item.detail.other }}</view>
</view>
</view>
</view>
</block>
</view>
<scroll-btn :scrollTop.sync="scrollTop" @on-status="fnOnScrollStatus"></scroll-btn>
</view>
<view class="app-page" @touchstart="fnOnTouchstart" @touchend="fnOnTouchend" @touchcancel="fnOnTouchend">
<view class="love-card" :class="{ ani: isDoAni }">
<view class="head">
<image class="avatar" :src="$utils.checkAvatarUrl(loveConfig.loveInfo.boyAvatar)" mode="scaleToFill"></image>
<view class="love-days">
<view class="tip-text">相恋</view>
<view class="number">
<text class="boy">-</text>
<text class="days">{{ calcLoveDays }}</text>
<text class="girl">-</text>
</view>
<view class="tip-text"></view>
</view>
<image class="avatar" :src="$utils.checkAvatarUrl(loveConfig.loveInfo.girlAvatar)" mode="scaleToFill"></image>
</view>
<view class="foot">
<view class="text" v-if="false">
我们已经相恋
<text class="number">- {{ calcLoveDays }} -</text>
天啦
</view>
看看我们的恋爱清单都完成了哪些吧
</view>
</view>
<view v-if="list.length == 0" class="list empty">
<view class="card">
<image class="empty-image" :src="$utils.checkImageUrl(loveConfig.pageImages.heartImageUrl)" mode="scaleToFill"></image>
<view class="empty-text">暂时还没有恋爱清单快去制定你们的恋爱清单吧~</view>
</view>
</view>
<view v-else class="list">
<block v-for="(item, index) in list" :key="index">
<view class="card" :class="{ ani: isDoAni }" :style="{ '--delay': calcCardDelay(index) }">
<view class="head">
<view class="status">
<view v-if="item.status==='wait'" class="text">未开始</view>
<view v-else-if="item.status==='doing'" class="text">进行中</view>
<view v-else-if="item.status==='complete'" class="text finish">已完成</view>
</view>
<view class="title">
<view class="title-name">{{ item.title }}</view>
</view>
<view class="actions" @click="fnOnItemOpen(item)">
<text class="icon">{{ item.open ? '-' : '+' }}</text>
</view>
</view>
<view v-if="item.open && item.content" class="body">
<view v-if="item.content" class="desc">
<view class="desc-label">事件内容</view>
<view class="desc-value">{{ item.content || "-" }}</view>
</view>
<view v-if="item.status==='complete' && item.completeDate" class="desc">
<view class="desc-label">完成时间</view>
<view class="desc-value">{{ item.completeDate || '-' }}</view>
</view>
</view>
</view>
</block>
</view>
<scroll-btn :scrollTop.sync="scrollTop" @on-status="fnOnScrollStatus"></scroll-btn>
</view>
</template>
<script>
import LoveConfig from '@/config/love.config.js';
import ScrollBtn from '@/components/scroll-btn/scroll-btn.vue';
export default {
components: { ScrollBtn },
data() {
return {
isDoAni: true,
scrollTop: 0,
loveConfig: LoveConfig,
list: []
};
},
computed: {
calcLoveDays() {
const formatStartDate = this.loveConfig.loveStartDate.replace(/-/g, '/');
const start = new Date(formatStartDate),
now = new Date();
const T = now.getTime() - start.getTime();
const i = 24 * 60 * 60 * 1000;
const d = T / i;
const D = Math.floor(d);
return D;
},
calcCardDelay() {
return index => {
return Math.random() * index + 1 + 's';
};
}
},
created() {
this.fnGetList();
},
onPageScroll(e) {
this.scrollTop = e.scrollTop;
},
methods: {
fnGetList() {
if (LoveConfig.loveList.useApi && LoveConfig.loveList.api) {
uni.request({
url: LoveConfig.loveList.api,
header: {
ContentType: 'application/json'
},
method: 'GET',
dataType: 'json',
success: res => {
if (res.statusCode == 200 && res.data.status == 200) {
this.list = res.data.data.map(item => {
item['open'] = false;
return item;
});
} else {
uni.$tm.toast('数据请求失败,请检查接口!');
}
},
fail: err => {
uni.$tm.toast('数据请求失败,请检查接口!');
}
});
} else {
this.list = LoveConfig.loveList.data.map(item => {
item['open'] = false;
return item;
});
}
},
fnOnItemOpen(item) {
item.open = !item.open;
this.$forceUpdate();
},
fnOnScrollStatus(isEnd) {
this.isDoAni = isEnd;
},
fnOnTouchstart() {
this.isDoAni = false;
},
fnOnTouchend() {
this.isDoAni = true;
}
}
components: {
ScrollBtn
},
data() {
return {
isDoAni: true,
scrollTop: 0,
list: []
};
},
computed: {
loveConfig() {
return this.$tm.vx.getters().getConfigs.loveConfig;
},
calcLoveDays() {
const formatStartDate = this.loveConfig.loveDate.replace(/-/g, '/');
const start = new Date(formatStartDate),
now = new Date();
const T = now.getTime() - start.getTime();
const i = 24 * 60 * 60 * 1000;
const d = T / i;
const D = Math.floor(d);
return D;
},
calcCardDelay() {
return index => {
return Math.random() * index + 1 + 's';
};
}
},
watch: {
loveConfig: {
deep: true,
immediate: true,
handler(newVal) {
if (!newVal) return;
this.fnGetList();
}
}
},
onPageScroll(e) {
this.scrollTop = e.scrollTop;
},
methods: {
fnGetList() {
this.list = this.loveConfig.loveDaily.list.map(item => {
item['open'] = false;
return item;
});
},
fnOnItemOpen(item) {
item.open = !item.open;
this.$forceUpdate();
},
fnOnScrollStatus(isEnd) {
this.isDoAni = isEnd;
},
fnOnTouchstart() {
this.isDoAni = false;
},
fnOnTouchend() {
this.isDoAni = true;
}
}
};
</script>
<style scoped lang="scss">
.app-page {
width: 100vw;
min-height: 100vh;
box-sizing: border-box;
padding: 36rpx;
/* #ifdef H5 */
padding-top: 60rpx;
/* #endif */
/* #ifndef H5 */
padding-top: 180rpx;
/* #endif */
width: 100vw;
min-height: 100vh;
box-sizing: border-box;
padding: 36rpx;
/* #ifdef H5 */
padding-top: 60rpx;
/* #endif */
/* #ifndef H5 */
padding-top: 180rpx;
/* #endif */
background: linear-gradient(
135deg,
rgba(247, 149, 51, 0.1),
rgba(243, 112, 85, 0.1) 15%,
rgba(239, 78, 123, 0.1) 30%,
rgba(161, 102, 171, 0.1) 44%,
rgba(80, 115, 184, 0.1) 58%,
rgba(16, 152, 173, 0.1) 72%,
rgba(7, 179, 155, 0.1) 86%,
rgba(109, 186, 130, 0.1)
);
background: linear-gradient(135deg,
rgba(247, 149, 51, 0.1),
rgba(243, 112, 85, 0.1) 15%,
rgba(239, 78, 123, 0.1) 30%,
rgba(161, 102, 171, 0.1) 44%,
rgba(80, 115, 184, 0.1) 58%,
rgba(16, 152, 173, 0.1) 72%,
rgba(7, 179, 155, 0.1) 86%,
rgba(109, 186, 130, 0.1));
}
.love-card {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
box-sizing: border-box;
padding: 0 24rpx;
padding-top: 66rpx;
padding-bottom: 52rpx;
border-radius: 50rpx;
border: 4rpx solid rgba(96, 77, 68, 0.9);
border-color: #faf8eb;
background-color: rgba(255, 199, 184, 0.9);
margin-bottom: 52rpx;
box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.1);
&.ani {
animation: loveCardAni 3s ease-in-out infinite;
}
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
box-sizing: border-box;
padding: 0 24rpx;
padding-top: 66rpx;
padding-bottom: 52rpx;
border-radius: 50rpx;
border: 4rpx solid rgba(96, 77, 68, 0.9);
border-color: #faf8eb;
background-color: rgba(255, 199, 184, 0.9);
margin-bottom: 52rpx;
box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.1);
.head {
display: flex;
.avatar {
width: 150rpx;
height: 150rpx;
box-sizing: border-box;
border-radius: 50%;
border: 6rpx solid rgba(255, 255, 255, 0.7);
&.ani {
animation: loveCardAni 3s ease-in-out infinite;
}
&.boy {
border-color: #56bbf9;
}
&.girl {
border-color: #f88ca2;
}
}
.love-days {
margin: 0 12rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: 26rpx;
.tip-text {
color: #333;
}
.number {
font-size: 46rpx;
padding: 12rpx 0;
> .boy {
color: #56bbf9;
margin-right: 12rpx;
}
> .girl {
color: #f88ca2;
margin-left: 12rpx;
}
}
.days {
animation: daysAni 6s ease-in-out infinite;
font-weight: bold;
}
}
}
.foot {
display: none;
margin-top: 36rpx;
font-size: 24rpx;
}
.head {
display: flex;
.avatar {
width: 150rpx;
height: 150rpx;
box-sizing: border-box;
border-radius: 50%;
border: 6rpx solid rgba(255, 255, 255, 0.7);
&.boy {
border-color: #56bbf9;
}
&.girl {
border-color: #f88ca2;
}
}
.love-days {
margin: 0 12rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: 26rpx;
.tip-text {
color: #333;
}
.number {
font-size: 46rpx;
padding: 12rpx 0;
> .boy {
color: #56bbf9;
margin-right: 12rpx;
}
> .girl {
color: #f88ca2;
margin-left: 12rpx;
}
}
.days {
animation: daysAni 6s ease-in-out infinite;
font-weight: bold;
}
}
}
.foot {
display: none;
margin-top: 36rpx;
font-size: 24rpx;
}
}
@keyframes daysAni {
0% {
color: #f88ca2;
}
50% {
color: #56bbf9;
}
100% {
color: #f88ca2;
}
0% {
color: #f88ca2;
}
50% {
color: #56bbf9;
}
100% {
color: #f88ca2;
}
}
@keyframes loveCardAni {
0% {
transform: scale(1);
}
50% {
transform: scale(1.03);
}
100% {
transform: scale(1);
}
0% {
transform: scale(1);
}
50% {
transform: scale(1.03);
}
100% {
transform: scale(1);
}
}
.list {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
}
.empty {
height: calc(100vh - 180rpx - 280rpx - 36rpx);
.card {
height: 100%;
padding: 100rpx;
margin-bottom: 0;
text-align: center;
justify-content: center;
color: rgba(96, 77, 68, 0.9);
}
&-image {
width: 300rpx;
height: 300rpx;
}
&-text {
margin-top: 36rpx;
line-height: 50rpx;
}
height: calc(100vh - 180rpx - 280rpx - 36rpx);
.card {
height: 100%;
padding: 100rpx;
margin-bottom: 0;
text-align: center;
justify-content: center;
color: rgba(96, 77, 68, 0.9);
}
&-image {
width: 300rpx;
height: 300rpx;
}
&-text {
margin-top: 36rpx;
line-height: 50rpx;
}
}
.card {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
box-sizing: border-box;
padding: 24rpx;
border-radius: 50rpx;
border: 4rpx solid rgba(96, 77, 68, 0.9);
border-color: #fff;
// background-color: #faf8eb;
background-color: #ffffff;
margin-bottom: 36rpx;
box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.05);
animation-delay: var(--delay);
&.ani {
animation: cardAni 3s ease-in-out infinite;
}
.head {
width: 100%;
display: flex;
align-items: center;
box-sizing: border-box;
.status {
width: 100rpx;
display: flex;
.text {
width: 100rpx;
height: 100rpx;
border-radius: 50%;
background-color: #ffc6ba;
font-size: 24rpx;
line-height: 100rpx;
text-align: center;
color: #55423b;
&.finish {
background-color: #bfe9ef;
}
}
}
.title {
width: 0;
flex-grow: 1;
box-sizing: border-box;
padding-left: 30rpx;
padding-right: 24rpx;
&-name {
font-weight: bold;
font-size: 30rpx;
color: #333;
}
&-desc {
margin-top: 8rpx;
font-size: 26rpx;
color: #555;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
}
.actions {
width: 50rpx;
.icon {
display: inline-block;
width: 45rpx;
height: 45rpx;
background-color: rgba(96, 77, 68, 0.2);
border-radius: 50%;
text-align: center;
line-height: 45rpx;
font-size: 32rpx;
font-weight: bold;
}
}
}
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
box-sizing: border-box;
padding: 24rpx;
border-radius: 50rpx;
border: 4rpx solid rgba(96, 77, 68, 0.9);
border-color: #fff;
// background-color: #faf8eb;
background-color: #ffffff;
margin-bottom: 36rpx;
box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.05);
animation-delay: var(--delay);
.body {
margin-top: 24rpx;
width: 100%;
background-color: #ffffff;
// background-color: #faf8eb;
background-color: rgba(96, 77, 68, 0.05);
border-radius: 24rpx;
box-sizing: border-box;
padding: 24rpx;
padding-bottom: 12rpx;
font-size: 26rpx;
}
&.ani {
// animation: cardAni 3s ease-in-out infinite;
}
.head {
width: 100%;
display: flex;
align-items: center;
box-sizing: border-box;
.status {
width: 100rpx;
display: flex;
.text {
width: 100rpx;
height: 100rpx;
border-radius: 50%;
background-color: #ffc6ba;
font-size: 24rpx;
line-height: 100rpx;
text-align: center;
color: #55423b;
&.finish {
background-color: #bfe9ef;
}
}
}
.title {
width: 0;
flex-grow: 1;
box-sizing: border-box;
padding-left: 30rpx;
padding-right: 24rpx;
&-name {
font-weight: bold;
font-size: 30rpx;
color: #333;
}
&-desc {
margin-top: 8rpx;
font-size: 26rpx;
color: #555;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
}
.actions {
width: 50rpx;
.icon {
display: inline-block;
width: 45rpx;
height: 45rpx;
background-color: rgba(96, 77, 68, 0.2);
border-radius: 50%;
text-align: center;
line-height: 45rpx;
font-size: 32rpx;
font-weight: bold;
}
}
}
.body {
margin-top: 24rpx;
width: 100%;
background-color: #ffffff;
// background-color: #faf8eb;
background-color: rgba(96, 77, 68, 0.05);
border-radius: 24rpx;
box-sizing: border-box;
padding: 24rpx;
padding-bottom: 12rpx;
font-size: 26rpx;
}
}
@keyframes cardAni {
0% {
transform: translateY(0rpx);
}
0% {
transform: translateY(0rpx);
}
50% {
transform: translateY(-10rpx);
}
50% {
transform: translateY(-10rpx);
}
100% {
transform: translateY(0rpx);
}
100% {
transform: translateY(0rpx);
}
}
.desc {
display: flex;
margin-bottom: 12rpx;
&-label {
color: #333;
width: 140rpx;
// font-weight: bold;
}
&-value {
width: 0;
flex-grow: 1;
line-height: 1.5;
color: #333;
}
display: flex;
margin-bottom: 12rpx;
&-label {
color: #333;
width: 140rpx;
// font-weight: bold;
}
&-value {
width: 0;
flex-grow: 1;
line-height: 1.5;
color: #333;
}
}
</style>
+382 -322
View File
@@ -1,358 +1,418 @@
<template>
<view class="app-page bg-white">
<!-- 情侣信息 -->
<view class="lover-wrap" :style="[loveWrapStyle]">
<view class="lover-card">
<view class="boy">
<image class="avatar" :src="loveConfig.boy.avatar" mode="aspectFit"></image>
<view class="name">{{ loveConfig.boy.name }}</view>
</view>
<image class="like" :src="loveConfig.loveImageUrl" mode="scaleToFill"></image>
<view class="girl">
<image class="avatar" :src="loveConfig.girl.avatar" mode="aspectFit"></image>
<view class="name">{{ loveConfig.girl.name }}</view>
</view>
</view>
<image class="wave-image" :src="loveConfig.waveImageUrl" mode="scaleToFill"></image>
</view>
<!-- 恋爱记时 -->
<view class="love-time-wrap">
<view class="title">{{ loveConfig.timeTitle }}</view>
<view class="content">
<text class="text">
<text class="number">{{ loveDayCount.d }}</text>
</text>
<text class="text">
<text class="number">{{ loveDayCount.h }}</text>
小时
</text>
<text class="text">
<text class="number">{{ loveDayCount.m }}</text>
分钟
</text>
<text class="text">
<text class="number">{{ loveDayCount.s }}</text>
</text>
</view>
</view>
<!-- 功能导航 -->
<view class="list-wrap">
<block v-for="(nav, index) in loveConfig.nav" :key="index">
<view v-if="nav.use" class="list-item" @click="fnToPage(nav.key)">
<view class="left"><image class="icon" :src="nav.iconImageUrl" mode="aspectFit"></image></view>
<view class="right">
<view class="name">{{ nav.title }}</view>
<view class="desc">{{ nav.desc }}</view>
</view>
</view>
</block>
</view>
</view>
<view class="app-page bg-white">
<!-- 情侣信息 -->
<view class="lover-wrap" :style="[loveWrapStyle]">
<view class="lover-card">
<view class="boy">
<image class="avatar" :src="$utils.checkAvatarUrl(loveConfig.loveInfo.boyAvatar)" mode="aspectFit"></image>
<view class="name">{{ loveConfig.loveInfo.boyNickname }}</view>
</view>
<image class="like" :src="$utils.checkImageUrl(loveConfig.loveImageUrl)" mode="scaleToFill"></image>
<view class="girl">
<image class="avatar" :src="$utils.checkAvatarUrl(loveConfig.loveInfo.girlAvatar)" mode="aspectFit"></image>
<view class="name">{{ loveConfig.loveInfo.girlNickname }}</view>
</view>
</view>
<image class="wave-image" :src="$utils.checkImageUrl(loveConfig.pageImages.waveImageUrl)" mode="scaleToFill"></image>
</view>
<!-- 恋爱记时 -->
<view class="love-time-wrap">
<view class="title">{{ loveConfig.loveDateTitle }}</view>
<view class="content">
<text class="text">
<text class="number">{{ loveDayCount.d }}</text>
</text>
<text class="text">
<text class="number">{{ loveDayCount.h }}</text>
小时
</text>
<text class="text">
<text class="number">{{ loveDayCount.m }}</text>
分钟
</text>
<text class="text">
<text class="number">{{ loveDayCount.s }}</text>
</text>
</view>
</view>
<!-- 功能导航 -->
<view class="list-wrap">
<block v-for="(nav, index) in navList" :key="index">
<view v-if="nav.use" class="list-item" @click="fnToPage(nav.key)">
<view class="left">
<image class="icon" :src="nav.iconImageUrl" mode="aspectFit"></image>
</view>
<view class="right">
<view class="name">{{ nav.title }}</view>
<view class="desc">{{ nav.desc }}</view>
</view>
</view>
</block>
</view>
</view>
</template>
<script>
import LoveConfig from '@/config/love.config.js';
export default {
data() {
return {
loveConfig: LoveConfig,
loveDayTimer: null,
loveDayCount: {
d: 0,
h: 0,
m: 0,
s: 0
}
};
},
computed: {
loveWrapStyle() {
return {
backgroundImage: `url(${this.loveConfig.bgImageUrl})`
};
}
},
onLoad() {
this.fnSetPageTitle('恋爱日记');
this.fnInitLoveDayCount();
},
methods: {
fnInitLoveDayCount() {
clearTimeout(this.loveDayTimer);
const _countDownFn = () => {
this.loveDayTimer = setTimeout(_countDownFn, 1000);
const formatStartDate = this.loveConfig.loveStartDate.replace(/-/g, '/');
const start = new Date(formatStartDate),
now = new Date();
const T = now.getTime() - start.getTime();
const i = 24 * 60 * 60 * 1000;
const d = T / i;
const D = Math.floor(d);
const h = (d - D) * 24;
const H = Math.floor(h);
const m = (h - H) * 60;
const M = Math.floor(m);
const s = (m - M) * 60;
const S = Math.floor(s);
this.loveDayCount = {
d: D,
h: H,
m: M,
s: S
};
};
_countDownFn();
},
fnToPage(pageName) {
uni.navigateTo({
url: `/pagesA/love/${pageName}`
});
}
}
data() {
return {
loveDayTimer: null,
loveDayCount: {
d: 0,
h: 0,
m: 0,
s: 0
},
navList: []
};
},
computed: {
loveConfig() {
return this.$tm.vx.getters().getConfigs.loveConfig;
},
loveWrapStyle() {
return {
backgroundImage: `url(${this.$utils.checkImageUrl(this.loveConfig.pageImages.bgImageUrl)})`
};
}
},
watch: {
loveConfig: {
deep: true,
immediate: true,
handler(newVal, oldVal) {
if (!newVal) return;
this.initList(newVal)
this.fnInitLoveDayCount();
}
}
},
onLoad() {
this.fnSetPageTitle('恋爱日记');
},
methods: {
initList(configs) {
this.navList = [
{
key: 'journey',
use: configs.ourStory.enabled,
iconImageUrl: 'https://b.925i.cn/uni_halo_love/diandian.png',
title: '关于我们',
desc: '我们一起度过的那些经历'
},
{
key: 'album',
use: configs.lovePhoto.enabled,
iconImageUrl: 'https://b.925i.cn/uni_halo_love/diandian.png',
title: '恋爱相册',
desc: '定格了我们的那些小美好'
},
{
key: 'list',
use: configs.loveDaily.enabled,
iconImageUrl: 'https://b.925i.cn/uni_halo_love/diandian.png',
title: '恋爱清单',
desc: '你我之间的约定我们都在努力实现'
},
]
},
fnInitLoveDayCount() {
clearTimeout(this.loveDayTimer);
const _countDownFn = () => {
this.loveDayTimer = setTimeout(_countDownFn, 1000);
const formatStartDate = this.loveConfig.loveDate.replace(/-/g, '/');
const start = new Date(formatStartDate),
now = new Date();
const T = now.getTime() - start.getTime();
const i = 24 * 60 * 60 * 1000;
const d = T / i;
const D = Math.floor(d);
const h = (d - D) * 24;
const H = Math.floor(h);
const m = (h - H) * 60;
const M = Math.floor(m);
const s = (m - M) * 60;
const S = Math.floor(s);
this.loveDayCount = {
d: D,
h: H,
m: M,
s: S
};
};
_countDownFn();
},
fnToPage(pageName) {
uni.navigateTo({
url: `/pagesA/love/${pageName}`
});
}
}
};
</script>
<style scoped lang="scss">
.app-page {
width: 100vw;
min-height: 100vh;
background: linear-gradient(
-45deg,
rgba(247, 149, 51, 0.1),
rgba(243, 112, 85, 0.1) 15%,
rgba(239, 78, 123, 0.1) 30%,
rgba(161, 102, 171, 0.1) 44%,
rgba(80, 115, 184, 0.1) 58%,
rgba(16, 152, 173, 0.1) 72%,
rgba(7, 179, 155, 0.1) 86%,
rgba(109, 186, 130, 0.1)
);
width: 100vw;
min-height: 100vh;
background: linear-gradient(
-45deg,
rgba(247, 149, 51, 0.1),
rgba(243, 112, 85, 0.1) 15%,
rgba(239, 78, 123, 0.1) 30%,
rgba(161, 102, 171, 0.1) 44%,
rgba(80, 115, 184, 0.1) 58%,
rgba(16, 152, 173, 0.1) 72%,
rgba(7, 179, 155, 0.1) 86%,
rgba(109, 186, 130, 0.1)
);
}
.lover-wrap {
position: relative;
width: 100vw;
height: 50vh;
display: flex;
align-items: center;
justify-content: center;
background-size: cover;
background-repeat: no-repeat;
background-position: 50% 50%;
position: relative;
width: 100vw;
height: 50vh;
display: flex;
align-items: center;
justify-content: center;
background-size: cover;
background-repeat: no-repeat;
background-position: 50% 50%;
&::before {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
content: '';
background-color: rgba(255, 255, 255, 0.1);
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAKUlEQVQImU3IMREAIAgAwJfNkQCEsH8cijjpMf6vnXlQaIiJFx+omEBfmqIEZLe2jzcAAAAASUVORK5CYII=);
z-index: 0;
backdrop-filter: blur(4rpx);
overflow: hidden;
}
&::after {
content: '';
position: absolute;
left: 0;
bottom: -60rpx;
width: 100vw;
height: 60rpx;
background-image: linear-gradient(to bottom, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0));
}
.lover-card {
position: absolute;
left: 50%;
top: 58%;
transform: translate(-50%, -50%);
width: 90vw;
display: flex;
align-items: center;
justify-content: space-around;
border-radius: 12rpx;
z-index: 2;
.avatar {
width: 180rpx;
height: 180rpx;
border-radius: 50%;
box-sizing: border-box;
// border: 8rpx solid transparent;
// border: 8rpx solid rgba(255, 255, 255, 0.7) !important;
border: 8rpx solid rgba(255, 255, 255, 1) !important;
}
.name {
font-size: 32rpx;
font-weight: bold;
color: #ffffff;
text-align: center;
letter-spacing: 2rpx;
}
.boy {
color: #3ab8e4;
.avatar {
border-color: rgba(58, 184, 228, 0.7);
}
}
.girl {
color: #f57ab3;
.avatar {
border-color: rgba(245, 122, 179, 0.7);
}
}
&::before {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
content: '';
background-color: rgba(255, 255, 255, 0.1);
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAKUlEQVQImU3IMREAIAgAwJfNkQCEsH8cijjpMf6vnXlQaIiJFx+omEBfmqIEZLe2jzcAAAAASUVORK5CYII=);
z-index: 0;
backdrop-filter: blur(4rpx);
overflow: hidden;
}
.like {
width: 120rpx;
height: 120rpx;
animation: likeani 1s ease-in-out infinite;
}
}
.wave-image {
width: 100%;
height: 120rpx;
position: absolute;
left: 0;
bottom: 0;
mix-blend-mode: screen;
}
&::after {
content: '';
position: absolute;
left: 0;
bottom: -60rpx;
width: 100vw;
height: 60rpx;
background-image: linear-gradient(to bottom, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0));
}
.lover-card {
position: absolute;
left: 50%;
top: 58%;
transform: translate(-50%, -50%);
width: 90vw;
display: flex;
align-items: center;
justify-content: space-around;
border-radius: 12rpx;
z-index: 2;
.avatar {
width: 180rpx;
height: 180rpx;
border-radius: 50%;
box-sizing: border-box;
// border: 8rpx solid transparent;
// border: 8rpx solid rgba(255, 255, 255, 0.7) !important;
border: 8rpx solid rgba(255, 255, 255, 1) !important;
}
.name {
font-size: 32rpx;
font-weight: bold;
color: #ffffff;
text-align: center;
letter-spacing: 2rpx;
}
.boy {
color: #3ab8e4;
.avatar {
border-color: rgba(58, 184, 228, 0.7);
}
}
.girl {
color: #f57ab3;
.avatar {
border-color: rgba(245, 122, 179, 0.7);
}
}
.like {
width: 120rpx;
height: 120rpx;
animation: likeani 1s ease-in-out infinite;
}
}
.wave-image {
width: 100%;
height: 120rpx;
position: absolute;
left: 0;
bottom: 0;
mix-blend-mode: screen;
}
}
.love-time-wrap {
margin-top: 80rpx;
width: 100vw;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin-top: 80rpx;
width: 100vw;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.title {
font-size: 46rpx;
letter-spacing: 4rpx;
// background-image: linear-gradient(270deg, #ff4500, #ffa500, #ffd700, #90ee90, #00ffff, #1e90ff, #9370db, #ff69b4, #ff4500);
// -webkit-background-clip: text;
// color: #000;
color: #333;
font-size: 42rpx;
font-weight: bold;
// animation: loveTimeTitleAni 80s linear infinite;
}
.content {
margin-top: 24rpx;
display: flex;
align-items: center;
justify-content: center;
.title {
font-size: 46rpx;
letter-spacing: 4rpx;
// background-image: linear-gradient(270deg, #ff4500, #ffa500, #ffd700, #90ee90, #00ffff, #1e90ff, #9370db, #ff69b4, #ff4500);
// -webkit-background-clip: text;
// color: #000;
color: #333;
font-size: 42rpx;
font-weight: bold;
// animation: loveTimeTitleAni 80s linear infinite;
}
.text {
font-size: 28rpx;
}
.number {
margin: 0 8rpx;
font-size: 46rpx;
// color: #ff69b4;
color: #f83856;
font-weight: bold;
}
}
.content {
margin-top: 24rpx;
display: flex;
align-items: center;
justify-content: center;
.text {
font-size: 28rpx;
}
.number {
margin: 0 8rpx;
font-size: 46rpx;
// color: #ff69b4;
color: #f83856;
font-weight: bold;
}
}
}
.list-wrap {
margin-top: 75rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
padding: 0 36rpx;
margin-top: 75rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
padding: 0 36rpx;
.list-item {
width: 100%;
display: flex;
align-items: center;
justify-content: space-around;
box-sizing: border-box;
padding: 28rpx 32rpx;
background-color: #ffffff;
border-radius: 50rpx;
margin-bottom: 32rpx;
box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.03);
.list-item {
width: 100%;
display: flex;
align-items: center;
justify-content: space-around;
box-sizing: border-box;
padding: 28rpx 32rpx;
background-color: #ffffff;
border-radius: 50rpx;
margin-bottom: 32rpx;
box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.03);
&:nth-child(1) {
animation: listItemAni1 3s ease-in-out infinite;
}
&:nth-child(2) {
animation: listItemAni1 3s ease-in-out infinite;
animation-delay: 1.5s;
}
&:nth-child(3) {
animation: listItemAni1 3s ease-in-out infinite;
animation-delay: 2s;
}
.left {
width: 120rpx;
height: 120rpx;
.icon {
width: 100%;
height: 100%;
}
}
.right {
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: center;
box-sizing: border-box;
padding-left: 40rpx;
.name {
font-size: 32rpx;
font-weight: bold;
color: #333333;
}
.desc {
margin-top: 8px;
font-size: 26rpx;
color: #777777;
}
}
}
&:nth-child(1) {
animation: listItemAni1 3s ease-in-out infinite;
}
&:nth-child(2) {
animation: listItemAni1 3s ease-in-out infinite;
animation-delay: 1.5s;
}
&:nth-child(3) {
animation: listItemAni1 3s ease-in-out infinite;
animation-delay: 2s;
}
.left {
width: 120rpx;
height: 120rpx;
.icon {
width: 100%;
height: 100%;
}
}
.right {
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: center;
box-sizing: border-box;
padding-left: 40rpx;
.name {
font-size: 32rpx;
font-weight: bold;
color: #333333;
}
.desc {
margin-top: 8px;
font-size: 26rpx;
color: #777777;
}
}
}
}
@keyframes likeani {
0% {
transform: scale(1);
}
25% {
transform: scale(1.2);
}
50% {
transform: scale(1.1);
}
75% {
transform: scale(1.3);
}
100% {
transform: scale(1);
}
0% {
transform: scale(1);
}
25% {
transform: scale(1.2);
}
50% {
transform: scale(1.1);
}
75% {
transform: scale(1.3);
}
100% {
transform: scale(1);
}
}
@keyframes loveTimeTitleAni {
to {
background-position: -200rem;
}
to {
background-position: -200rem;
}
}
@keyframes listItemAni1 {
0% {
transform: translateY(0rpx);
}
0% {
transform: translateY(0rpx);
}
50% {
transform: translateY(-10rpx);
}
50% {
transform: translateY(-10rpx);
}
100% {
transform: translateY(0rpx);
}
100% {
transform: translateY(0rpx);
}
}
</style>
+316 -273
View File
@@ -1,400 +1,443 @@
<template>
<view class="app-page bg-gradient-blue-lighten-b" :style="pageStyle">
<view class="tn-satr">
<view class="sky"></view>
<view class="stars">
<view class="falling-stars">
<view class="star-fall"></view>
<view class="star-fall"></view>
<view class="star-fall"></view>
<view class="star-fall"></view>
</view>
<view class="small-stars">
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
</view>
<view class="medium-stars">
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
</view>
</view>
</view>
<view class="app-page bg-gradient-blue-lighten-b" :style="pageStyle">
<view class="tn-satr">
<view class="sky"></view>
<view class="stars">
<view class="falling-stars">
<view class="star-fall"></view>
<view class="star-fall"></view>
<view class="star-fall"></view>
<view class="star-fall"></view>
</view>
<view class="small-stars">
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
</view>
<view class="medium-stars">
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
<view class="star"></view>
</view>
</view>
</view>
<view class="user-info__container flex flex-col flex-center">
<image class="user-info__avatar" :src="startInfo.logo" mode="aspectFill"></image>
<view class="user-info__nick-name"> {{ startInfo.title }} </view>
</view>
<view class="user-info__container flex flex-col flex-center">
<image class="user-info__avatar" :src="startConfig.logo" mode="aspectFill"></image>
<view class="user-info__nick-name"> {{ startConfig.title }} </view>
</view>
<view class="text-align-center text-white" style="padding: 60vh 0 0 0;">
<view class="" style="font-size: 44rpx;" v-if="startInfo.desc1">{{ startInfo.desc1 }}</view>
<view class="mt-30 text-size-m" v-if="startInfo.desc2">{{ startInfo.desc2 }}</view>
</view>
<view class="text-align-center text-white" style="padding: 60vh 0 0 0;">
<view class="" style="font-size: 44rpx;" v-if="startConfig.desc1">{{ startConfig.desc1 }}</view>
<view class="mt-30 text-size-m" v-if="startConfig.desc2">{{ startConfig.desc2 }}</view>
</view>
<view class="" style="padding: 120rpx 200rpx;z-index: 999;position: relative;">
<view class="start-btn" @click="fnStart()">{{ startInfo.btnText || '开始体验' }}</view>
</view>
<view class="" style="padding: 120rpx 200rpx;z-index: 999;position: relative;">
<view class="start-btn" @click="fnStart()">{{ startConfig.btnText || '开始体验' }}</view>
</view>
<!-- 波浪效果 -->
<wave></wave>
</view>
<!-- 波浪效果 -->
<wave></wave>
</view>
</template>
<script>
import wave from '@/components/wave/wave.vue';
export default {
components: { wave },
computed: {
startInfo() {
return getApp().globalData.start;
},
pageStyle() {
if (this.startInfo.bg) {
const _bg = this.$utils.checkIsUrl(this.startInfo.bg) ? `url(${this.startInfo.bg})` : this.startInfo.bg;
return {
background: _bg + '!important'
};
}
return {};
}
},
methods: {
fnStart() {
uni.switchTab({
url: '/pages/tabbar/home/home',
success: () => {
uni.setStorageSync('APP_HAS_STARTED', true);
}
});
}
}
components: {
wave
},
computed: {
startConfig() {
return this.$tm.vx.getters().getConfigs.startConfig;
},
pageStyle() {
if (this.startConfig.bg) {
const _bg = this.$utils.checkIsUrl(this.startConfig.bg) ? `url(${this.startConfig.bg})` : this
.startConfig.bg;
return {
background: _bg + '!important'
};
}
return {};
}
},
methods: {
fnStart() {
uni.switchTab({
url: '/pages/tabbar/home/home',
success: () => {
uni.setStorageSync('APP_HAS_STARTED', true);
}
});
}
}
};
</script>
<style lang="scss" scoped>
.app-page {
width: 100vw;
height: 100vh;
width: 100vw;
height: 100vh;
}
.start-btn {
box-sizing: border-box;
background-color: transparent;
padding: 16rpx 50rpx;
border-radius: 50rpx;
border: 2rpx solid #ffffff;
color: #ffffff;
text-align: center;
font-size: 28rpx;
box-sizing: border-box;
background-color: transparent;
padding: 16rpx 50rpx;
border-radius: 50rpx;
border: 2rpx solid #ffffff;
color: #ffffff;
text-align: center;
font-size: 28rpx;
}
/* 用户信息 start */
.user-info {
&__container {
position: absolute;
top: 25vh;
left: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
&__container {
position: absolute;
top: 25vh;
left: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
&__avatar {
width: 200rpx;
height: 200rpx;
border: 8rpx solid rgba(255, 255, 255, 0.05);
border-radius: 50%;
overflow: hidden;
box-shadow: 0rpx 0rpx 80rpx 0rpx rgba(0, 0, 0, 0.15);
}
&__avatar {
width: 200rpx;
height: 200rpx;
border: 8rpx solid rgba(255, 255, 255, 0.05);
border-radius: 50%;
overflow: hidden;
box-shadow: 0rpx 0rpx 80rpx 0rpx rgba(0, 0, 0, 0.15);
}
&__nick-name {
color: #ffffff;
margin-top: 26rpx;
font-size: 36rpx;
font-weight: 600;
text-align: center;
}
&__nick-name {
color: #ffffff;
margin-top: 26rpx;
font-size: 36rpx;
font-weight: 600;
text-align: center;
}
}
/* 用户信息 end */
/* 流星*/
.tn-satr {
position: fixed;
width: 100%;
height: 600px;
overflow: hidden;
flex-shrink: 0;
z-index: 998;
position: fixed;
width: 100%;
height: 600px;
overflow: hidden;
flex-shrink: 0;
z-index: 998;
}
.stars {
position: absolute;
z-index: 1;
width: 100%;
height: 400px;
position: absolute;
z-index: 1;
width: 100%;
height: 400px;
}
.star {
border-radius: 50%;
background: #ffffff;
box-shadow: 0px 0px 6px 0px rgba(255, 255, 255, 0.8);
border-radius: 50%;
background: #ffffff;
box-shadow: 0px 0px 6px 0px rgba(255, 255, 255, 0.8);
}
.small-stars .star {
position: absolute;
width: 3px;
height: 3px;
position: absolute;
width: 3px;
height: 3px;
}
.small-stars .star:nth-child(2n) {
opacity: 0;
-webkit-animation: star-blink 1.2s linear infinite alternate;
animation: star-blink 1.2s linear infinite alternate;
opacity: 0;
-webkit-animation: star-blink 1.2s linear infinite alternate;
animation: star-blink 1.2s linear infinite alternate;
}
.small-stars .star:nth-child(1) {
left: 40px;
bottom: 50px;
left: 40px;
bottom: 50px;
}
.small-stars .star:nth-child(2) {
left: 200px;
bottom: 40px;
left: 200px;
bottom: 40px;
}
.small-stars .star:nth-child(3) {
left: 60px;
bottom: 120px;
left: 60px;
bottom: 120px;
}
.small-stars .star:nth-child(4) {
left: 140px;
bottom: 250px;
left: 140px;
bottom: 250px;
}
.small-stars .star:nth-child(5) {
left: 400px;
bottom: 300px;
left: 400px;
bottom: 300px;
}
.small-stars .star:nth-child(6) {
left: 170px;
bottom: 80px;
left: 170px;
bottom: 80px;
}
.small-stars .star:nth-child(7) {
left: 200px;
bottom: 360px;
-webkit-animation-delay: 0.2s;
animation-delay: 0.2s;
left: 200px;
bottom: 360px;
-webkit-animation-delay: 0.2s;
animation-delay: 0.2s;
}
.small-stars .star:nth-child(8) {
left: 250px;
bottom: 320px;
left: 250px;
bottom: 320px;
}
.small-stars .star:nth-child(9) {
left: 300px;
bottom: 340px;
left: 300px;
bottom: 340px;
}
.small-stars .star:nth-child(10) {
left: 130px;
bottom: 320px;
-webkit-animation-delay: 0.5s;
animation-delay: 0.5s;
left: 130px;
bottom: 320px;
-webkit-animation-delay: 0.5s;
animation-delay: 0.5s;
}
.small-stars .star:nth-child(11) {
left: 230px;
bottom: 330px;
-webkit-animation-delay: 7s;
animation-delay: 7s;
left: 230px;
bottom: 330px;
-webkit-animation-delay: 7s;
animation-delay: 7s;
}
.small-stars .star:nth-child(12) {
left: 300px;
bottom: 360px;
-webkit-animation-delay: 0.3s;
animation-delay: 0.3s;
left: 300px;
bottom: 360px;
-webkit-animation-delay: 0.3s;
animation-delay: 0.3s;
}
@-webkit-keyframes star-blink {
50% {
width: 3px;
height: 3px;
opacity: 1;
}
50% {
width: 3px;
height: 3px;
opacity: 1;
}
}
@keyframes star-blink {
50% {
width: 3px;
height: 3px;
opacity: 1;
}
50% {
width: 3px;
height: 3px;
opacity: 1;
}
}
.medium-stars .star {
position: absolute;
width: 3px;
height: 3px;
opacity: 0;
-webkit-animation: star-blink 1.2s ease-in infinite alternate;
animation: star-blink 1.2s ease-in infinite alternate;
position: absolute;
width: 3px;
height: 3px;
opacity: 0;
-webkit-animation: star-blink 1.2s ease-in infinite alternate;
animation: star-blink 1.2s ease-in infinite alternate;
}
.medium-stars .star:nth-child(1) {
left: 300px;
bottom: 50px;
left: 300px;
bottom: 50px;
}
.medium-stars .star:nth-child(2) {
left: 400px;
bottom: 40px;
-webkit-animation-delay: 0.4s;
animation-delay: 0.4s;
left: 400px;
bottom: 40px;
-webkit-animation-delay: 0.4s;
animation-delay: 0.4s;
}
.medium-stars .star:nth-child(3) {
left: 330px;
bottom: 300px;
-webkit-animation-delay: 0.2s;
animation-delay: 0.2s;
left: 330px;
bottom: 300px;
-webkit-animation-delay: 0.2s;
animation-delay: 0.2s;
}
.medium-stars .star:nth-child(4) {
left: 460px;
bottom: 300px;
-webkit-animation-delay: 0.9s;
animation-delay: 0.9s;
left: 460px;
bottom: 300px;
-webkit-animation-delay: 0.9s;
animation-delay: 0.9s;
}
.medium-stars .star:nth-child(5) {
left: 300px;
bottom: 150px;
-webkit-animation-delay: 1.2s;
animation-delay: 1.2s;
left: 300px;
bottom: 150px;
-webkit-animation-delay: 1.2s;
animation-delay: 1.2s;
}
.medium-stars .star:nth-child(6) {
left: 440px;
bottom: 120px;
-webkit-animation-delay: 1s;
animation-delay: 1s;
left: 440px;
bottom: 120px;
-webkit-animation-delay: 1s;
animation-delay: 1s;
}
.medium-stars .star:nth-child(7) {
left: 200px;
bottom: 140px;
-webkit-animation-delay: 0.8s;
animation-delay: 0.8s;
left: 200px;
bottom: 140px;
-webkit-animation-delay: 0.8s;
animation-delay: 0.8s;
}
.medium-stars .star:nth-child(8) {
left: 30px;
bottom: 480px;
-webkit-animation-delay: 0.3s;
animation-delay: 0.3s;
left: 30px;
bottom: 480px;
-webkit-animation-delay: 0.3s;
animation-delay: 0.3s;
}
.medium-stars .star:nth-child(9) {
left: 460px;
bottom: 400px;
-webkit-animation-delay: 1.2s;
animation-delay: 1.2s;
left: 460px;
bottom: 400px;
-webkit-animation-delay: 1.2s;
animation-delay: 1.2s;
}
.medium-stars .star:nth-child(10) {
left: 150px;
bottom: 10px;
-webkit-animation-delay: 1s;
animation-delay: 1s;
left: 150px;
bottom: 10px;
-webkit-animation-delay: 1s;
animation-delay: 1s;
}
.medium-stars .star:nth-child(11) {
left: 420px;
bottom: 450px;
-webkit-animation-delay: 1.2s;
animation-delay: 1.2s;
left: 420px;
bottom: 450px;
-webkit-animation-delay: 1.2s;
animation-delay: 1.2s;
}
.medium-stars .star:nth-child(12) {
left: 340px;
bottom: 180px;
-webkit-animation-delay: 1.1s;
animation-delay: 1.1s;
left: 340px;
bottom: 180px;
-webkit-animation-delay: 1.1s;
animation-delay: 1.1s;
}
@keyframes star-blink {
50% {
width: 4px;
height: 4px;
opacity: 1;
}
50% {
width: 4px;
height: 4px;
opacity: 1;
}
}
.star-fall {
position: relative;
border-radius: 2px;
width: 80px;
height: 2px;
overflow: hidden;
-webkit-transform: rotate(-20deg);
transform: rotate(-20deg);
position: relative;
border-radius: 2px;
width: 80px;
height: 2px;
overflow: hidden;
-webkit-transform: rotate(-20deg);
transform: rotate(-20deg);
}
.star-fall:after {
content: '';
position: absolute;
width: 50px;
height: 2px;
background: -webkit-gradient(linear, right top, left top, from(rgba(0, 0, 0, 0)), to(rgba(255, 255, 255, 0.4)));
background: linear-gradient(to left, rgba(0, 0, 0, 0) 0%, rgba(255, 255, 255, 0.4) 100%);
left: 100%;
-webkit-animation: star-fall 3.6s linear infinite;
animation: star-fall 3.6s linear infinite;
content: '';
position: absolute;
width: 50px;
height: 2px;
background: -webkit-gradient(linear, right top, left top, from(rgba(0, 0, 0, 0)), to(rgba(255, 255, 255, 0.4)));
background: linear-gradient(to left, rgba(0, 0, 0, 0) 0%, rgba(255, 255, 255, 0.4) 100%);
left: 100%;
-webkit-animation: star-fall 3.6s linear infinite;
animation: star-fall 3.6s linear infinite;
}
.star-fall:nth-child(1) {
left: 80px;
bottom: -100px;
left: 80px;
bottom: -100px;
}
.star-fall:nth-child(1):after {
-webkit-animation-delay: 2.4s;
animation-delay: 2.4s;
-webkit-animation-delay: 2.4s;
animation-delay: 2.4s;
}
.star-fall:nth-child(2) {
left: 200px;
bottom: -200px;
left: 200px;
bottom: -200px;
}
.star-fall:nth-child(2):after {
-webkit-animation-delay: 2s;
animation-delay: 2s;
-webkit-animation-delay: 2s;
animation-delay: 2s;
}
.star-fall:nth-child(3) {
left: 430px;
bottom: -50px;
left: 430px;
bottom: -50px;
}
.star-fall:nth-child(3):after {
-webkit-animation-delay: 3.6s;
animation-delay: 3.6s;
-webkit-animation-delay: 3.6s;
animation-delay: 3.6s;
}
.star-fall:nth-child(4) {
left: 400px;
bottom: 100px;
left: 400px;
bottom: 100px;
}
.star-fall:nth-child(4):after {
-webkit-animation-delay: 0.2s;
animation-delay: 0.2s;
-webkit-animation-delay: 0.2s;
animation-delay: 0.2s;
}
@-webkit-keyframes star-fall {
20% {
left: -100%;
}
100% {
left: -100%;
}
20% {
left: -100%;
}
100% {
left: -100%;
}
}
@keyframes star-fall {
20% {
left: -100%;
}
100% {
left: -100%;
}
20% {
left: -100%;
}
100% {
left: -100%;
}
}
</style>
+20 -15
View File
@@ -53,12 +53,12 @@
<view class="poup pa-36" scroll-y="auto">
<view class="info flex">
<view class="poup-logo pa-4 shadow-24">
<image :src="blogDetail.logo" class="poup-logo_img" mode="aspectFill"></image>
<image :src="blogDetail.blogLogo" class="poup-logo_img" mode="aspectFill"></image>
</view>
<view class="pl-24 info-detail">
<view class="poup-name text-size-lg text-weight-b">{{ blogDetail.name }}</view>
<view class="poup-name text-size-lg text-weight-b">{{ blogDetail.blogName }}</view>
<view class="poup-tag ml--10 text-size-n mt-10 text-grey">
{{ blogDetail.description }}
{{ blogDetail.blogDesc }}
</view>
</view>
</view>
@@ -69,12 +69,12 @@
<!-- 博客预览图 -->
<view class="mt-24">
<tm-images :round="2" :src="caclSiteThumbnail(blogDetail.url)" :width="568"
<tm-images :round="2" :src="calcSiteThumbnail(blogDetail.blogUrl)" :width="568"
mode="aspectFill"></tm-images>
</view>
</view>
<view class="poup-link flex flex-center mb-24">
<tm-button theme="light-blue" size="n" @click="fnCopyLink(blogDetail.url)">复制友链交换信息</tm-button>
<tm-button theme="light-blue" size="n" @click="fnCopyLink(blogDetail.blogUrl)">复制友链交换信息</tm-button>
<tm-button text theme="white" @click="blogDetailPoupShow = false">关闭</tm-button>
</view>
</tm-poup>
@@ -117,7 +117,6 @@ export default {
data() {
return {
blogDetailPoupShow: false,
blogDetail: this.$haloPluginsConfig.autoSubmitLink.blogDetail,
form: {
url: '', //
name: '', //
@@ -129,10 +128,16 @@ export default {
};
},
computed: {
caclSiteThumbnail(val) {
haloPluginConfigs(){
return this.$tm.vx.getters().getConfigs.pluginConfig;
},
blogDetail() {
return this.haloPluginConfigs.submitLink;
},
calcSiteThumbnail(val) {
return val => {
if (!val) return '';
if (val.charAt(val.length - 1) != '/') {
if (val.charAt(val.length - 1) !== '/') {
val = val + '/';
}
return 'https://image.thum.io/get/width/1000/crop/800/' + val;
@@ -140,17 +145,17 @@ export default {
},
calcBlogContent() {
return `
博客名称${this.blogDetail.name}
博客地址${this.blogDetail.url}
博客logo${this.blogDetail.logo}
博客简介${this.blogDetail.description}
博客名称${this.blogDetail.blogName}
博客地址${this.blogDetail.blogUrl}
博客logo${this.blogDetail.blogLogo}
博客简介${this.blogDetail.blogDesc}
`
},
calcBlogCoupon() {
return {
img: this.blogDetail.logo,
title: this.blogDetail.name,
time: this.blogDetail.description,
img: this.blogDetail.blogLogo,
title: this.blogDetail.blogName,
time: this.blogDetail.blogDesc,
btnText: '友链详情'
}
}
+142 -138
View File
@@ -1,151 +1,155 @@
<template>
<view class="app-page">
<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>
<tm-skeleton model="listAvatr"></tm-skeleton>
</view>
<block v-else>
<view class="empty" v-if="dataList.length == 0"><tm-empty icon="icon-shiliangzhinengduixiang-"
label="该标签下暂无文章"></tm-empty></view>
<block v-else>
<block v-for="(article, index) in dataList" :key="article.metadata.name">
<!-- 文章卡片 -->
<tm-translate animation-name="fadeUp" :wait="calcAniWait(index)">
<article-card :article="article" @on-click="fnToArticleDetail"></article-card></tm-translate>
</block>
<view class="load-text">{{ loadMoreText }}</view>
</block>
<view class="app-page">
<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>
<tm-skeleton model="listAvatr"></tm-skeleton>
</view>
<block v-else>
<view class="empty" v-if="dataList.length == 0">
<tm-empty icon="icon-shiliangzhinengduixiang-"
label="该标签下暂无文章"></tm-empty>
</view>
<block v-else>
<block v-for="(article, index) in dataList" :key="article.metadata.name">
<!-- 文章卡片 -->
<tm-translate animation-name="fadeUp" :wait="calcAniWait(index)">
<article-card :article="article" @on-click="fnToArticleDetail"></article-card>
</tm-translate>
</block>
<view class="load-text">{{ loadMoreText }}</view>
</block>
<tm-flotbutton @click="fnToTopPage" color="light-blue" size="m" icon="icon-angle-up"></tm-flotbutton>
</block>
</view>
<tm-flotbutton @click="fnToTopPage" color="light-blue" size="m" icon="icon-angle-up"></tm-flotbutton>
</block>
</view>
</template>
<script>
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
import ArticleCard from '@/components/article-card/article-card.vue';
export default {
components: {
tmSkeleton,
tmTranslate,
tmFlotbutton,
tmEmpty,
ArticleCard
},
data() {
return {
loading: 'loading',
queryParams: {
name: "",
size: 10,
page: 0
},
name: '',
pageTitle: '加载中...',
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
import ArticleCard from '@/components/article-card/article-card.vue';
dataList: [],
hasNext:false,
isLoadMore: false,
loadMoreText: ''
};
},
export default {
components: {
tmSkeleton,
tmTranslate,
tmFlotbutton,
tmEmpty,
ArticleCard
},
data() {
return {
loading: 'loading',
queryParams: {
name: "",
size: 10,
page: 0
},
name: '',
pageTitle: '加载中...',
onLoad(e) {
this.name = e.name;
this.queryParams.name = this.name;
this.pageTitle = e.title;
this.fnGetData();
},
onPullDownRefresh() {
this.isLoadMore = false;
this.queryParams.page = 0;
this.fnGetData();
},
onReachBottom(e) {
if (this.hasNext) {
this.queryParams.page += 1;
this.isLoadMore = true;
this.fnGetData();
} else {
uni.showToast({
icon: 'none',
title: '没有更多数据了'
});
}
},
methods: {
fnGetData() {
// uni.showLoading({
// mask: true,
// title: '...'
// });
//
if (!this.isLoadMore) {
this.loading = 'loading';
}
this.loadMoreText = '加载中...';
this.$httpApi.v2
.getPostByTagName(this.name, this.queryParams)
.then(res => {
this.fnSetPageTitle(`${this.pageTitle} (共${res.total}篇)`);
this.hasNext = res.hasNext;
if (this.isLoadMore) {
this.dataList = this.dataList.concat(res.items);
} else {
this.dataList = res.items;
}
this.loadMoreText = res.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
setTimeout(() => {
this.loading = 'success';
}, 500);
})
.catch(err => {
console.error(err);
this.loading = 'error';
this.loadMoreText = '加载失败,请下拉刷新!';
})
.finally(() => {
setTimeout(() => {
uni.hideLoading();
uni.stopPullDownRefresh();
}, 500);
});
},
//
fnToArticleDetail(article) {
uni.navigateTo({
url: '/pagesA/article-detail/article-detail?name=' + article.metadata.name,
animationType: 'slide-in-right'
});
}
}
};
dataList: [],
hasNext: false,
isLoadMore: false,
loadMoreText: ''
};
},
onLoad(e) {
this.name = e.name;
this.queryParams.name = this.name;
this.pageTitle = e.title;
this.fnGetData();
},
onPullDownRefresh() {
this.isLoadMore = false;
this.queryParams.page = 0;
this.fnGetData();
},
onReachBottom(e) {
if (this.hasNext) {
this.queryParams.page += 1;
this.isLoadMore = true;
this.fnGetData();
} else {
uni.showToast({
icon: 'none',
title: '没有更多数据了'
});
}
},
methods: {
fnGetData() {
// uni.showLoading({
// mask: true,
// title: '...'
// });
//
if (!this.isLoadMore) {
this.loading = 'loading';
}
this.loadMoreText = '加载中...';
this.$httpApi.v2
.getPostByTagName(this.name, this.queryParams)
.then(res => {
this.fnSetPageTitle(`${this.pageTitle} (共${res.total}篇)`);
this.hasNext = res.hasNext;
if (this.isLoadMore) {
this.dataList = this.dataList.concat(res.items);
} else {
this.dataList = res.items;
}
this.loadMoreText = res.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
setTimeout(() => {
this.loading = 'success';
}, 500);
})
.catch(err => {
console.error(err);
this.loading = 'error';
this.loadMoreText = '加载失败,请下拉刷新!';
})
.finally(() => {
setTimeout(() => {
uni.hideLoading();
uni.stopPullDownRefresh();
}, 500);
});
},
//
fnToArticleDetail(article) {
uni.navigateTo({
url: '/pagesA/article-detail/article-detail?name=' + article.metadata.name,
animationType: 'slide-in-right'
});
}
}
};
</script>
<style lang="scss">
.app-page {
width: 100vw;
min-height: 100vh;
display: flex;
flex-direction: column;
padding: 24rpx 0;
background-color: #fafafd;
}
.app-page {
width: 100vw;
min-height: 100vh;
display: flex;
flex-direction: column;
padding: 24rpx 0;
background-color: #fafafd;
}
.loading-wrap {
padding: 0 24rpx;
min-height: 100vh;
}
.loading-wrap {
padding: 0 24rpx;
min-height: 100vh;
}
.empty {
height: 60vh;
display: flex;
align-items: center;
justify-content: center;
}
.empty {
height: 60vh;
display: flex;
align-items: center;
justify-content: center;
}
</style>
+5 -5
View File
@@ -1,13 +1,13 @@
<template>
<view>文章标签页面</view>
<view>文章标签页面</view>
</template>
<script>
export default {
data() {
return {};
},
methods: {}
data() {
return {};
},
methods: {}
};
</script>
+15 -13
View File
@@ -1,25 +1,27 @@
<template>
<view class="app-page"><web-view :src="webUrl"></web-view></view>
<view class="app-page">
<web-view :src="webUrl"></web-view>
</view>
</template>
<script>
export default {
data() {
return {
title: '',
webUrl: ''
};
},
onLoad(e) {
const { title, url } = JSON.parse(e.query.data);
this.webUrl = url;
this.fnSetPageTitle(title);
}
data() {
return {
title: '',
webUrl: ''
};
},
onLoad(e) {
const {title, url} = JSON.parse(e.query.data);
this.webUrl = url;
this.fnSetPageTitle(title);
}
};
</script>
<style scoped>
.app-page {
width: 100vw;
width: 100vw;
}
</style>
-5
View File
@@ -9,11 +9,6 @@ const router = createRouter({
routes: [...ROUTES]
});
import {
checkHasWxLogin,
checkHasAdminLogin
} from '@/utils/auth.js'
//全局路由前置守卫
router.beforeEach((to, from, next) => {
next();
-49
View File
@@ -1,49 +0,0 @@
/**
* 功能登录用户
* 作者小莫唐尼
* 邮箱studio@925i.cn
* 时间2022年07月21日 18:41:44
* 版本v0.1.0
* 修改记录
* 修改内容
* 修改人员
* 修改时间
*/
import HaloConfig from '@/config/halo.config.js';
import {
getWxLoginInfo
} from '@/utils/auth.js'
import {
setCache,
getCache
} from '@/utils/storage.js'
export default {
state: {
// 微信登录的信息
wxLoginInfo: getWxLoginInfo(),
},
getters: {
getWxLoginInfo(state) {
return state.wxLoginInfo
},
},
mutations: {
setWxLoginInfo(state, data) {
state.wxLoginInfo = data
uni.setStorageSync('APP_WX_LOGIN_INFO', JSON.stringify(data))
},
},
actions: {
checkAndSetDefaultUser(context) {
if (!context.state.wxLoginInfo) {
context.commit('setWxLoginInfo', {
avatarUrl: HaloConfig.defaultAvatarUrl,
nickName: '匿名访客',
email: '',
url: ''
})
}
}
},
};
-32
View File
@@ -1,32 +0,0 @@
/**
* 功能博客作者信息
* 作者小莫唐尼
* 邮箱studio@925i.cn
* 时间2022年07月21日 18:41:44
* 版本v0.1.0
* 修改记录
* 修改内容
* 修改人员
* 修改时间
*/
import HaloConfig from '@/config/halo.config.js';
export default {
state: {
blogger: {},
},
getters: {
getBlogger(state) {
return state.blogger
},
},
mutations: {
setBlogger(state, data) {
state.blogger = data;
},
},
actions: {
fnGetBlogger(context) {
context.commit("setBlogger", HaloConfig.author);
},
},
};
+51
View File
@@ -0,0 +1,51 @@
/**
* 功能应用配置
* 作者小莫唐尼
* 邮箱studio@925i.cn
* 时间2024年06月22日 12:00:44
* 版本v0.1.0
*/
import {DefaultAppConfigs, getAppConfigs, setAppConfigs} from '@/config/index.js'
import v2Config from '@/api/v2/all.config.js'
export default {
namespaced: true,
state: {
configs: getAppConfigs(),
},
getters: {
getConfigs(state) {
if (state.configs) return state.configs;
return getAppConfigs()
},
},
mutations: {
setConfigs(state, data) {
state.configs = data;
setAppConfigs(data)
},
},
actions: {
fetchConfigs({commit, dispatch}) {
return new Promise(async (resolve, reject) => {
try {
const res = await v2Config.getAppConfigs()
if (res) {
commit('setConfigs', res)
resolve(res)
} else {
dispatch("setDefaultAppSettings");
reject()
}
} catch (e) {
dispatch("setDefaultAppSettings");
reject()
}
})
},
// 设置默认的数据
setDefaultAppSettings({commit}) {
commit('setConfigs', JSON.parse(JSON.stringify(DefaultAppConfigs)))
},
}
};
-51
View File
@@ -1,51 +0,0 @@
/**
* 功能登录用户
* 作者小莫唐尼
* 邮箱studio@925i.cn
* 时间2022年07月21日 18:41:44
* 版本v0.1.0
* 修改记录
* 修改内容
* 修改人员
* 修改时间
*/
import HaloConfig from '@/config/halo.config.js';
import {
getWxLoginInfo
} from '@/utils/auth.js'
import {
setCache,
getCache
} from '@/utils/storage.js'
export default {
state: {
// 微信登录的信息
wxLoginInfo: getWxLoginInfo(),
},
getters: {
getWxLoginInfo(state) {
return state.wxLoginInfo
},
},
mutations: {
setWxLoginInfo(state, data) {
state.wxLoginInfo = data
uni.setStorageSync('APP_WX_LOGIN_INFO', JSON.stringify(data))
},
},
actions: {
checkAndSetDefaultUser(context) {
if (!context.state.wxLoginInfo) {
context.commit('setWxLoginInfo', {
avatarUrl: HaloConfig.defaultAvatarUrl,
nickName: '匿名访客',
email: '',
url: ''
})
}
},
},
};
+1 -1
View File
@@ -7,7 +7,7 @@ export const Platform = {
* 检查当前环境是什么环境
*/
export const checkPlatform = (name) => {
return uni.getSystemInfoSync().platform == name;
return uni.getSystemInfoSync().platform === name;
}
// 默认的应用设置
+144 -147
View File
@@ -10,160 +10,157 @@
* 修改时间
*/
import HaloConfig from '@/config/halo.config.js';
import HaloTokenConfig from '@/config/token.config.js'
import {
logTypes,
logUtils
} from '@/utils/halo.logs.js'
import {getAppConfigs} from '@/config/index.js'
const utils = {
/**
* 检查是否为http/https链接
*/
checkIsUrl: function(s) {
var reg = /^(http(s)?:\/\/)/i;
return reg.test(s)
},
/**
* 检查是否为http/https链接
*/
checkIsUrl: function (s) {
var reg = /^(http(s)?:\/\/)/i;
return reg.test(s)
},
// 检查链接
checkUrl: function(url) {
if (!url) return '';
if (!this.checkIsUrl(url)) return HaloTokenConfig.BASE_API + url;
return url
},
// 检查链接
checkUrl: function (url) {
if (!url) return '';
if (!this.checkIsUrl(url)) return HaloTokenConfig.BASE_API + url;
return url
},
// 检查封面图
checkThumbnailUrl: function(thumbnail, mustRealUrl = false) {
if (!thumbnail && mustRealUrl) {
return HaloConfig.defaultStaticThumbnailUrl
}
let _url = HaloConfig.defaultThumbnailUrl
if (_url) {
if (_url.indexOf('?') == -1) {
_url += `?next-v=${new Date().getTime()}`
} else {
_url += `&next-v=${new Date().getTime()}`
}
}
if (!thumbnail) return _url;
if (!this.checkIsUrl(thumbnail)) return HaloTokenConfig.BASE_API + thumbnail;
return thumbnail
},
// 检查封面图
checkThumbnailUrl: function (thumbnail, mustRealUrl = false) {
if (!thumbnail && mustRealUrl) {
return this.checkUrl(getAppConfigs().imagesConfig.defaultStaticThumbnailUrl);
}
let _url = this.checkUrl(getAppConfigs().imagesConfig.defaultThumbnailUrl);
if (_url) {
if (_url.indexOf('?') === -1) {
_url += `?next-v=${new Date().getTime()}`
} else {
_url += `&next-v=${new Date().getTime()}`
}
}
if (!thumbnail) return _url;
if (!this.checkIsUrl(thumbnail)) return HaloTokenConfig.BASE_API + thumbnail;
return thumbnail
},
// 检查图片
checkImageUrl: function(image) {
let _url = HaloConfig.defaultImageUrl
if (_url) {
if (_url.indexOf('?') == -1) {
_url += `?next-v=${new Date().getTime()}`
} else {
_url += `&next-v=${new Date().getTime()}`
}
}
if (!image) return _url;
if (!this.checkIsUrl(image)) return HaloTokenConfig.BASE_API + image;
return image
},
// 检查图片
checkImageUrl: function (image) {
let _url
this.checkUrl(getAppConfigs().imagesConfig.defaultImageUrl);
if (_url) {
if (_url.indexOf('?') === -1) {
_url += `?next-v=${new Date().getTime()}`
} else {
_url += `&next-v=${new Date().getTime()}`
}
}
if (!image) return _url;
if (!this.checkIsUrl(image)) return HaloTokenConfig.BASE_API + image;
return image
},
// 检查头像
checkAvatarUrl: function(avatar, isAdmin = false) {
if (isAdmin) return HaloConfig.author.avatar;
if (!avatar) {
let _url = HaloConfig.defaultAvatarUrl
if (_url) {
if (_url.indexOf('?') == -1) {
_url += `?next-v=${new Date().getTime()}`
} else {
_url += `&next-v=${new Date().getTime()}`
}
}
return _url;
}
if (!this.checkIsUrl(avatar)) return HaloTokenConfig.BASE_API + avatar;
return avatar
},
// 检查头像
checkAvatarUrl: function (avatar) {
if (!avatar) {
let _url = this.checkUrl(getAppConfigs().imagesConfig.defaultAvatarUrl);
if (_url) {
if (_url.indexOf('?') === -1) {
_url += `?next-v=${new Date().getTime()}`
} else {
_url += `&next-v=${new Date().getTime()}`
}
}
return _url;
}
if (!this.checkIsUrl(avatar)) return HaloTokenConfig.BASE_API + avatar;
return avatar
},
// 检查文件类型
fnCheckIsFileType(type, attachment) {
if (!attachment) return false;
if (!attachment.mediaType) return false;
if (type == 'video') return attachment.mediaType.indexOf('video/') != -1;
else if (type == 'image') return attachment.mediaType.indexOf('image/') != -1;
else return false;
},
groupData: function(arr, fun) {
const groups = {}
arr.forEach((el) => {
const group = fun(el)
groups[group] = groups[group] || []
groups[group].push(el)
})
return Object.keys(groups).map((group) => {
// 更改data的数据结构 可以改变新数据的结构 data即为newData的数组中每个数据的结构
let data = {
groupName: group,
data: groups[group]
}
return data
})
},
/**
* 数据分组
* @param {Object} oldData 数据源
* @param {Object} prop 分组属性
*/
arrayGroupBy: function(oldData, prop) {
const newData = this.groupData(oldData, (item) => {
return item[prop]
})
return newData
},
/**
* 深克隆
* @param {Object} obj 数据源
*/
deepClone(obj) {
var objClone = Array.isArray(obj) ? [] : {};
if (obj && typeof obj === "object") {
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
if (obj[key] && typeof obj[key] === "object") {
objClone[key] = this.deepClone(obj[key]);
} else {
objClone[key] = obj[key];
}
}
}
}
return objClone;
},
/**
* 复制内容到剪贴板
* @param {Object} obj 数据源
*/
copyText(content, tips = '复制成功') {
uni.setClipboardData({
data: content,
showToast: false,
success: () => {
if (tips) {
uni.showToast({
icon: 'none',
title: tips
})
}
}
})
},
previewImage(list) {
list = list.map(item => {
return this.checkUrl(item)
})
uni.previewImage({
urls: list,
loop: true
})
}
// 检查文件类型
fnCheckIsFileType(type, attachment) {
if (!attachment) return false;
if (!attachment.mediaType) return false;
if (type === 'video') return attachment.mediaType.indexOf('video/') !== -1;
else if (type === 'image') return attachment.mediaType.indexOf('image/') !== -1;
else return false;
},
groupData: function (arr, fun) {
const groups = {}
arr.forEach((el) => {
const group = fun(el)
groups[group] = groups[group] || []
groups[group].push(el)
})
return Object.keys(groups).map((group) => {
// 更改data的数据结构 可以改变新数据的结构 data即为newData的数组中每个数据的结构
let data = {
groupName: group,
data: groups[group]
}
return data
})
},
/**
* 数据分组
* @param {Object} oldData 数据源
* @param {Object} prop 分组属性
*/
arrayGroupBy: function (oldData, prop) {
const newData = this.groupData(oldData, (item) => {
return item[prop]
})
return newData
},
/**
* 深克隆
* @param {Object} obj 数据源
*/
deepClone(obj) {
var objClone = Array.isArray(obj) ? [] : {};
if (obj && typeof obj === "object") {
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
if (obj[key] && typeof obj[key] === "object") {
objClone[key] = this.deepClone(obj[key]);
} else {
objClone[key] = obj[key];
}
}
}
}
return objClone;
},
/**
* 复制内容到剪贴板
* @param {Object} obj 数据源
*/
copyText(content, tips = '复制成功') {
uni.setClipboardData({
data: content,
showToast: false,
success: () => {
if (tips) {
uni.showToast({
icon: 'none',
title: tips
})
}
}
})
},
previewImage(list) {
list = list.map(item => {
return this.checkUrl(item)
})
uni.previewImage({
urls: list,
loop: true
})
}
};