1
0
zrcadlo https://github.com/ialley-workshop-open/uni-halo.git synchronizováno 2026-06-10 11:59:28 +08:00

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

Tento commit je obsažen v:
小莫唐尼
2024-06-24 18:59:05 +08:00
rodič 959acab9c7
revize e17edade28
54 změnil soubory, kde provedl 5299 přidání a 5653 odebrání
+1 -2
Zobrazit soubor
@@ -3,8 +3,7 @@ unpackage/
package-lock.json package-lock.json
.idea .idea
config/halo.config.js config/halo.config.js
config/ad.config.js
config/love.config.js config/love.config.js
config/token.config.js config/token.config.js
config/plugins.config.js config/plugins.config.js
+7 -17
Zobrazit soubor
@@ -1,7 +1,5 @@
<script> <script>
import HaloTokenConfig from '@/config/token.config.js'; 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 升级中心) // app升级检测(搭配:https://ext.dcloud.net.cn/plugin?id=4470 升级中心)
import CheckAppUpdate from '@/uni_modules/uni-upgrade-center-app/utils/check-update'; import CheckAppUpdate from '@/uni_modules/uni-upgrade-center-app/utils/check-update';
@@ -10,9 +8,7 @@
} from '@/utils/update.js'; } from '@/utils/update.js';
export default { export default {
globalData: { globalData: {
baseApiUrl: HaloTokenConfig.BASE_API, baseApiUrl: HaloTokenConfig.BASE_API
...HaloConfig,
haloAdConfig: HaloAdConfig
}, },
onLaunch: function() { onLaunch: function() {
console.log('App Launch'); console.log('App Launch');
@@ -23,20 +19,14 @@
// #ifdef MP-WEIXIN // #ifdef MP-WEIXIN
CheckWxUpdate(); CheckWxUpdate();
uni.$tm.vx.commit('setWxShare', HaloConfig.wxShareConfig);
// #endif // #endif
// 监听中间按钮(暂时没有使用) uni.$tm.vx.actions('config/fetchConfigs').then((res) => {
uni.onTabBarMidButtonTap(() => { console.log('正常:', res)
console.log('点击中间按钮'); // #ifdef MP-WEIXIN
}); uni.$tm.vx.commit('setWxShare', res.shareConfig);
// #endif
// 初始化博主信息 })
uni.$tm.vx.actions('blogger/fnGetBlogger');
// 临时:检查是否有用户,没有的话添加一个默认的用户
uni.$tm.vx.actions('user/checkAndSetDefaultUser');
// 启动检查app的配置是否已经就绪,若未就绪则设置默认的 // 启动检查app的配置是否已经就绪,若未就绪则设置默认的
uni.$tm.vx.actions('setting/checkAndSetDefaultAppSettings'); uni.$tm.vx.actions('setting/checkAndSetDefaultAppSettings');
}, },
+5 -5
Zobrazit soubor
@@ -10,19 +10,19 @@
* 修改时间: * 修改时间:
*/ */
import HttpHandler from '@/common/http/request.js'
// 2.0接口 // 2.0接口
import v2 from './v2/all.api.js' import v2 from './v2/all.api.js'
import v2Config from './v2/all.config.js'
const ApiManager = { const ApiManager = {
v2 v2,
v2Config,
}; };
const install = (Vue) => { const install = (Vue) => {
Vue.prototype.$httpApi = ApiManager Vue.prototype.$httpApi = ApiManager
} }
export default { export default {
install install
} }
+165 -164
Zobrazit soubor
@@ -3,191 +3,192 @@
*/ */
import HaloTokenConfig from '@/config/token.config.js' import HaloTokenConfig from '@/config/token.config.js'
import HttpHandler from '@/common/http/request.js' import HttpHandler from '@/common/http/request.js'
import { import {
getCache getAppConfigs
} from '@/utils/storage.js' } from '@/config/index.js'
import HaloPluginsConfig from '@/config/plugins.config.js'
export default { export default {
/** /**
* 获取文章列表 * 获取文章列表
* @param {Object} params 参数 * @param {Object} params 参数
*/ */
getPostList: (params) => { getPostList: (params) => {
return HttpHandler.Get(`/apis/api.content.halo.run/v1alpha1/posts`, params) return HttpHandler.Get(`/apis/api.content.halo.run/v1alpha1/posts`, params)
}, },
/** /**
* 根据名称获取文章 * 根据名称获取文章
* @param {String} name 分类名称 * @param {String} name 分类名称
*/ */
getPostByName: (name) => { getPostByName: (name) => {
return HttpHandler.Get(`/apis/api.content.halo.run/v1alpha1/posts/${name}`, {}, { return HttpHandler.Get(`/apis/api.content.halo.run/v1alpha1/posts/${name}`, {}, {
header: { header: {
'Wechat-Session-Id': uni.getStorageSync('openid'), 'Wechat-Session-Id': uni.getStorageSync('openid'),
} }
}) })
}, },
/** /**
* 搜索文章 * 搜索文章
* @param {Object} params 数据 * @param {Object} params 数据
*/ */
getPostListByKeyword: (params) => { getPostListByKeyword: (params) => {
return HttpHandler.Get(`/apis/api.halo.run/v1alpha1/indices/post`, params) return HttpHandler.Get(`/apis/api.halo.run/v1alpha1/indices/post`, params)
}, },
/** /**
* 查询分类列表 * 查询分类列表
* @param {Object} params 查询参数 * @param {Object} params 查询参数
*/ */
getCategoryList: (params) => { getCategoryList: (params) => {
return HttpHandler.Get('/apis/api.content.halo.run/v1alpha1/categories', params) return HttpHandler.Get('/apis/api.content.halo.run/v1alpha1/categories', params)
}, },
/** /**
* 查询分类下的文章 * 查询分类下的文章
* @param {String} name 分类名称 * @param {String} name 分类名称
* @param {Object} params 查询参数 * @param {Object} params 查询参数
*/ */
getCategoryPostList: (name, params) => { getCategoryPostList: (name, params) => {
return HttpHandler.Get(`/apis/api.content.halo.run/v1alpha1/categories/${name}/posts`, params) return HttpHandler.Get(`/apis/api.content.halo.run/v1alpha1/categories/${name}/posts`, params)
}, },
/** /**
* 获取评论列表接口(列表数据) * 获取评论列表接口(列表数据)
* @param {Object} params 查询参数 * @param {Object} params 查询参数
*/ */
getPostCommentList: (params) => { getPostCommentList: (params) => {
return HttpHandler.Get(`/apis/api.halo.run/v1alpha1/comments`, params) return HttpHandler.Get(`/apis/api.halo.run/v1alpha1/comments`, params)
}, },
/** /**
* 获取回复列表 * 获取回复列表
* @param {String} commentName 名称 * @param {String} commentName 名称
* @param {Object} params 查询参数 * @param {Object} params 查询参数
*/ */
getPostCommentReplyList: (commentName, params) => { getPostCommentReplyList: (commentName, params) => {
return HttpHandler.Get(`/apis/api.halo.run/v1alpha1/comments/${commentName}/reply`, params) return HttpHandler.Get(`/apis/api.halo.run/v1alpha1/comments/${commentName}/reply`, params)
}, },
// 提交评论 // 提交评论
addPostComment: (data) => { addPostComment: (data) => {
return HttpHandler.Post(`/apis/api.halo.run/v1alpha1/comments`, data) return HttpHandler.Post(`/apis/api.halo.run/v1alpha1/comments`, data)
}, },
// 提交回复 // 提交回复
addPostCommentReply: (commentName, data) => { addPostCommentReply: (commentName, data) => {
return HttpHandler.Post(`/apis/api.halo.run/v1alpha1/comments/${commentName}/replay`, data) return HttpHandler.Post(`/apis/api.halo.run/v1alpha1/comments/${commentName}/replay`, data)
}, },
/** /**
* 获取标签列表 * 获取标签列表
* @param {Object} params 查询参数 * @param {Object} params 查询参数
*/ */
getTagList: (params) => { getTagList: (params) => {
return HttpHandler.Get(`/apis/api.content.halo.run/v1alpha1/tags`, params) return HttpHandler.Get(`/apis/api.content.halo.run/v1alpha1/tags`, params)
}, },
/** /**
* 根据标签获取文章列表 * 根据标签获取文章列表
* @param {String} tagName 参数 * @param {String} tagName 参数
* @param {Object} params 查询参数 * @param {Object} params 查询参数
*/ */
getPostByTagName: (tagName, params) => { getPostByTagName: (tagName, params) => {
return HttpHandler.Get(`/apis/api.content.halo.run/v1alpha1/tags/${tagName}/posts`, params) return HttpHandler.Get(`/apis/api.content.halo.run/v1alpha1/tags/${tagName}/posts`, params)
}, },
/** /**
* 获取瞬间列表 * 获取瞬间列表
*/ */
getMomentList: (params) => { getMomentList: (params) => {
return HttpHandler.Get(`/apis/moment.halo.run/v1alpha1/moments`, params, { return HttpHandler.Get(`/apis/moment.halo.run/v1alpha1/moments`, params, {
custom: { custom: {
systemToken: HaloTokenConfig.systemToken systemToken: HaloTokenConfig.systemToken
} }
}) })
}, },
/** /**
* 查询站点统计信息 * 查询站点统计信息
*/ */
getBlogStatistics: () => { getBlogStatistics: () => {
return HttpHandler.Get(`/apis/api.halo.run/v1alpha1/stats/-`, {}) return HttpHandler.Get(`/apis/api.halo.run/v1alpha1/stats/-`, {})
}, },
/** /**
* 获取相册分组 * 获取相册分组
*/ */
getPhotoGroupList: (params) => { getPhotoGroupList: (params) => {
return HttpHandler.Get(`/apis/core.halo.run/v1alpha1/photogroups`, params, { return HttpHandler.Get(`/apis/core.halo.run/v1alpha1/photogroups`, params, {
custom: { custom: {
systemToken: HaloTokenConfig.systemToken systemToken: HaloTokenConfig.systemToken
} }
}) })
}, },
/** /**
* 根据分组获取相册 * 根据分组获取相册
*/ */
getPhotoListByGroupName: (params) => { getPhotoListByGroupName: (params) => {
return HttpHandler.Get(`/apis/console.api.photo.halo.run/v1alpha1/photos`, params, { return HttpHandler.Get(`/apis/console.api.photo.halo.run/v1alpha1/photos`, params, {
custom: { custom: {
systemToken: HaloTokenConfig.systemToken systemToken: HaloTokenConfig.systemToken
} }
}) })
}, },
/** /**
* 获取友链 * 获取友链
*/ */
getFriendLinkList: (params) => { getFriendLinkList: (params) => {
return HttpHandler.Get(`/apis/api.plugin.halo.run/v1alpha1/plugins/PluginLinks/links`, params) return HttpHandler.Get(`/apis/api.plugin.halo.run/v1alpha1/plugins/PluginLinks/links`, params)
}, },
/** /**
* 校验文章访问密码 * 校验文章访问密码
*/ */
checkPostVerifyCode: (verifyCode, postId) => { checkPostVerifyCode: (verifyCode, postId) => {
return HttpHandler.Get(`/apis/tools.muyin.site/v1alpha1/verificationCode/check?code=${verifyCode}`, null, { return HttpHandler.Get(`/apis/tools.muyin.site/v1alpha1/verificationCode/check?code=${verifyCode}`, null, {
header: { header: {
'Authorization': HaloPluginsConfig.toolsPlugin.Authorization, 'Authorization': getAppConfigs().pluginConfig.toolsPlugin?.Authorization,
'Wechat-Session-Id': uni.getStorageSync('openid'), 'Wechat-Session-Id': uni.getStorageSync('openid'),
'Post-Id': postId 'Post-Id': postId
} }
}) })
}, },
/** /**
* 校验文章访问密码 * 校验文章访问密码
*/ */
checkPostPasswordAccess: (password, postId) => { checkPostPasswordAccess: (password, postId) => {
return HttpHandler.Get(`/apis/tools.muyin.site/v1alpha1/visitPassword/checkPost?password=${password}`, null, { return HttpHandler.Get(`/apis/tools.muyin.site/v1alpha1/visitPassword/checkPost?password=${password}`,
header: { null, {
'Authorization': HaloPluginsConfig.toolsPlugin.Authorization, header: {
'Wechat-Session-Id': uni.getStorageSync('openid'), 'Authorization': getAppConfigs().pluginConfig.toolsPlugin?.Authorization,
'Post-Id': postId 'Wechat-Session-Id': uni.getStorageSync('openid'),
} 'Post-Id': postId
}) }
}, })
},
/** /**
* 获取文章验证码 * 获取文章验证码
*/ */
getPostVerifyCode: () => { getPostVerifyCode: () => {
return HttpHandler.Get(`/apis/tools.muyin.site/v1alpha1/verificationCode/create`, null, { return HttpHandler.Get(`/apis/tools.muyin.site/v1alpha1/verificationCode/create`, null, {
header: { header: {
'Authorization': HaloPluginsConfig.toolsPlugin.Authorization 'Authorization': getAppConfigs().pluginConfig.toolsPlugin?.Authorization,
} }
}) })
}, },
/** /**
* 提交友情链接 * 提交友情链接
*/ */
submitLink(form) { submitLink(form) {
return HttpHandler.Post(`/apis/linksSubmit.muyin.site/v1alpha1/submit`, form, null) return HttpHandler.Post(`/apis/linksSubmit.muyin.site/v1alpha1/submit`, form, null)
} }
} }
+10
Zobrazit soubor
@@ -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`, {})
},
}
+3 -4
Zobrazit soubor
@@ -1,5 +1,5 @@
/** /**
* 功能:请求工具 * 功能:请求工具
* 作者:小莫唐尼 * 作者:小莫唐尼
* 邮箱:studio@925i.cn * 邮箱:studio@925i.cn
* 时间:2022年07月21日 18:58:03 * 时间:2022年07月21日 18:58:03
@@ -10,7 +10,6 @@
* 修改时间: * 修改时间:
*/ */
import HaloConfig from '@/config/halo.config.js'
import HaloTokenConfig from '@/config/token.config.js' import HaloTokenConfig from '@/config/token.config.js'
import { import {
setInterceptors setInterceptors
@@ -25,13 +24,13 @@ http.setConfig((config) => {
config.baseURL = HaloTokenConfig.BASE_API; config.baseURL = HaloTokenConfig.BASE_API;
config.header = { config.header = {
...config.header, ...config.header,
ContentType: 'application/json', ContentType: 'application/json',
dataType: 'json' dataType: 'json'
} }
return config return config
}) })
setInterceptors(http) setInterceptors(http)
export { export {
+6 -4
Zobrazit soubor
@@ -2,7 +2,9 @@
* markdown配置 * markdown配置
*/ */
import HaloConfig from '@/config/halo.config.js' import {
getAppConfigs
} from '@/config/index.js'
import HaloTokenConfig from '@/config/token.config.js' import HaloTokenConfig from '@/config/token.config.js'
export default { export default {
domain: HaloTokenConfig.BASE_API, 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;', 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, loadingGif: getAppConfigs().imagesConfig.loadingGifUrl,
emptyGif: HaloConfig.loadingEmptyUrl, emptyGif: getAppConfigs().imagesConfig.loadingEmptyUrl,
} }
+82 -78
Zobrazit soubor
@@ -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 { export default {
install(Vue) { install(Vue) {
Vue.mixin({ Vue.mixin({
data() { data() {
return { return {
author: HaloConfig.author, _isWechat: true,
_isWechat: true, _aniWaitIndex: 0
haloConfig: HaloConfig, };
haloAdConfig: HaloAdConfig, },
haloPluginsConfig: HaloPluginsConfig, computed: {
_aniWaitIndex: 0, // 动画索引 haloConfig() {
}; return this.$tm.vx.getters().getConfigs;
}, },
computed: { haloPluginsConfig() {
// 获取全局应用设置 return this.$tm.vx.getters().getConfigs?.pluginConfig;
globalAppSettings() { },
return uni.$tm.vx.getters().getSettings; // 获取全局应用设置
}, globalAppSettings() {
// 计算动画索引 return uni.$tm.vx.getters().getSettings;
calcAniWait() { },
return (index) => { // 计算动画索引
if ((index + 1) % 10 == 0) { calcAniWait() {
this._aniWaitIndex = 1; return (index) => {
} else { if ((index + 1) % 10 === 0) {
this._aniWaitIndex += 1; this._aniWaitIndex = 1;
} } else {
console.log('this._aniWaitIndex', this._aniWaitIndex); this._aniWaitIndex += 1;
return this._aniWaitIndex * 50 }
} return this._aniWaitIndex * 50
} }
}, }
onLoad() { },
this.fnResetSetAniWaitIndex() watch: {
}, haloConfig: {
created() { deep: true,
// #ifdef MP-WEIXIN immediate: true,
this._isWechat = true; handler(newVal) {
uni.$tm.vx.commit('setWxShare', HaloConfig.wxShareConfig); if (!newVal) return;
// #endif // #ifdef MP-WEIXIN
// #ifndef MP-WEIXIN uni.$tm.vx.commit('setWxShare', newVal.shareConfig);
this._isWechat = false; // #endif
// #endif }
}, }
onShow() { },
this.fnResetSetAniWaitIndex() onLoad() {
}, this.fnResetSetAniWaitIndex()
methods: { },
/** created() {
* 设置页面标题 // #ifdef MP-WEIXIN
* @param {Object} title 标题 this._isWechat = true;
*/ // #endif
fnSetPageTitle(title) { // #ifndef MP-WEIXIN
uni.setNavigationBarTitle({ this._isWechat = false;
title: title || HaloConfig.title // #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
fnToTopPage(duration = 500) { uni.pageScrollTo({
duration = isNaN(duration) ? 500 : duration scrollTop: 0,
uni.pageScrollTo({ duration: duration,
scrollTop: 0, fail: (err) => {
duration: duration, console.log('err', err);
fail: (err) => { },
console.log('err', err); });
}, },
}); // 初始化动画索引值(需要在每个页面调用)
}, fnResetSetAniWaitIndex() {
// 初始化动画索引值(需要在每个页面调用) this._aniWaitIndex = 0
fnResetSetAniWaitIndex() { }
this._aniWaitIndex = 0 },
} });
}, },
});
},
}; };
+8 -9
Zobrazit soubor
@@ -1,16 +1,15 @@
// 微信分享配置 // 微信分享配置
import haloConfig from '@/config/halo.config.js'
import HaloTokenConfig from '@/config/token.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 = { export const haloWxShareMixin = {
data() { computed: {
return { haloWxShareData() {
haloWxShareData: { const configs = this.$tm.vx.getters().getConfigs;
...haloConfig.wxShareConfig return configs.shareConfig || {}
},
} }
}, },
//#ifdef MP-WEIXIN //#ifdef MP-WEIXIN
onShareAppMessage(res) { onShareAppMessage(res) {
return { return {
@@ -64,4 +63,4 @@ export const haloWxShareMixin = {
this.haloWxShareData = _config; this.haloWxShareData = _config;
} }
} }
} }
+7 -3
Zobrazit soubor
@@ -10,7 +10,8 @@
<text class="img-load-text">{{ loadErrText }}</text> --> <text class="img-load-text">{{ loadErrText }}</text> -->
<image class="img-error-img" :src="loadingErrorImageSrc" mode="scaleToFill"></image> <image class="img-error-img" :src="loadingErrorImageSrc" mode="scaleToFill"></image>
</view> </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> </view>
</template> </template>
@@ -91,11 +92,14 @@
}; };
}, },
computed: { computed: {
imagesConfig() {
return this.$tm.vx.getters().getConfigs.imagesConfig
},
loadingImgSrc() { loadingImgSrc() {
return getApp().globalData.loadingGifUrl; return this.imagesConfig.loadingGifUrl;
}, },
loadingErrorImageSrc() { loadingErrorImageSrc() {
return getApp().globalData.loadingErrUrl return this.imagesConfig.loadingErrUrl
} }
}, },
watch: { watch: {
+1 -1
Zobrazit soubor
@@ -1,6 +1,6 @@
<template> <template>
<view class="category-mini-card"> <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> :fileMd5="$utils.checkThumbnailUrl(category.spec.cover)" mode="aspectFill"></cache-image>
<view class="content"> <view class="content">
<view class="name">{{ category.spec.displayName }}</view> <view class="name">{{ category.spec.displayName }}</view>
+7 -5
Zobrazit soubor
@@ -72,9 +72,11 @@
} }
}, },
computed: { computed: {
// 获取博主信息 imageConfigs() {
return this.$tm.vx.getters().getConfigs.imagesConfig;
},
bloggerInfo() { 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); blogger.avatar = this.$utils.checkAvatarUrl(blogger.avatar, true);
return blogger; return blogger;
} }
@@ -82,10 +84,10 @@
methods: { methods: {
fnOnImageError(data) { fnOnImageError(data) {
if (data && data.owner) { if (data && data.owner) {
if (this.$haloConfig.defaultAvatarUrl.indexOf('?') == -1) { if (this.imageConfigs.defaultAvatarUrl.indexOf('?') == -1) {
data.owner.avatar = `${this.$haloConfig.defaultAvatarUrl}?next-v=${new Date().getTime()}` data.owner.avatar = `${this.imageConfigs.defaultAvatarUrl}?next-v=${new Date().getTime()}`
} else { } else {
data.owner.avatar = `${this.$haloConfig.defaultAvatarUrl}&next-v=${new Date().getTime()}` data.owner.avatar = `${this.imageConfigs.defaultAvatarUrl}&next-v=${new Date().getTime()}`
} }
} }
} }
+127 -145
Zobrazit soubor
@@ -2,176 +2,158 @@
<view class="journal-card mb-24 round-3 bg-white "> <view class="journal-card mb-24 round-3 bg-white ">
<view class="head pa-24 pb-0 flex flex-between"> <view class="head pa-24 pb-0 flex flex-between">
<view class="left flex"> <view class="left flex">
<cache-image <cache-image class="avatar rounded" radius="50%" width="70rpx" height="70rpx" :url="bloggerInfo.avatar"
class="avatar rounded" :fileMd5="bloggerInfo.avatar" mode="scaleToFill"></cache-image>
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="info pl-16 flex flex-col">
<view class="nickname text-weight-b text-grey-darken-4">{{ bloggerInfo.nickname }}</view> <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> </view>
<view class="right"> <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="useLike" :shadow="0" theme="light-blue" size="s"
<tm-button v-if="useEdit" :shadow="0" theme="light-blue" size="s" @click="$emit('on-edit', journal)">编辑</tm-button> @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> <tm-button v-if="useDel" :shadow="0" theme="red" size="s" @click="fnDel(journal)">删除</tm-button>
</view> </view>
</view> </view>
<tm-more v-if="journal.content.length > 50" :maxHeight="100" label="查看全部内容" open-label="隐藏部分内容"> <tm-more v-if="journal.content.length > 50" :maxHeight="100" label="查看全部内容" open-label="隐藏部分内容">
<mp-html <mp-html class="evan-markdown" lazy-load :domain="markdownConfig.domain"
class="evan-markdown" :loading-img="markdownConfig.loadingGif" :scroll-table="true" :selectable="true"
lazy-load :tag-style="markdownConfig.tagStyle" :container-style="markdownConfig.containStyle"
:domain="markdownConfig.domain" :content="journal.content" :markdown="true" :showLineNumber="true" :showLanguageName="true"
:loading-img="markdownConfig.loadingGif" :copyByLongPress="true" />
: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> </tm-more>
<mp-html <mp-html v-else class="evan-markdown" lazy-load :domain="markdownConfig.domain"
v-else :loading-img="markdownConfig.loadingGif" :scroll-table="true" :selectable="true"
class="evan-markdown" :tag-style="markdownConfig.tagStyle" :container-style="markdownConfig.containStyle"
lazy-load :content="journal.content" :markdown="true" :showLineNumber="true" :showLanguageName="true"
:domain="markdownConfig.domain" :copyByLongPress="true" />
: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> </view>
</template> </template>
<script> <script>
import MarkdownConfig from '@/common/markdown/markdown.config.js'; import MarkdownConfig from '@/common/markdown/markdown.config.js';
import mpHtml from '@/components/mp-html/components/mp-html/mp-html.vue'; import mpHtml from '@/components/mp-html/components/mp-html/mp-html.vue';
import tmButton from '@/tm-vuetify/components/tm-button/tm-button.vue'; import tmButton from '@/tm-vuetify/components/tm-button/tm-button.vue';
import tmMore from '@/tm-vuetify/components/tm-more/tm-more.vue'; import tmMore from '@/tm-vuetify/components/tm-more/tm-more.vue';
export default { export default {
name: 'journal-card', name: 'journal-card',
components: { mpHtml, tmButton, tmMore }, components: {
props: { mpHtml,
isAdmin: { tmButton,
type: Boolean, tmMore
default: false
}, },
journal: { props: {
type: Object, isAdmin: {
default: () => {} type: Boolean,
default: false
},
journal: {
type: Object,
default: () => {}
},
useLike: {
type: Boolean,
default: false
},
useEdit: {
type: Boolean,
default: false
},
useDel: {
type: Boolean,
default: false
}
}, },
useLike: { data() {
type: Boolean, return {
default: false markdownConfig: MarkdownConfig
};
}, },
useEdit: { computed: {
type: Boolean, bloggerInfo() {
default: false let blogger = this.$tm.vx.getters().getConfigs.authorConfig.blogger;
blogger.avatar = this.$utils.checkAvatarUrl(blogger.avatar, true);
return blogger;
},
}, },
useDel: { methods: {
type: Boolean, fnLike(journal) {
default: false uni.showLoading({
} mask: true,
}, title: '正在点赞中...'
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('Ծ‸Ծ点赞失败了~');
}); });
}, 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) { fnDel(journal) {
uni.$eShowModal({ uni.$eShowModal({
title: '提示', title: '提示',
content: '您确定要删除该日记吗?', content: '您确定要删除该日记吗?',
showCancel: true, showCancel: true,
cancelText: '否', cancelText: '否',
cancelColor: '#999999', cancelColor: '#999999',
confirmText: '是', confirmText: '是',
confirmColor: '#03a9f4' confirmColor: '#03a9f4'
}) })
.then(res => { .then(res => {
this.$httpApi.admin this.$httpApi.admin
.deleteJournalsById(journal.id) .deleteJournalsById(journal.id)
.then(res => { .then(res => {
if (res.status == 200) { if (res.status == 200) {
this.$emit('on-del', journal); this.$emit('on-del', journal);
uni.$tm.toast('删除成功!'); uni.$tm.toast('删除成功!');
} else { } else {
uni.$tm.toast('Ծ‸Ծ删除失败~');
}
})
.catch(err => {
uni.$tm.toast('Ծ‸Ծ删除失败~'); uni.$tm.toast('Ծ‸Ծ删除失败~');
} });
}) })
.catch(err => { .catch(() => {});
uni.$tm.toast('Ծ‸Ծ删除失败~'); }
});
})
.catch(() => {});
} }
} };
};
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.journal-card { .journal-card {
box-sizing: border-box; box-sizing: border-box;
box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.05); box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.05);
overflow: hidden; overflow: hidden;
.avatar {
width: 70rpx; .avatar {
height: 70rpx; width: 70rpx;
border: 6rpx solid #fff; height: 70rpx;
box-shadow: 0rpx 0rpx 24rpx rgba(0, 0, 0, 0.05); border: 6rpx solid #fff;
} box-shadow: 0rpx 0rpx 24rpx rgba(0, 0, 0, 0.05);
.info {
justify-content: center;
.nickname {
font-size: 30rpx;
} }
.time {
font-size: 26rpx; .info {
justify-content: center;
.nickname {
font-size: 30rpx;
}
.time {
font-size: 26rpx;
}
} }
} }
} </style>
</style>
-14
Zobrazit soubor
@@ -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
Zobrazit soubor
@@ -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
Zobrazit soubor
@@ -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
Zobrazit soubor
@@ -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
Zobrazit soubor
@@ -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
Zobrazit soubor
@@ -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
Zobrazit soubor
@@ -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
Zobrazit soubor
@@ -62,18 +62,9 @@ Vue.prototype.$http = http;
import ApiManager from '@/api/index.js' import ApiManager from '@/api/index.js'
Vue.use(ApiManager); Vue.use(ApiManager);
import HaloConfig from '@/config/halo.config.js'
import HaloTokenConfig from '@/config/token.config.js' import HaloTokenConfig from '@/config/token.config.js'
Vue.prototype.$haloConfig = HaloConfig
Vue.prototype.$baseApiUrl = HaloTokenConfig.BASE_API 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非必填 // 由于微信小程序的运行机制问题,需声明如下一行,H5和APP非必填
Vue.prototype._i18n = i18n; Vue.prototype._i18n = i18n;
@@ -83,7 +74,6 @@ const app = new Vue({
i18n, i18n,
...App, ...App,
}); });
// app.$mount();
// #ifdef H5 // #ifdef H5
RouterMount(app, router, '#app') RouterMount(app, router, '#app')
+42 -31
Zobrazit soubor
@@ -1,35 +1,46 @@
<template> <template>
<view class="app-page"></view> <view class="app-page"></view>
</template> </template>
<script> <script>
export default { export default {
onLoad() { computed: {
this.fnCheckShowStarted(); configs() {
}, return this.$tm.vx.getters().getConfigs;
methods: { }
// 检查是否需要跳转到启动页 },
fnCheckShowStarted() { onLoad() {
if (!getApp().globalData.start.use) { uni.$tm.vx.actions('config/fetchConfigs').then((res) => {
uni.switchTab({ console.log('正常:', res)
url: '/pages/tabbar/home/home' // #ifdef MP-WEIXIN
}); uni.$tm.vx.commit('setWxShare', res.shareConfig);
return; // #endif
} this.fnCheckShowStarted();
if (uni.getStorageSync('APP_HAS_STARTED')) { }).catch((err) => {
uni.switchTab({ console.log('异常:', err)
url: '/pages/tabbar/home/home' uni.switchTab({
}); url: '/pages/tabbar/home/home'
});
// uni.navigateTo({ })
// url:'/pagesA/test-page/test-page' },
// }) methods: {
} else { fnCheckShowStarted() {
uni.redirectTo({ if (!this.configs.startConfig.enable) {
url: '/pagesA/start/start' uni.switchTab({
}); url: '/pages/tabbar/home/home'
} });
} return;
} }
}; if (uni.getStorageSync('APP_HAS_STARTED')) {
</script> uni.switchTab({
url: '/pages/tabbar/home/home'
});
} else {
uni.redirectTo({
url: '/pagesA/start/start'
});
}
}
}
};
</script>
Rozdílový obsah nebyl zobrazen, protože je příliš veliký Načíst rozdílové porovnání
+4 -10
Zobrazit soubor
@@ -7,20 +7,19 @@
</view> </view>
<!-- 内容区域 --> <!-- 内容区域 -->
<view v-else class="app-page-content"> <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> <tm-empty icon="icon-shiliangzhinengduixiang-" label="暂无数据"></tm-empty>
</view> </view>
<block v-else> <block v-else>
<tm-translate v-for="(item, index) in dataList" :key="index" <tm-translate v-for="(item, index) in dataList" :key="index"
style="box-sizing: border-box;width: 50%;padding: 0 8rpx;" animation-name="fadeUp" style="box-sizing: border-box;width: 50%;padding: 0 8rpx;" animation-name="fadeUp"
:wait="calcAniWait(index)"> :wait="calcAniWait(index)">
<view class="catgory-card" :style="{backgroundImage:`url(${item.spec.cover})`}"> <view class="catgory-card" :style="{backgroundImage:`url(${item.spec.cover})`}">
<view class="content" @click="handleToCategory(item)"> <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;"> <view style="font-size: 24rpx;color: #ffffff;margin-top: 6rpx;">
{{item.postCount}} 篇文章 {{ item.postCount }} 篇文章
</view> </view>
</view> </view>
</view> </view>
@@ -40,6 +39,7 @@
import MarkdownConfig from '@/common/markdown/markdown.config.js'; import MarkdownConfig from '@/common/markdown/markdown.config.js';
import mpHtml from '@/components/mp-html/components/mp-html/mp-html.vue'; import mpHtml from '@/components/mp-html/components/mp-html/mp-html.vue';
export default { export default {
components: { components: {
tmSkeleton, tmSkeleton,
@@ -63,12 +63,6 @@
}; };
}, },
computed: {
bloggerInfo() {
return this.$tm.vx.getters().getBlogger;
},
},
onLoad() { onLoad() {
this.fnGetData(); this.fnGetData();
}, },
+235 -235
Zobrazit soubor
@@ -1,253 +1,253 @@
<template> <template>
<view class="app-page"> <view class="app-page">
<!-- 顶部切换 --> <!-- 顶部切换 -->
<view class="e-fixed" v-if="category.list.length > 0"> <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" <tm-tabs color="light-blue" v-model="category.activeIndex" range-key="displayName" :list="category.list"
align="left" @change="fnOnCategoryChange"></tm-tabs> align="left" @change="fnOnCategoryChange"></tm-tabs>
</view> </view>
<!-- 占位区域 --> <!-- 占位区域 -->
<view v-if="category.list.length > 0" style="width: 100vw;height: 90rpx;"></view> <view v-if="category.list.length > 0" style="width: 100vw;height: 90rpx;"></view>
<!-- 加载区域 --> <!-- 加载区域 -->
<view v-if="loading != 'success'" class="loading-wrap"> <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>
<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>
<!-- 内容区域 --> <!-- 内容区域 -->
<view class="content" v-else> <view class="content" v-else>
<view v-if="dataList.length == 0" class="content-empty"> <view v-if="dataList.length == 0" class="content-empty">
<!-- 空布局 --> <!-- 空布局 -->
<tm-empty icon="icon-shiliangzhinengduixiang-" label="博主还没有分享图片~"></tm-empty> <tm-empty icon="icon-shiliangzhinengduixiang-" label="博主还没有分享图片~"></tm-empty>
</view> </view>
<block v-else> <block v-else>
<block v-for="(item, index) in dataList" :key="index"> <block v-for="(item, index) in dataList" :key="index">
<tm-translate style="box-sizing: border-box;padding: 6rpx;width: 50%;height: 250rpx;" <tm-translate style="box-sizing: border-box;padding: 6rpx;width: 50%;height: 250rpx;"
animation-name="fadeUp" :wait="calcAniWait(index)"> animation-name="fadeUp" :wait="calcAniWait(index)">
<view style="border-radius: 12rpx;overflow: hidden;width: 100%;height: 250rpx;"> <view style="border-radius: 12rpx;overflow: hidden;width: 100%;height: 250rpx;">
<image style="width: 100%;height: 100%;" mode="aspectFill" :src="item.spec.cover" <image style="width: 100%;height: 100%;" mode="aspectFill" :src="item.spec.cover"
@click="fnPreview(index)" /> @click="fnPreview(index)"/>
</view> </view>
</tm-translate> </tm-translate>
</block> </block>
<tm-flotbutton @click="fnToTopPage" color="light-blue" size="m" icon="icon-angle-up"></tm-flotbutton> <tm-flotbutton @click="fnToTopPage" color="light-blue" size="m" icon="icon-angle-up"></tm-flotbutton>
<view class="load-text">{{ loadMoreText }}</view> <view class="load-text">{{ loadMoreText }}</view>
</block> </block>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue'; import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue'; import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue'; import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
import tmTags from '@/tm-vuetify/components/tm-tags/tm-tags.vue'; import tmTags from '@/tm-vuetify/components/tm-tags/tm-tags.vue';
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue'; import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
import tmIcons from '@/tm-vuetify/components/tm-icons/tm-icons.vue'; import tmIcons from '@/tm-vuetify/components/tm-icons/tm-icons.vue';
import tmImages from '@/tm-vuetify/components/tm-images/tm-images.vue'; import tmImages from '@/tm-vuetify/components/tm-images/tm-images.vue';
import tmFlowLayout from '@/tm-vuetify/components/tm-flowLayout/tm-flowLayout.vue'; import tmFlowLayout from '@/tm-vuetify/components/tm-flowLayout/tm-flowLayout.vue';
import tmTabs from '@/tm-vuetify/components/tm-tabs/tm-tabs.vue'; import tmTabs from '@/tm-vuetify/components/tm-tabs/tm-tabs.vue';
export default { export default {
components: { components: {
tmSkeleton, tmSkeleton,
tmTranslate, tmTranslate,
tmFlotbutton, tmFlotbutton,
tmTags, tmTags,
tmEmpty, tmEmpty,
tmIcons, tmIcons,
tmImages, tmImages,
tmFlowLayout, tmFlowLayout,
tmTabs tmTabs
}, },
data() { data() {
return { return {
isBlackTheme: false, isBlackTheme: false,
loading: 'loading', loading: 'loading',
category: { category: {
activeIndex: 0, activeIndex: 0,
activeValue: '', activeValue: '',
list: [] list: []
}, },
queryParams: { queryParams: {
size: 10, size: 10,
page: 1, page: 1,
group: "" group: ""
}, },
cache: { cache: {
dataList: [], dataList: [],
total: 0 total: 0
}, },
isLoadMore: false, isLoadMore: false,
loadMoreText: '', loadMoreText: '',
hasNext: false, hasNext: false,
dataList: [] dataList: []
}; };
}, },
filters: { filters: {
filterTakeTime(val) { filterTakeTime(val) {
return uni.$tm.dayjs(val).format('DD/MM/YYYY'); return uni.$tm.dayjs(val).format('DD/MM/YYYY');
} }
}, },
onLoad() { onLoad() {
this.fnSetPageTitle('个人图库'); this.fnSetPageTitle('个人图库');
this.fnGetCategory(); this.fnGetCategory();
}, },
onPullDownRefresh() { onPullDownRefresh() {
this.dataList = [] this.dataList = []
this.isLoadMore = false; this.isLoadMore = false;
this.queryParams.page = 1; this.queryParams.page = 1;
this.fnGetData(); this.fnGetData();
}, },
onReachBottom(e) { onReachBottom(e) {
if (this.hasNext) { if (this.hasNext) {
this.queryParams.page += 1; this.queryParams.page += 1;
this.isLoadMore = true; this.isLoadMore = true;
this.fnGetData(); this.fnGetData();
} else { } else {
uni.showToast({ uni.showToast({
icon: 'none', icon: 'none',
title: '没有更多数据了' title: '没有更多数据了'
}); });
} }
}, },
methods: { methods: {
fnOnCategoryChange(index) { fnOnCategoryChange(index) {
this.fnResetSetAniWaitIndex(); this.fnResetSetAniWaitIndex();
this.cache.dataList = [] this.cache.dataList = []
this.dataList = []; this.dataList = [];
this.queryParams.group = this.category.list[index].name; this.queryParams.group = this.category.list[index].name;
this.queryParams.page = 1; this.queryParams.page = 1;
this.fnToTopPage(); this.fnToTopPage();
this.fnGetData(); this.fnGetData();
}, },
fnGetCategory() { fnGetCategory() {
this.$httpApi.v2.getPhotoGroupList({ this.$httpApi.v2.getPhotoGroupList({
page: 1, page: 1,
size: 9999 size: 9999
}).then(res => { }).then(res => {
this.category.list = res.items.map(item => { this.category.list = res.items.map(item => {
return { return {
name: item.metadata.name, name: item.metadata.name,
displayName: item.spec.displayName displayName: item.spec.displayName
} }
}); });
if (this.category.list.length !== 0) { if (this.category.list.length !== 0) {
this.queryParams.group = this.category.list[0].name; this.queryParams.group = this.category.list[0].name;
this.fnGetData(); this.fnGetData();
} }
}); });
}, },
fnGetData() { fnGetData() {
// 设置状态为加载中 // 设置状态为加载中
if (!this.isLoadMore) { if (!this.isLoadMore) {
this.loading = 'loading'; this.loading = 'loading';
} }
this.loadMoreText = ''; this.loadMoreText = '';
this.$httpApi.v2 this.$httpApi.v2
.getPhotoListByGroupName(this.queryParams) .getPhotoListByGroupName(this.queryParams)
.then(res => { .then(res => {
console.log("相册 res", res) console.log("相册 res", res)
this.hasNext = res.hasNext; this.hasNext = res.hasNext;
this.loading = 'success'; this.loading = 'success';
if (res.items.length != 0) { if (res.items.length != 0) {
const _list = res.items.map((item, index) => { const _list = res.items.map((item, index) => {
item.spec.cover = this.$utils.checkImageUrl(item.spec.cover); item.spec.cover = this.$utils.checkImageUrl(item.spec.cover);
return item; return item;
}); });
this.fnCacheDataList(_list); this.fnCacheDataList(_list);
if (this.isLoadMore) { if (this.isLoadMore) {
this.dataList = this.dataList.concat(_list); this.dataList = this.dataList.concat(_list);
} else { } else {
this.dataList = _list; this.dataList = _list;
} }
} }
this.loadMoreText = res.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~'; this.loadMoreText = res.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
}) })
.catch(err => { .catch(err => {
console.error(err); console.error(err);
this.loading = 'error'; this.loading = 'error';
this.waterfall.loading = 'finish'; this.waterfall.loading = 'finish';
this.loadMoreText = '加载失败,请下拉刷新!'; this.loadMoreText = '加载失败,请下拉刷新!';
}) })
.finally(() => { .finally(() => {
setTimeout(() => { setTimeout(() => {
uni.hideLoading(); uni.hideLoading();
uni.stopPullDownRefresh(); uni.stopPullDownRefresh();
}, 500); }, 500);
}); });
}, },
// 缓存数据 // 缓存数据
fnCacheDataList(dataList) { fnCacheDataList(dataList) {
if (this.queryParams.page == 1) { if (this.queryParams.page == 1) {
this.cache.dataList = dataList; this.cache.dataList = dataList;
} else { } else {
this.cache.dataList = [...this.cache.dataList, ...dataList]; this.cache.dataList = [...this.cache.dataList, ...dataList];
} }
}, },
// 瀑布流组件点击事件 // 瀑布流组件点击事件
fnOnClick(data) { fnOnClick(data) {
console.log('点击数据', data); console.log('点击数据', data);
}, },
// 预览 // 预览
fnPreview(index) { fnPreview(index) {
uni.previewImage({ uni.previewImage({
current: index, current: index,
urls: this.dataList.map(x => x.spec.cover), urls: this.dataList.map(x => x.spec.cover),
indicator: 'number', indicator: 'number',
loop: true loop: true
}); });
} }
} }
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.app-page { .app-page {
width: 100vw; width: 100vw;
min-height: 100vh; min-height: 100vh;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
padding-bottom: 24rpx; padding-bottom: 24rpx;
background-color: #fafafa; background-color: #fafafa;
&.is-balck { &.is-balck {
background-color: #212121; background-color: #212121;
} }
} }
.content { .content {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
box-sizing: border-box; box-sizing: border-box;
padding: 0 24rpx; padding: 0 24rpx;
padding-top: 24rpx; padding-top: 24rpx;
gap: 12rpx 0; gap: 12rpx 0;
.content-empty { .content-empty {
width: 100%; width: 100%;
height: 60vh; height: 70vh;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
} }
.loading-wrap { .loading-wrap {
box-sizing: border-box; box-sizing: border-box;
padding: 24rpx; padding: 24rpx;
} }
.card { .card {
box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.03); box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.03);
} }
.load-text { .load-text {
width: 100%; width: 100%;
text-align: center; text-align: center;
} }
</style> </style>
+412 -406
Zobrazit soubor
@@ -1,446 +1,452 @@
<template> <template>
<view class="app-page"> <view class="app-page">
<tm-menubars iconColor="white" color="white" :flat="true" :showback="false"> <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> <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"> <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> <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 class="search-input_text pl-12 text-size-m text-grey">搜索文章...</view>
</view> </view>
<!-- #ifdef APP-PLUS || H5 --> <!-- #ifdef APP-PLUS || H5 -->
<view slot="right" class="mr-24 text-size-m text-grey">uni-halo</view> <view slot="right" class="mr-24 text-size-m text-grey">uni-halo</view>
<!-- #endif --> <!-- #endif -->
</tm-menubars> </tm-menubars>
<view v-if="loading != 'success' && articleList.length===0" class="loading-wrap"> <view v-if="loading !== 'success' && articleList.length===0" class="loading-wrap">
<tm-skeleton model="card"></tm-skeleton> <tm-skeleton model="card"></tm-skeleton>
<tm-skeleton model="cardActions"></tm-skeleton> <tm-skeleton model="cardActions"></tm-skeleton>
<tm-skeleton model="list"></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> <tm-skeleton model="listAvatr"></tm-skeleton>
<tm-skeleton model="listAvatr"></tm-skeleton> <tm-skeleton model="listAvatr"></tm-skeleton>
</view> </view>
<block v-else> <block v-else>
<view class="bg-white pb-24"> <view class="bg-white pb-24">
<view class="banner bg-white ml-24 mr-24 mt-12 round-3" v-if="bannerList.length != 0"> <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" <e-swiper :dotPosition="globalAppSettings.banner.dotPosition" :autoplay="true"
:useDot="globalAppSettings.banner.useDot" :list="bannerList" :useDot="globalAppSettings.banner.useDot" :list="bannerList"
@on-click="fnOnBannerClick"></e-swiper> @on-click="fnOnBannerClick"></e-swiper>
</view> </view>
</view> </view>
<view class="flex flex-between mt-16 mb-24 pl-24 pr-24"> <view class="flex flex-between mt-16 mb-24 pl-24 pr-24">
<view class="page-item_title text-weight-b ">精品分类</view> <view class="page-item_title text-weight-b ">精品分类</view>
<view class="show-more flex flex-center bg-white round-3" @click="fnToCategoryPage"> <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> <text class="iconfont icon-angle-right text-size-s text-grey-darken-1"></text>
</view> </view>
<view v-if="false" class="flex flex-center text-size-s text-grey-darken-1" @click="fnToCategoryPage"> <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=" text-size-m">查看更多</text>
<text class="iconfont icon-angle-right text-size-s "></text> <text class="iconfont icon-angle-right text-size-s "></text>
</view> </view>
</view> </view>
<scroll-view class="category" scroll-x="true"> <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 v-if="categoryList.length == 0" class="cate-empty round-3 mr-5 flex flex-center text-grey">
还没有任何文章分类~</view> 还没有任何文章分类~
<block v-else> </view>
<view class="content" v-for="(category, index) in categoryList" :key="category.metadata.name" <block v-else>
@click="fnToCategoryBy(category)"> <view class="content" v-for="(category, index) in categoryList" :key="category.metadata.name"
<category-mini-card :category="category"></category-mini-card> @click="fnToCategoryBy(category)">
</view> <category-mini-card :category="category"></category-mini-card>
</block> </view>
</scroll-view> </block>
</scroll-view>
<!-- 最新文章 --> <!-- 最新文章 -->
<view class="flex flex-between mt-24 mb-24 pl-24 pr-24"> <view class="flex flex-between mt-24 mb-24 pl-24 pr-24">
<view class="page-item_title text-weight-b">文章列表</view> <view class="page-item_title text-weight-b">文章列表</view>
<view class="show-more flex flex-center bg-white round-3" @click="fnToArticlesPage"> <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> <text class="iconfont icon-angle-right text-size-s text-grey-darken-1"></text>
</view> </view>
<view v-if="false" class="flex flex-center text-size-s text-grey-darken-1" @click="fnToArticlesPage"> <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=" text-size-m ">查看更多</text>
<text class="iconfont icon-angle-right text-size-s "></text> <text class="iconfont icon-angle-right text-size-s "></text>
</view> </view>
</view> </view>
<view v-if="articleList.length == 0" class="article-empty"><tm-empty icon="icon-shiliangzhinengduixiang-" <view v-if="articleList.length == 0" class="article-empty">
label="博主还没有发表任何文章~"></tm-empty></view> <tm-empty icon="icon-shiliangzhinengduixiang-"
<block v-else> label="博主还没有发表任何文章~"></tm-empty>
<view :class="globalAppSettings.layout.home"> </view>
<tm-translate v-for="(article, index) in articleList" :key="index" class="ani-item" <block v-else>
animation-name="fadeUp" :wait="calcAniWait(index)"> <view :class="globalAppSettings.layout.home">
<article-card from="home" :article="article" :post="article" <tm-translate v-for="(article, index) in articleList" :key="index" class="ani-item"
@on-click="fnToArticleDetail"></article-card> animation-name="fadeUp" :wait="calcAniWait(index)">
</tm-translate> <article-card from="home" :article="article" :post="article"
</view> @on-click="fnToArticleDetail"></article-card>
<view class="load-text mt-12">{{ loadMoreText }}</view> </tm-translate>
<tm-flotbutton v-if="articleList.length > 10" color="light-blue" @click="fnToTopPage" size="m" </view>
icon="icon-angle-up"></tm-flotbutton> <view class="load-text mt-12">{{ loadMoreText }}</view>
</block> <tm-flotbutton v-if="articleList.length > 10" color="light-blue" @click="fnToTopPage" size="m"
</block> icon="icon-angle-up"></tm-flotbutton>
</view> </block>
</block>
</view>
</template> </template>
<script> <script>
import tmMenubars from '@/tm-vuetify/components/tm-menubars/tm-menubars.vue'; import tmMenubars from '@/tm-vuetify/components/tm-menubars/tm-menubars.vue';
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue'; import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue'; import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue'; import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
import tmIcons from '@/tm-vuetify/components/tm-icons/tm-icons.vue'; import tmIcons from '@/tm-vuetify/components/tm-icons/tm-icons.vue';
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue'; import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
import eSwiper from '@/components/e-swiper/e-swiper.vue'; import eSwiper from '@/components/e-swiper/e-swiper.vue';
import qs from 'qs' import qs from 'qs'
export default { export default {
components: { components: {
tmMenubars, tmMenubars,
tmSkeleton, tmSkeleton,
tmTranslate, tmTranslate,
tmFlotbutton, tmFlotbutton,
tmIcons, tmIcons,
tmEmpty, tmEmpty,
eSwiper eSwiper
}, },
data() { data() {
return { return {
loading: 'loading', loading: 'loading',
queryParams: { queryParams: {
size: 5, size: 5,
page: 1, page: 1,
sort: ['spec.pinned,desc', 'spec.publishTime,desc'] sort: ['spec.pinned,desc', 'spec.publishTime,desc']
}, },
result: {}, result: {},
isLoadMore: false, isLoadMore: false,
loadMoreText: '加载中...', loadMoreText: '加载中...',
bannerCurrent: 0, bannerCurrent: 0,
bannerList: [], bannerList: [],
noticeList: [], noticeList: [],
articleList: [], articleList: [],
categoryList: [], categoryList: [],
}; };
}, },
computed: { computed: {
bloggerInfo() { 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); console.log('blogger----------------', blogger)
return blogger; blogger.avatar = this.$utils.checkAvatarUrl(blogger.avatar, true);
}, return blogger;
},
},
onLoad() {
this.fnSetPageTitle();
},
}, created() {
onLoad() { this.fnQuery();
this.fnSetPageTitle(); },
}, onPullDownRefresh() {
this.isLoadMore = false;
this.queryParams.page = 1;
this.fnQuery();
},
created() { onReachBottom(e) {
this.fnQuery(); if (this.result.hasNext) {
}, this.queryParams.page += 1;
onPullDownRefresh() { this.isLoadMore = true;
this.isLoadMore = false; this.fnGetArticleList();
this.queryParams.page = 1; } else {
this.fnQuery(); uni.showToast({
}, icon: 'none',
title: '没有更多数据了'
});
}
},
methods: {
fnQuery() {
this.fnGetBanner();
this.fnGetArticleList();
this.fnGetCategoryList();
},
onReachBottom(e) { fnGetCategoryList() {
if (this.result.hasNext) { this.$httpApi.v2
this.queryParams.page += 1; .getCategoryList({})
this.isLoadMore = true; .then(res => {
this.fnGetArticleList(); this.categoryList = res.items.sort((a, b) => {
} else { return b.postCount - a.postCount;
uni.showToast({ });
icon: 'none',
title: '没有更多数据了'
});
}
},
methods: {
fnQuery() {
this.fnGetBanner();
this.fnGetArticleList();
this.fnGetCategoryList();
},
fnGetCategoryList() { setTimeout(() => {
this.$httpApi.v2 this.loading = 'success';
.getCategoryList({}) }, 500);
.then(res => { })
this.categoryList = res.items.sort((a, b) => { .catch(err => {
return b.postCount - a.postCount; 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(() => { const paramsStr = qs.stringify(this.queryParams, {
this.loading = 'success'; allowDots: true,
}, 500); encodeValuesOnly: true,
}) skipNulls: true,
.catch(err => { encode: true,
console.error(err); arrayFormat: 'repeat'
this.loading = 'error'; })
}) uni.request({
.finally(() => { url: this.$baseApiUrl + '/apis/api.content.halo.run/v1alpha1/posts?' + paramsStr,
setTimeout(() => { method: 'GET',
uni.hideLoading(); params: this.queryParams,
uni.stopPullDownRefresh(); success: (res) => {
}, 500); this.bannerList = _format(res.data.items);
}); },
}, fail: (err) => {
// 获取轮播图 }
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, fnOnBannerChange(e) {
encodeValuesOnly: true, this.bannerCurrent = e.current;
skipNulls: true, },
encode: true, fnOnBannerClick(item) {
arrayFormat: 'repeat' if (item.id == '') return;
}) this.fnToArticleDetail({
uni.request({ metadata: {
url: this.$baseApiUrl + '/apis/api.content.halo.run/v1alpha1/posts?' + paramsStr, name: item.id
method: 'GET', }
params: this.queryParams, });
success: (res) => { },
this.bannerList = _format(res.data.items); // 文章列表
}, fnGetArticleList() {
fail: (err) => {} // uni.showLoading({
}) // mask: true,
// title: '加载中...'
// });
// 设置状态为加载中
if (!this.isLoadMore) {
this.loading = 'loading';
}
this.loadMoreText = '加载中...';
}, const paramsStr = qs.stringify(this.queryParams, {
fnOnBannerChange(e) { allowDots: true,
this.bannerCurrent = e.current; encodeValuesOnly: true,
}, skipNulls: true,
fnOnBannerClick(item) { encode: true,
if (item.id == '') return; arrayFormat: 'repeat'
this.fnToArticleDetail({ })
metadata: { uni.request({
name: item.id url: this.$baseApiUrl + '/apis/api.content.halo.run/v1alpha1/posts?' + paramsStr,
} method: 'GET',
}); params: this.queryParams,
}, success: (res) => {
// 文章列表 const data = res.data;
fnGetArticleList() { this.result.hasNext = data.hasNext;
// uni.showLoading({ if (this.isLoadMore) {
// mask: true, this.articleList = this.articleList.concat(data.items);
// title: '加载中...' } else {
// }); this.articleList = data.items;
// 设置状态为加载中 }
if (!this.isLoadMore) { this.loading = 'success';
this.loading = 'loading'; this.loadMoreText = data.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
} uni.hideLoading();
this.loadMoreText = '加载中...'; uni.stopPullDownRefresh();
},
fail: (err) => {
this.loading = 'error';
this.loadMoreText = '加载失败,请下拉刷新!';
uni.$tm.toast(err.message || '数据加载失败!');
uni.stopPullDownRefresh();
}
})
},
const paramsStr = qs.stringify(this.queryParams, { //跳转文章详情
allowDots: true, fnToArticleDetail(article) {
encodeValuesOnly: true, uni.navigateTo({
skipNulls: true, url: '/pagesA/article-detail/article-detail?name=' + article.metadata.name,
encode: true, animationType: 'slide-in-right'
arrayFormat: 'repeat' });
}) },
uni.request({ // 快捷导航页面跳转
url: this.$baseApiUrl + '/apis/api.content.halo.run/v1alpha1/posts?' + paramsStr, fnToNavPage(item) {
method: 'GET', switch (item.type) {
params: this.queryParams, case 'tabbar':
success: (res) => { uni.switchTab({
const data = res.data; url: item.path
this.result.hasNext = data.hasNext; });
if (this.isLoadMore) { break;
this.articleList = this.articleList.concat(data.items); case 'page':
} else { uni.navigateTo({
this.articleList = data.items; url: item.path
} });
this.loading = 'success'; break;
this.loadMoreText = data.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~'; }
uni.hideLoading(); },
uni.stopPullDownRefresh(); // 分类页面
}, fnToCategoryPage() {
fail: (err) => { uni.switchTab({
this.loading = 'error'; url: '/pages/tabbar/category/category'
this.loadMoreText = '加载失败,请下拉刷新!'; });
uni.$tm.toast(err.message || '数据加载失败!'); },
uni.stopPullDownRefresh(); // 所有的文章列表页面
} fnToArticlesPage() {
}) uni.navigateTo({
}, url: '/pagesA/articles/articles'
});
},
//跳转文章详情 // 根据slug查询分类下的文章
fnToArticleDetail(article) { fnToCategoryBy(category) {
uni.navigateTo({ uni.navigateTo({
url: '/pagesA/article-detail/article-detail?name=' + article.metadata.name, url: `/pagesA/category-detail/category-detail?name=${category.metadata.name}&title=${category.spec.displayName}`
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查询分类下的文章 fnChangeMode() {
fnToCategoryBy(category) { const isBlackTheme = this.$tm.vx.state().tmVuetify.black;
uni.navigateTo({ this.$tm.theme.setBlack(!isBlackTheme);
url: `/pagesA/category-detail/category-detail?name=${category.metadata.name}&title=${category.spec.displayName}` uni.setNavigationBarColor({
}); backgroundColor: !isBlackTheme ? '#0a0a0a' : '#ffffff',
}, frontColor: !isBlackTheme ? '#ffffff' : '#0a0a0a'
});
},
fnChangeMode() { fnToSearch() {
const isBlackTheme = this.$tm.vx.state().tmVuetify.black; uni.navigateTo({
this.$tm.theme.setBlack(!isBlackTheme); url: '/pagesA/articles/articles'
uni.setNavigationBarColor({ });
backgroundColor: !isBlackTheme ? '#0a0a0a' : '#ffffff', }
frontColor: !isBlackTheme ? '#ffffff' : '#0a0a0a' }
}); };
},
fnToSearch() {
uni.navigateTo({
url: '/pagesA/articles/articles'
});
}
}
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.app-page { .app-page {
width: 100vw; width: 100vw;
min-height: 100vh; min-height: 100vh;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
// background-color: #ffffff; // background-color: #ffffff;
.logo { .logo {
width: 60rpx; width: 60rpx;
height: 60rpx; height: 60rpx;
box-sizing: border-box; box-sizing: border-box;
} }
::v-deep { ::v-deep {
.tm-menubars .body .body_wk .left { .tm-menubars .body .body_wk .left {
min-width: initial; min-width: initial;
} }
} }
} }
.loading-wrap { .loading-wrap {
padding: 24rpx; padding: 24rpx;
} }
.search-input { .search-input {
background-color: #f5f5f5; background-color: #f5f5f5;
align-items: center; align-items: center;
/* #ifdef MP-WEIXIN */ /* #ifdef MP-WEIXIN */
margin-right: 24rpx; margin-right: 24rpx;
/* #endif */ /* #endif */
&_icon {} &_icon {
}
&_text {} &_text {
} }
}
.show-more { .show-more {
width: 42rpx; width: 42rpx;
height: 42rpx; height: 42rpx;
box-sizing: border-box; box-sizing: border-box;
box-shadow: 0rpx 0rpx 24rpx rgba(0, 0, 0, 0.03); box-shadow: 0rpx 0rpx 24rpx rgba(0, 0, 0, 0.03);
} }
.banner { .banner {
overflow: hidden; overflow: hidden;
} }
.quick-nav { .quick-nav {
background-color: #fff; background-color: #fff;
box-sizing: border-box; box-sizing: border-box;
// box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.03); // box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.03);
.name { .name {
color: var(--main-text-color); color: var(--main-text-color);
} }
} }
.category { .category {
width: 94vw; width: 94vw;
display: flex; display: flex;
height: 200rpx; height: 200rpx;
white-space: nowrap; white-space: nowrap;
margin: 0 24rpx; margin: 0 24rpx;
.content { .content {
display: inline-block; display: inline-block;
padding-left: 24rpx; padding-left: 24rpx;
&:first-child { &:first-child {
padding-left: 0; padding-left: 0;
} }
} }
.cate-empty { .cate-empty {
height: inherit; height: inherit;
} }
} }
.page-item { .page-item {
&_title { &_title {
position: relative; position: relative;
padding-left: 24rpx; padding-left: 24rpx;
font-size: 32rpx; font-size: 32rpx;
z-index: 1; z-index: 1;
color: var(--main-text-color); color: var(--main-text-color);
&:before { &:before {
content: ''; content: '';
position: absolute; position: absolute;
left: 0rpx; left: 0rpx;
top: 8rpx; top: 8rpx;
width: 8rpx; width: 8rpx;
height: 30rpx; height: 30rpx;
background-color: rgba(33, 150, 243, 1); background-color: rgba(33, 150, 243, 1);
border-radius: 6rpx; border-radius: 6rpx;
z-index: 0; z-index: 0;
} }
} }
} }
.h_row_col2 { .h_row_col2 {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
box-sizing: border-box; box-sizing: border-box;
padding: 0 12rpx; padding: 0 12rpx;
.ani-item { .ani-item {
width: 50%; width: 50%;
} }
} }
</style> </style>
+219 -215
Zobrazit soubor
@@ -1,236 +1,240 @@
<template> <template>
<view class="app-page"> <view class="app-page">
<view v-if="loading != 'success'" class="loading-wrap"> <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>
<tm-skeleton model="listAvatr"></tm-skeleton> <tm-skeleton model="listAvatr"></tm-skeleton>
</view> </view>
<!-- 内容区域 --> <!-- 内容区域 -->
<view v-else class="app-page-content"> <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="min-height: 70vh;">
<!-- 空布局 --> <!-- 空布局 -->
<tm-empty icon="icon-shiliangzhinengduixiang-" label="暂无数据"></tm-empty> <tm-empty icon="icon-shiliangzhinengduixiang-" label="暂无数据"></tm-empty>
</view> </view>
<block v-else> <block v-else>
<block v-for="(moment, index) in dataList" :key="index"> <block v-for="(moment, index) in dataList" :key="index">
<!-- 卡片 --> <!-- 卡片 -->
<tm-translate animation-name="fadeUp" :wait="calcAniWait()"> <tm-translate animation-name="fadeUp" :wait="calcAniWait()">
<view class="moment-card"> <view class="moment-card">
<view class="head" style="display: flex;align-items: center;"> <view class="head" style="display: flex;align-items: center;">
<view class="avatar" style="flex-shrink: 0;"> <view class="avatar" style="flex-shrink: 0;">
<image style="width: 66rpx;height: 66rpx;border-radius: 50%;" <image style="width: 66rpx;height: 66rpx;border-radius: 50%;"
:src="moment.spec.user.avatar" /> :src="moment.spec.user.avatar"/>
</view> </view>
<view class="nickname" style="margin-left: 12rpx;"> <view class="nickname" style="margin-left: 12rpx;">
<view style="font-size: 30rpx;font-weight: bold;color: #333333;"> <view style="font-size: 30rpx;font-weight: bold;color: #333333;">
{{moment.spec.user.displayName}} {{ moment.spec.user.displayName }}
</view> </view>
<view style="margin-top: 6rpx;font-size: 24rpx;color: #666;"> <view style="margin-top: 6rpx;font-size: 24rpx;color: #666;">
{{ { d: moment.spec.releaseTime, f: 'yyyy年MM月dd日 星期w' } | formatTime }} {{ {d: moment.spec.releaseTime, f: 'yyyy年MM月dd日 星期w'} | formatTime }}
</view> </view>
</view> </view>
</view> </view>
<view class="content"> <view class="content">
<mp-html class="evan-markdown" lazy-load :domain="markdownConfig.domain" <mp-html class="evan-markdown" lazy-load :domain="markdownConfig.domain"
:loading-img="markdownConfig.loadingGif" :scroll-table="true" :selectable="true" :loading-img="markdownConfig.loadingGif" :scroll-table="true" :selectable="true"
:tag-style="markdownConfig.tagStyle" :container-style="markdownConfig.containStyle" :tag-style="markdownConfig.tagStyle" :container-style="markdownConfig.containStyle"
:content="moment.spec.content.html" :markdown="true" :showLineNumber="true" :content="moment.spec.content.html" :markdown="true" :showLineNumber="true"
:showLanguageName="true" :copyByLongPress="true" /> :showLanguageName="true" :copyByLongPress="true"/>
</view> </view>
<view v-if="moment.spec.content.medium.length!==0" class="images" <view v-if="moment.spec.content.medium.length!==0" class="images"
:class="['images-'+moment.spec.content.medium.length]"> :class="['images-'+moment.spec.content.medium.length]">
<view class="image-item" v-for="(image,mediumIndex) in moment.spec.content.medium" <view class="image-item" v-for="(image,mediumIndex) in moment.spec.content.medium"
:key="mediumIndex"> :key="mediumIndex">
<image mode="aspectFill" style="width: 100%;height: 100%;border-radius: 6rpx;" <image mode="aspectFill" style="width: 100%;height: 100%;border-radius: 6rpx;"
:src="image.url" @click="handlePreview(mediumIndex,moment.spec.content.medium)" /> :src="image.url"
</view> @click="handlePreview(mediumIndex,moment.spec.content.medium)"/>
</view> </view>
</view> </view>
</tm-translate> </view>
</block> </tm-translate>
<tm-flotbutton @click="fnToTopPage" size="m" color="light-blue" icon="icon-angle-up"></tm-flotbutton> </block>
<view class="load-text">{{ loadMoreText }}</view> <tm-flotbutton @click="fnToTopPage" size="m" color="light-blue" icon="icon-angle-up"></tm-flotbutton>
</block> <view class="load-text">{{ loadMoreText }}</view>
</view> </block>
</view> </view>
</view>
</template> </template>
<script> <script>
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue'; import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue'; import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue'; import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue'; import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
import MarkdownConfig from '@/common/markdown/markdown.config.js'; import MarkdownConfig from '@/common/markdown/markdown.config.js';
import mpHtml from '@/components/mp-html/components/mp-html/mp-html.vue'; 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: '加载中...'
};
},
computed: { export default {
bloggerInfo() { components: {
return this.$tm.vx.getters().getBlogger; tmSkeleton,
}, tmFlotbutton,
}, tmTranslate,
tmEmpty,
mpHtml
},
data() {
return {
markdownConfig: MarkdownConfig,
loading: 'loading',
queryParams: {
size: 10,
page: 1
},
hasNext: false,
dataList: [],
isLoadMore: false,
loadMoreText: '加载中...'
};
},
onLoad() { computed: {
this.fnGetData(); bloggerInfo() {
}, let blogger = this.$tm.vx.getters().getConfigs.authorConfig.blogger;
onPullDownRefresh() { blogger.avatar = this.$utils.checkAvatarUrl(blogger.avatar, true);
this.isLoadMore = false; return blogger;
this.queryParams.page = 0; }
this.fnGetData(); },
},
onReachBottom(e) { onLoad() {
if (this.hasNext) { this.fnGetData();
this.queryParams.page += 1; },
this.isLoadMore = true; onPullDownRefresh() {
this.fnGetData(); this.isLoadMore = false;
} else { this.queryParams.page = 0;
uni.showToast({ this.fnGetData();
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);
this.loading = 'success'; onReachBottom(e) {
this.loadMoreText = res.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~'; if (this.hasNext) {
this.hasNext = res.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 => { this.loading = 'success';
item.spec.user = { this.loadMoreText = res.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
displayName: this.bloggerInfo.nickname, this.hasNext = res.hasNext;
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) { const tempItems = res.items.map(item => {
this.dataList = this.dataList.concat(tempItems); item.spec.user = {
} else { displayName: this.bloggerInfo.nickname,
this.dataList = tempItems; avatar: this.$utils.checkAvatarUrl(this.bloggerInfo.avatar)
} }
}) item.spec.content.medium
.catch(err => { .filter(x => x.type === 'PHOTO')
console.error(err); .map(medium => {
this.loading = 'error'; medium.url = this.$utils.checkThumbnailUrl(medium.url, true)
this.loadMoreText = '加载失败,请下拉刷新!'; })
}) return item;
.finally(() => { })
setTimeout(() => {
uni.hideLoading(); if (this.isLoadMore) {
uni.stopPullDownRefresh(); this.dataList = this.dataList.concat(tempItems);
}, 500); } else {
}); this.dataList = tempItems;
}, }
handlePreview(index, list) { })
uni.previewImage({ .catch(err => {
current: index, console.error(err);
urls: list.map(item => item.url) 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> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.app-page { .app-page {
width: 100vw; width: 100vw;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
padding: 24rpx 0; padding: 24rpx 0;
} }
.loading-wrap { .loading-wrap {
padding: 24rpx; padding: 24rpx;
} }
.moment-card { .moment-card {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
box-sizing: border-box; box-sizing: border-box;
margin: 0 24rpx; margin: 0 24rpx;
border-radius: 12rpx; border-radius: 12rpx;
background-color: #ffff; background-color: #ffff;
box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.03); box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.03);
overflow: hidden; overflow: hidden;
margin-bottom: 24rpx; margin-bottom: 24rpx;
} }
.head { .head {
padding: 24rpx; padding: 24rpx;
padding-bottom: 0; padding-bottom: 0;
} }
.images { .images {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
align-items: flex-start; align-items: flex-start;
padding: 24rpx; padding: 24rpx;
padding-top: 0; padding-top: 0;
.image-item { .image-item {
box-sizing: border-box; box-sizing: border-box;
border-radius: 24rpx; border-radius: 24rpx;
padding: 6rpx; padding: 6rpx;
width: 33%; width: 33%;
height: 200rpx height: 200rpx
} }
&-1 { &-1 {
>.image-item { > .image-item {
width: 100%; width: 100%;
height: 350rpx height: 350rpx
} }
} }
&-2 { &-2 {
>.image-item { > .image-item {
width: 50%; width: 50%;
height: 250rpx height: 250rpx
} }
} }
} }
</style> </style>
+80 -75
Zobrazit soubor
@@ -1,94 +1,99 @@
<template> <template>
<view class="app-page bg-white flex flex-col"> <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="logo mt-40 pt-40">
<view class="mt-12 text-weight-b text-size-lg" :class="{ 'mt-40 pt-40': !uni_halo_logo }">uni-halo</view> <image class="logo-img round-3" src="https://uni-halo.925i.cn/logo.png" mode="aspectFill"></image>
<view class="mt-12 text-size-s text-grey-darken-3"></view> </view>
<view class="list-group mt-48" style="width: 100%;"> <view class="mt-12 text-weight-b text-size-lg">uni-halo</view>
<tm-grouplist :shadow="0" :margin="0" :borderBottom="true"> <view class="mt-12 text-size-s text-grey-darken-3"></view>
<tm-listitem title="开源组织" :font-size="28" @click="$utils.copyText('https://www.ialley.cn', '巷子工坊官网已复制成功!')"> <view class="list-group mt-48" style="width: 100%;">
<text class="text-size-s" slot="rightValue">巷子工坊</text> <tm-grouplist :shadow="0" :margin="0" :borderBottom="true">
</tm-listitem> <tm-listitem title="开源组织" :font-size="28" @click="$utils.copyText('https://www.ialley.cn', '巷子工坊官网已复制成功!')">
<tm-listitem title="开源作者" :font-size="28" @click="$utils.copyText('https://b.925i.cn', '作者博客地址已复制')"> <text class="text-size-s" slot="rightValue">巷子工坊</text>
<text class="text-size-s" slot="rightValue">小莫唐尼</text> </tm-listitem>
</tm-listitem> <tm-listitem title="开源作者" :font-size="28" @click="$utils.copyText('https://b.925i.cn', '作者博客地址已复制')">
<tm-listitem title="作者博客" :font-size="28" @click="$utils.copyText('https://b.925i.cn', '作者博客地址已复制')"> <text class="text-size-s" slot="rightValue">小莫唐尼</text>
<text class="text-size-s text-overflow" slot="rightValue">https://b.925i.cn</text> </tm-listitem>
</tm-listitem> <tm-listitem title="作者博客" :font-size="28" @click="$utils.copyText('https://b.925i.cn', '作者博客地址已复制')">
<tm-listitem title="文档地址" :font-size="28" @click="$utils.copyText('https://uni-halo.925i.cn', '项目码云仓库已复制')"> <text class="text-size-s text-overflow" slot="rightValue">https://b.925i.cn</text>
<text class="text-size-s text-overflow" slot="rightValue">https://uni-halo.925i.cn</text> </tm-listitem>
</tm-listitem> <tm-listitem title="文档地址" :font-size="28" @click="$utils.copyText('https://uni-halo.925i.cn', '项目码云仓库已复制')">
<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://uni-halo.925i.cn</text>
<text class="text-size-s text-overflow" slot="rightValue">https://gitee.com/ialley-workshop-open/uni-halo</text> </tm-listitem>
</tm-listitem> <tm-listitem title="码云仓库" :font-size="28"
<tm-listitem title="Github" :font-size="28" @click="$utils.copyText('https://github.com/ialley-workshop-open/uni-halo', 'Github地址已复制')"> @click="$utils.copyText('https://gitee.com/ialley-workshop-open/uni-halo', '码云仓库地址已复制')">
<text class="text-size-s text-overflow" slot="rightValue">https://github.com/ialley-workshop-open/uni-halo</text> <text class="text-size-s text-overflow" slot="rightValue">https://gitee.com/ialley-workshop-open/uni-halo</text>
</tm-listitem> </tm-listitem>
</tm-grouplist> <tm-listitem title="Github" :font-size="28"
</view> @click="$utils.copyText('https://github.com/ialley-workshop-open/uni-halo', 'Github地址已复制')">
<view class="copyright bg-white text-size-xs text-align-center text-grey-darken-1 pa-36"> <text class="text-size-s text-overflow" slot="rightValue">https://github.com/ialley-workshop-open/uni-halo</text>
<view class="">根据 AGPL-3.0 协议开源</view> </tm-listitem>
<view class="mt-8"> 2022 uni-halo 开源项目丨巷子工坊@小莫唐尼 </view> </tm-grouplist>
</view> </view>
</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> </template>
<script> <script>
import tmGrouplist from '@/tm-vuetify/components/tm-grouplist/tm-grouplist.vue'; import tmGrouplist from '@/tm-vuetify/components/tm-grouplist/tm-grouplist.vue';
import tmListitem from '@/tm-vuetify/components/tm-listitem/tm-listitem.vue'; import tmListitem from '@/tm-vuetify/components/tm-listitem/tm-listitem.vue';
export default { export default {
components: { components: {
tmGrouplist, tmGrouplist,
tmListitem tmListitem
}, },
computed: { onLoad() {
uni_halo_logo() { this.fnSetPageTitle('关于项目');
return getApp().globalData.uni_halo_logo; },
} methods: {}
},
onLoad() {
this.fnSetPageTitle('关于项目');
},
methods: {}
}; };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.app-page { .app-page {
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
box-sizing: border-box; box-sizing: border-box;
align-items: center; 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;
}
.label { .logo-img {
display: inline-block; width: 160rpx;
min-width: 140rpx; 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 { .text-overflow {
width: calc(100vw - 300rpx); width: calc(100vw - 300rpx);
text-align: right; text-align: right;
} }
.list-group { .list-group {
::v-deep { ::v-deep {
.left { .left {
width: 160rpx; width: 160rpx;
min-width: 160rpx; min-width: 160rpx;
} }
} }
} }
</style> </style>
+7 -6
Zobrazit soubor
@@ -54,6 +54,11 @@ export default {
} }
} }
}, },
computed: {
adConfigs() {
return this.$tm.vx.getters().getConfigs.adConfig;
}
},
onLoad(options) { onLoad(options) {
// #ifdef MP-WEIXIN // #ifdef MP-WEIXIN
wx.hideShareMenu(); wx.hideShareMenu();
@@ -71,7 +76,7 @@ export default {
adLoad() { adLoad() {
if (wx.createRewardedVideoAd) { if (wx.createRewardedVideoAd) {
videoAd = wx.createRewardedVideoAd({ videoAd = wx.createRewardedVideoAd({
adUnitId: this.$haloAdConfig.rewardedVideoAd //你的广告key adUnitId: this.adConfigs.rewardedVideoAdId //你的广告key
}) })
videoAd.onError(err => { videoAd.onError(err => {
}) })
@@ -86,7 +91,7 @@ export default {
} }
}, },
openVideoAd: function () { openVideoAd: function () {
if (videoAd && this.$haloAdConfig.rewardedVideoAd != '') { if (videoAd && this.adConfigs.rewardedVideoAdId != '') {
videoAd.show().catch(err => { videoAd.show().catch(err => {
// 失败重试 // 失败重试
console.log("广告拉取失败") console.log("广告拉取失败")
@@ -138,7 +143,3 @@ export default {
} }
} }
</script> </script>
<style>
</style>
+328 -316
Zobrazit soubor
@@ -1,367 +1,379 @@
<template> <template>
<view class="app-page"> <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 class="e-fixed">
<!-- 占位区域 --> <tm-tabs color="light-blue" v-model="tab.activeIndex" :list="tab.list" align="center" @change="fnOnTabChange"></tm-tabs>
<view style="width: 100vw;height: 90rpx;"></view> </view>
<!-- 占位区域 -->
<view style="width: 100vw;height: 90rpx;"></view>
<!-- 骨架屏加载区域 --> <!-- 骨架屏加载区域 -->
<view v-if="loading != 'success'" class="loading-wrap"> <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>
<tm-skeleton model="listAvatr"></tm-skeleton> <tm-skeleton model="listAvatr"></tm-skeleton>
</view> </view>
<!-- 加载完成区域 --> <!-- 加载完成区域 -->
<block v-else> <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-if="dataList.length == 0" class="list-empty flex flex-center">
<view v-else class="e-timeline tm-timeline mt-24"> <tm-empty icon="icon-shiliangzhinengduixiang-" label="暂无归档的文章"></tm-empty>
<block v-for="(item, index) in dataList" :key="index"> </view>
<view class="tm-timeline-item tm-timeline-item--leftDir"> <view v-else class="e-timeline tm-timeline mt-24">
<view style="width: 160rpx;"> <block v-for="(item, index) in dataList" :key="index">
<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 class="tm-timeline-item tm-timeline-item--leftDir">
<view :style="{ marginTop: '-24rpx' }" :class="[index !== dataList.length - 1 ? 'tm-timeline-item-boder' : '', black_tmeme ? 'bk' : '']" class="grey-lighten-2"></view> <view style="width: 160rpx;">
</view> <view :style="{ width: '24rpx', height: '24rpx' }" :class="[black_tmeme ? 'bk' : '']"
<view class="tm-timeline-item-content relative"> class="flex-center rounded tm-timeline-jidian border-white-a-2 grey-lighten-2 light-blue shadow-primary-4"></view>
<view class="tm-timeline-item-left"> <view :style="{ marginTop: '-24rpx' }"
<view class="time text-weight-b mb-24"> :class="[index !== dataList.length - 1 ? 'tm-timeline-item-boder' : '', black_tmeme ? 'bk' : '']"
{{ item.year }} class="grey-lighten-2"></view>
<block v-if="tab.activeIndex == 0">{{ item.month }}</block> </view>
<text class="text-size-s text-grey-darken-1 ml-24">共发布 {{ item.posts.length }} 篇文章</text> <view class="tm-timeline-item-content relative">
</view> <view class="tm-timeline-item-left">
<block v-if="item.posts.length != 0"> <view class="time text-weight-b mb-24">
<block v-for="(post, postIndex) in item.posts" :key="post.id"> {{ item.year }}
<tm-translate animation-name="fadeUp" :wait="calcAniWait(postIndex)"> <block v-if="tab.activeIndex == 0">{{ item.month }}</block>
<view class="flex post shadow-3 pa-24 mb-24" :class="[globalAppSettings.layout.cardType]" @click="fnToArticleDetail(post)"> <text class="text-size-s text-grey-darken-1 ml-24">共发布 {{ item.posts.length }} 篇文章</text>
<image class="post-thumbnail" :src="$utils.checkThumbnailUrl(post.thumbnail)" mode="aspectFill"></image> </view>
<view class="post-info pl-20"> <block v-if="item.posts.length != 0">
<view class="post-info_title text-overflow">{{ post.title }}</view> <block v-for="(post, postIndex) in item.posts" :key="post.id">
<view class="post-info_summary text-overflow-2 mt-12 text-size-s text-grey-darken-1">{{ post.summary }}</view> <tm-translate animation-name="fadeUp" :wait="calcAniWait(postIndex)">
<view class="post-info_time mt-12 text-size-s text-grey-darken-1"> <view class="flex post shadow-3 pa-24 mb-24" :class="[globalAppSettings.layout.cardType]"
<text class="iconfont icon-clock text-size-s mr-6"></text> @click="fnToArticleDetail(post)">
<text class="time-label">发布时间</text> <image class="post-thumbnail" :src="$utils.checkThumbnailUrl(post.thumbnail)"
{{ { d: post.createTime, f: 'yyyy年MM月dd日 星期w' } | formatTime }} mode="aspectFill"></image>
</view> <view class="post-info pl-20">
</view> <view class="post-info_title text-overflow">{{ post.title }}</view>
</view> <view class="post-info_summary text-overflow-2 mt-12 text-size-s text-grey-darken-1">
</tm-translate> {{ post.summary }}
</block> </view>
</block> <view class="post-info_time mt-12 text-size-s text-grey-darken-1">
<view v-else class="post-empty text-size-m text-grey-darken-1">该日期下暂无归档文章</view> <text class="iconfont icon-clock text-size-s mr-6"></text>
</view> <text class="time-label">发布时间</text>
</view> {{ {d: post.createTime, f: 'yyyy年MM月dd日 星期w'} | formatTime }}
</view> </view>
</block> </view>
</view> </view>
<!-- 返回顶部 --> </tm-translate>
<tm-flotbutton @click="fnToTopPage" size="m" color="bg-gradient-light-blue-accent" icon="icon-angle-up"></tm-flotbutton> </block>
</block> </block>
</view> <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> </template>
<script> <script>
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue'; import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue'; import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue'; import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
import tmTabs from '@/tm-vuetify/components/tm-tabs/tm-tabs.vue'; import tmTabs from '@/tm-vuetify/components/tm-tabs/tm-tabs.vue';
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue'; import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
export default { export default {
components: { components: {
tmSkeleton, tmSkeleton,
tmTranslate, tmTranslate,
tmFlotbutton, tmFlotbutton,
tmTabs, tmTabs,
tmEmpty tmEmpty
}, },
data() { data() {
return { return {
loading: 'loading', loading: 'loading',
tab: { tab: {
activeIndex: 0, activeIndex: 0,
list: ['按月份查看', '按年份查看'] list: ['按月份查看', '按年份查看']
}, },
queryParams: { queryParams: {
size: 10, size: 10,
page: 0 page: 0
}, },
result: null, result: null,
dataList: [], dataList: [],
api: 'getMonthArchives' api: 'getMonthArchives'
}; };
}, },
computed: { computed: {
black_tmeme: function() { black_tmeme: function () {
return this.$tm.vx.state().tmVuetify.black; return this.$tm.vx.state().tmVuetify.black;
}, },
color_tmeme: function() { color_tmeme: function () {
return this.$tm.vx.state().tmVuetify.color; return this.$tm.vx.state().tmVuetify.color;
} }
}, },
created() { created() {
this.fnGetData(); this.fnGetData();
}, },
onPullDownRefresh() { onPullDownRefresh() {
this.fnGetData(); this.fnGetData();
this.queryParams.page = 0; this.queryParams.page = 0;
}, },
methods: { methods: {
fnOnTabChange(index) { fnOnTabChange(index) {
this.fnResetSetAniWaitIndex(); this.fnResetSetAniWaitIndex();
const _api = ['getMonthArchives', 'getYearArchives']; const _api = ['getMonthArchives', 'getYearArchives'];
this.api = _api[index]; this.api = _api[index];
this.queryParams.page = 0; this.queryParams.page = 0;
this.fnGetData(); this.fnGetData();
}, },
fnGetData() { fnGetData() {
this.loading = 'loading'; this.loading = 'loading';
// uni.showLoading({ // uni.showLoading({
// mask: true, // mask: true,
// title: '加载中...' // title: '加载中...'
// }); // });
this.$httpApi[this.api](this.queryParams) this.$httpApi[this.api](this.queryParams)
.then(res => { .then(res => {
this.result = res.data; this.result = res.data;
this.dataList = res.data; this.dataList = res.data;
setTimeout(() => { setTimeout(() => {
this.loading = 'success'; this.loading = 'success';
}, 500); }, 500);
}) })
.catch(err => { .catch(err => {
console.error(err); console.error(err);
this.loading = 'error'; this.loading = 'error';
}) })
.finally(() => { .finally(() => {
setTimeout(() => { setTimeout(() => {
uni.hideLoading(); uni.hideLoading();
uni.stopPullDownRefresh(); uni.stopPullDownRefresh();
}, 500); }, 500);
}); });
}, },
//跳转文章详情 //跳转文章详情
fnToArticleDetail(article) { fnToArticleDetail(article) {
uni.navigateTo({ uni.navigateTo({
url: '/pagesA/article-detail/article-detail?articleId=' + article.id, url: '/pagesA/article-detail/article-detail?articleId=' + article.id,
animationType: 'slide-in-right' animationType: 'slide-in-right'
}); });
} }
} }
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.app-page { .app-page {
width: 100vw; width: 100vw;
min-height: 100vh; min-height: 100vh;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
background-color: #fafafd; background-color: #fafafd;
} }
.loading-wrap { .loading-wrap {
padding: 24rpx; padding: 24rpx;
} }
.list-empty { .list-empty {
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
} }
.statistics { .statistics {
background-color: #ffffff; background-color: #ffffff;
} }
.e-timeline { .e-timeline {
::v-deep { ::v-deep {
.tm-timeline-item>view:first-child { .tm-timeline-item > view:first-child {
width: 110rpx !important; width: 110rpx !important;
} }
.tm-timeline-item-left { .tm-timeline-item-left {
max-width: 580rpx !important; max-width: 580rpx !important;
width: 100% !important; width: 100% !important;
} }
} }
} }
.tm-timeline { .tm-timeline {
.tm-timeline-item { .tm-timeline-item {
.tm-timeline-item-left, .tm-timeline-item-left,
.tm-timeline-item-right { .tm-timeline-item-right {
width: 200rpx; width: 200rpx;
flex-shrink: 0; flex-shrink: 0;
} }
.tm-timeline-item-content { .tm-timeline-item-content {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: flex-start; align-items: flex-start;
align-content: flex-start; align-content: flex-start;
} }
.tm-timeline-jidian { .tm-timeline-jidian {
margin: auto; margin: auto;
} }
&.tm-timeline-item--leftDir { &.tm-timeline-item--leftDir {
display: flex; display: flex;
flex-flow: row; flex-flow: row;
&.endright { &.endright {
justify-content: flex-end; justify-content: flex-end;
} }
.tm-timeline-item-left, .tm-timeline-item-left,
.tm-timeline-item-right { .tm-timeline-item-right {
width: auto; width: auto;
max-width: 400rpx; max-width: 400rpx;
} }
.tm-timeline-item-boder { .tm-timeline-item-boder {
height: 100%; height: 100%;
width: 1px; width: 1px;
margin: auto; margin: auto;
} }
.tm-timeline-jidian { .tm-timeline-jidian {
position: relative; position: relative;
margin: auto; margin: auto;
z-index: 2; z-index: 2;
} }
.tm-timeline-item-content { .tm-timeline-item-content {
display: flex; display: flex;
justify-content: flex-start; justify-content: flex-start;
align-items: flex-start; align-items: flex-start;
align-content: flex-start; align-content: flex-start;
} }
} }
} }
} }
.post { .post {
width: 560rpx; width: 560rpx;
border-radius: 12rpx; border-radius: 12rpx;
background-color: #fff; background-color: #fff;
&.lr_image_text {} &.lr_image_text {
}
&.lr_text_image { &.lr_text_image {
.post-thumbnail { .post-thumbnail {
order: 2; order: 2;
} }
.post-info { .post-info {
order: 1; order: 1;
padding-left: 0; padding-left: 0;
padding-right: 24rpx; padding-right: 24rpx;
} }
} }
&.tb_image_text { &.tb_image_text {
flex-direction: column; flex-direction: column;
.post-thumbnail { .post-thumbnail {
width: 100%; width: 100%;
height: 220rpx; height: 220rpx;
} }
.post-info { .post-info {
width: 100%; width: 100%;
padding-left: 0; padding-left: 0;
&_title { &_title {
margin-top: 12rpx; margin-top: 12rpx;
} }
&_time { &_time {
.iconfont { .iconfont {
display: none; display: none;
} }
.time-label { .time-label {
display: inline-block; display: inline-block;
} }
} }
} }
} }
&.tb_text_image { &.tb_text_image {
flex-direction: column; flex-direction: column;
.post-thumbnail { .post-thumbnail {
order: 2; order: 2;
width: 100%; width: 100%;
height: 220rpx; height: 220rpx;
margin-top: 12rpx; margin-top: 12rpx;
} }
.post-info { .post-info {
order: 1; order: 1;
width: 100%; width: 100%;
padding-left: 0; padding-left: 0;
&_time { &_time {
.iconfont { .iconfont {
display: none; display: none;
} }
.time-label { .time-label {
display: inline-block; display: inline-block;
} }
} }
} }
} }
&.only_text { &.only_text {
.post-info { .post-info {
padding: 6rpx; padding: 6rpx;
&_time { &_time {
margin-top: 20rpx; margin-top: 20rpx;
.iconfont { .iconfont {
display: none; display: none;
} }
.time-label { .time-label {
display: inline-block; display: inline-block;
} }
} }
} }
.post-thumbnail { .post-thumbnail {
display: none; display: none;
} }
} }
} }
.post-thumbnail { .post-thumbnail {
border-radius: 6rpx; border-radius: 6rpx;
width: 200rpx; width: 200rpx;
height: 170rpx; height: 170rpx;
} }
.post-info { .post-info {
width: 0; width: 0;
flex-grow: 1; flex-grow: 1;
&_title { &_title {
color: #303133; color: #303133;
font-size: 28rpx; font-size: 28rpx;
font-weight: bold; font-weight: bold;
} }
&_summary { &_summary {
display: -webkit-box; display: -webkit-box;
line-height: 1.6; line-height: 1.6;
} }
&_time { &_time {
.time-label { .time-label {
display: none; display: none;
} }
} }
} }
</style> </style>
+71 -91
Zobrazit soubor
@@ -65,12 +65,10 @@
<view v-if="originalURL" class="mt-18 category-type original-url"> <view v-if="originalURL" class="mt-18 category-type original-url">
<view class="original-url_left text-weight-b">原文</view> <view class="original-url_left text-weight-b">原文</view>
<view class="original-url_right text-grey"> <view class="original-url_right text-grey">
<text class="original-url_right__link" <text class="original-url_right__link" @click.stop="fnToOriginal(originalURL)">{{ originalURL }}
@click.stop="fnToOriginal(originalURL)">{{ originalURL }}
</text> </text>
<text class="original-url_right__btn" @click.stop="fnToOriginal(originalURL)">阅读原文 <text class="original-url_right__btn" @click.stop="fnToOriginal(originalURL)">阅读原文
<text <text class="iconfont icon-angle-right ml-5 text-size-s"></text>
class="iconfont icon-angle-right ml-5 text-size-s"></text>
</text> </text>
</view> </view>
</view> </view>
@@ -82,8 +80,8 @@
<mp-html class="evan-markdown" lazy-load :domain="markdownConfig.domain" <mp-html class="evan-markdown" lazy-load :domain="markdownConfig.domain"
:loading-img="markdownConfig.loadingGif" :scroll-table="true" :selectable="true" :loading-img="markdownConfig.loadingGif" :scroll-table="true" :selectable="true"
:tag-style="markdownConfig.tagStyle" :container-style="markdownConfig.containStyle" :tag-style="markdownConfig.tagStyle" :container-style="markdownConfig.containStyle"
:content="result.content.raw" :markdown="true" :showLineNumber="true" :content="result.content.raw" :markdown="true" :showLineNumber="true" :showLanguageName="true"
:showLanguageName="true" :copyByLongPress="true"/> :copyByLongPress="true"/>
<tm-more v-if="showValidVisitMore" :disabled="true" :maxHeight="1" :isRemovBar="true" <tm-more v-if="showValidVisitMore" :disabled="true" :maxHeight="1" :isRemovBar="true"
@click="showValidVisitMorePop()"> @click="showValidVisitMorePop()">
<view class="text-size-n pa-24"> <view class="text-size-n pa-24">
@@ -97,44 +95,32 @@
</template> </template>
</tm-more> </tm-more>
</view> </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-title text-weight-b">版权声明</view>
<view <view
class="copyright-content mt-12 grey-lighten-5 text-grey-darken-2 round-4 pt-12 pb-12 pl-24 pr-24 "> 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 "> <view v-if="postDetailConfig.copyrightAuthor" class="copyright-text text-size-s ">
版权归属{{ copyright.author }} 版权归属{{ postDetailConfig.copyrightAuthor }}
</view> </view>
<view v-if="copyright.description" class="copyright-text text-size-s mt-12"> <view v-if="postDetailConfig.copyrightDesc" class="copyright-text text-size-s mt-12">
版权说明{{ copyright.description }} 版权说明{{ postDetailConfig.copyrightDesc }}
</view> </view>
<view v-if="copyright.violation" class="copyright-text text-size-s mt-12 text-red"> <view v-if="postDetailConfig.copyrightViolation" class="copyright-text text-size-s mt-12 text-red">
侵权处理{{ copyright.violation }} 侵权处理{{ postDetailConfig.copyrightViolation }}
</view> </view>
</view> </view>
</view> </view>
<!-- 评论展示区域 --> <!-- 评论展示区域 -->
<view v-if="result" class="comment-wrap bg-white mt-24 pa-24 round-4"> <block v-if="postDetailConfig && postDetailConfig.showComment">
<commentList :disallowComment="!result.spec.allowComment" :postName="result.metadata.name" <view v-if="result" class="comment-wrap bg-white mt-24 pa-24 round-4">
:post="result" @on-comment-detail="fnOnShowCommentDetail" @on-loaded="fnOnCommentLoaded"> <commentList :disallowComment="!result.spec.allowComment" :postName="result.metadata.name"
</commentList> :post="result" @on-comment-detail="fnOnShowCommentDetail" @on-loaded="fnOnCommentLoaded">
</view> </commentList>
</view>
</block>
</view> </view>
<!-- 弹幕效果 --> <!-- 弹幕效果 -->
@@ -238,9 +224,7 @@ import commentItem from '@/components/comment-item/comment-item.vue';
import rCanvas from '@/components/r-canvas/r-canvas.vue'; import rCanvas from '@/components/r-canvas/r-canvas.vue';
import barrage from '@/components/barrage/barrage.vue'; import barrage from '@/components/barrage/barrage.vue';
import { import {haloWxShareMixin} from '@/common/mixins/wxshare.mixin.js';
haloWxShareMixin
} from '@/common/mixins/wxshare.mixin.js';
export default { export default {
components: { components: {
@@ -311,8 +295,11 @@ export default {
}; };
}, },
computed: { computed: {
copyright() { haloConfigs() {
return getApp().globalData.copyright; return this.$tm.vx.getters().getConfigs;
},
postDetailConfig() {
return this.$tm.vx.getters().getConfigs.postDetailConfig;
}, },
calcUrl() { calcUrl() {
return url => { return url => {
@@ -324,10 +311,11 @@ export default {
}, },
// 获取博主信息 // 获取博主信息
bloggerInfo() { 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); blogger.avatar = this.$utils.checkAvatarUrl(blogger.avatar, true);
return blogger; return blogger;
}, },
// 原文链接:个人资质=可以打开公众号文章;非个人:任意链接地址(需在小程序后台配置) // 原文链接:个人资质=可以打开公众号文章;非个人:任意链接地址(需在小程序后台配置)
originalURL() { originalURL() {
if ('unihalo_originalURL' in this.result?.metadata?.annotations) { if ('unihalo_originalURL' in this.result?.metadata?.annotations) {
@@ -357,14 +345,15 @@ export default {
this.result = res; this.result = res;
const openid = uni.getStorageSync('openid'); const openid = uni.getStorageSync('openid');
if (openid == '' || openid == null) { if (openid === '' || openid === null) {
this.fnGetOpenid(); this.fnGetOpenid();
} }
const visitFlag = uni.getStorageSync('visit_' + this.result?.metadata?.name); const visitFlag = uni.getStorageSync('visit_' + this.result?.metadata?.name);
if (!visitFlag) { if (!visitFlag) {
const annotationsMap = res?.metadata?.annotations; const annotationsMap = res?.metadata?.annotations;
if (('restrictReadEnable' in annotationsMap) && annotationsMap.restrictReadEnable === 'true') { if (('restrictReadEnable' in annotationsMap) && annotationsMap.restrictReadEnable ===
'true') {
this.visitType = 1; this.visitType = 1;
this.showValidVisitMorePop(); this.showValidVisitMorePop();
} else if ('unihalo_useVisitMorePwd' in annotationsMap) { } else if ('unihalo_useVisitMorePwd' in annotationsMap) {
@@ -375,9 +364,10 @@ export default {
this.visitType = 3; this.visitType = 3;
this.visitPwd = annotationsMap.unihalo_useVisitPwd; this.visitPwd = annotationsMap.unihalo_useVisitPwd;
this.showValidVisitPop(); this.showValidVisitPop();
} else if (('restrictReadEnable' in annotationsMap) && annotationsMap.restrictReadEnable === 'password') { } else if (('restrictReadEnable' in annotationsMap) && annotationsMap
this.visitType = 4; .restrictReadEnable === 'password') {
this.showValidVisitPop(); this.visitType = 4;
this.showValidVisitPop();
} else { } else {
this.visitType = 0; this.visitType = 0;
this.showValidVisitMore = false; this.showValidVisitMore = false;
@@ -425,6 +415,9 @@ export default {
}, },
fnToComment() { fnToComment() {
if (!this.haloConfig.basicConfig.postDetailConfig.showComment) {
return;
}
if (!this.result.spec.allowComment) { if (!this.result.spec.allowComment) {
return uni.$tm.toast('文章已开启禁止评论!'); return uni.$tm.toast('文章已开启禁止评论!');
} }
@@ -615,7 +608,7 @@ export default {
// 小程序信息 // 小程序信息
await this.$refs.rCanvas await this.$refs.rCanvas
.drawImage({ .drawImage({
url: this.$haloConfig.miniCodeImageUrl, url: this.haloConfig.imagesConfig.miniCodeImageUrl,
x: 20, x: 20,
y: 360, y: 360,
w: 80, w: 80,
@@ -681,23 +674,6 @@ export default {
// #ifdef MP-WEIXIN // #ifdef MP-WEIXIN
uni.$tm.toast('点击右上角分享给好友!'); uni.$tm.toast('点击右上角分享给好友!');
// #endif // #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) { fnOnShowCommentDetail(data) {
const { const {
@@ -723,7 +699,7 @@ export default {
this.commentDetail.list = res.items; this.commentDetail.list = res.items;
}) })
.catch(err => { .catch(err => {
console.log('getPostChildrenCommentList err', error); console.log('getPostChildrenCommentList err', err);
this.commentDetail.loading = 'error'; this.commentDetail.loading = 'error';
}); });
}, },
@@ -742,12 +718,12 @@ export default {
const _list = []; const _list = [];
const _handleData = list => { const _handleData = list => {
return new Promise(resolve => { return new Promise(resolve => {
if (list.length == 0) { if (list.length === 0) {
resolve(); resolve();
} else { } else {
list.forEach(item => { list.forEach(item => {
_list.push(item); _list.push(item);
if (item.replies && item.replies.length != 0) { if (item.replies && item.replies.length !== 0) {
_handleData(item.replies.items); _handleData(item.replies.items);
} }
resolve(); resolve();
@@ -833,6 +809,7 @@ export default {
}, },
// 获取openid // 获取openid
fnGetOpenid() { fnGetOpenid() {
// #ifdef MP-WEIXIN
uni.login({ uni.login({
provider: 'weixin', provider: 'weixin',
success: function (loginRes) { success: function (loginRes) {
@@ -844,6 +821,7 @@ export default {
} }
} }
}) })
// #endif
}, },
// 隐藏内容 // 隐藏内容
fnHideContent() { fnHideContent() {
@@ -872,18 +850,19 @@ export default {
case 0: case 0:
return; return;
case 1: case 1:
this.$httpApi.v2.checkPostVerifyCode(this.validVisitModal.value, this.result?.metadata?.name).then(res => { this.$httpApi.v2.checkPostVerifyCode(this.validVisitModal.value, this.result?.metadata?.name).then(
if (res.code === 200) { res => {
uni.setStorageSync('visit_' + this.result?.metadata?.name, true) if (res.code === 200) {
this.closeAllPop(); uni.setStorageSync('visit_' + this.result?.metadata?.name, true)
this.fnGetData(); this.closeAllPop();
} else { this.fnGetData();
uni.showToast({ } else {
title: '密码错误', uni.showToast({
icon: 'none' title: '密码错误',
}); icon: 'none'
} });
}).catch(err => { }
}).catch(err => {
console.log(err); console.log(err);
}); });
return; return;
@@ -900,22 +879,23 @@ export default {
}); });
} }
return; return;
case 4: case 4:
this.$httpApi.v2.checkPostPasswordAccess(this.validVisitModal.value, this.result?.metadata?.name).then(res => { this.$httpApi.v2.checkPostPasswordAccess(this.validVisitModal.value, this.result?.metadata?.name)
if (res.code === 200) { .then(res => {
uni.setStorageSync('visit_' + this.result?.metadata?.name, true) if (res.code === 200) {
this.closeAllPop(); uni.setStorageSync('visit_' + this.result?.metadata?.name, true)
this.fnGetData(); this.closeAllPop();
} else { this.fnGetData();
uni.showToast({ } else {
title: '密码错误', uni.showToast({
icon: 'none' title: '密码错误',
icon: 'none'
});
}
}).catch(err => {
console.log(err);
}); });
} return;
}).catch(err => {
console.log(err);
});
return;
default: default:
return; return;
} }
+198 -198
Zobrazit soubor
@@ -1,214 +1,214 @@
<template> <template>
<view class="app-page" :class="{ 'is-balck grey-darken-6': isBlackTheme }"> <view class="app-page" :class="{ 'is-balck grey-darken-6': isBlackTheme }">
<!-- 顶部切换 --> <!-- 顶部切换 -->
<view class="e-fixed shadow-2"> <view class="e-fixed shadow-2">
<tm-search v-model="queryParams.keyword" :round="24" :shadow="0" color="light-blue" <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> 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" <tm-tabs v-if="false" color="light-blue" :shadow="0" v-model="tab.activeIndex" :list="tab.list"
align="center" @change="fnOnTabChange"></tm-tabs> align="center" @change="fnOnTabChange"></tm-tabs>
</view> </view>
<!-- 占位区域 --> <!-- 占位区域 -->
<view style="width: 100vw;height: 100rpx;"></view> <view style="width: 100vw;height: 100rpx;"></view>
<!-- 加载区域 --> <!-- 加载区域 -->
<view v-if="loading != 'success'" class="loading-wrap pa-24"> <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>
<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>
<!-- 内容区域 --> <!-- 内容区域 -->
<view v-else class="content"> <view v-else class="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">
<!-- 空布局 --> <!-- 空布局 -->
<tm-empty v-if="!queryParams.keyword" icon="icon-shiliangzhinengduixiang-" label="请输入关键词搜索"></tm-empty> <tm-empty v-if="!queryParams.keyword" icon="icon-shiliangzhinengduixiang-" label="请输入关键词搜索"></tm-empty>
<tm-empty v-else icon="icon-shiliangzhinengduixiang-" <tm-empty v-else icon="icon-shiliangzhinengduixiang-"
:label="`未搜到 ${queryParams.keyword} 相关文章`"></tm-empty> :label="`未搜到 ${queryParams.keyword} 相关文章`"></tm-empty>
</view> </view>
<block v-else> <block v-else>
<!-- 文章卡片 --> <!-- 文章卡片 -->
<tm-translate v-for="(article, index) in dataList" :key="article.name" animation-name="fadeUp" <tm-translate v-for="(article, index) in dataList" :key="article.name" animation-name="fadeUp"
:wait="calcAniWait(index)"> :wait="calcAniWait(index)">
<view class="article-card" @click="fnToArticleDetail(article)"> <view class="article-card" @click="fnToArticleDetail(article)">
<rich-text style="font-size: 32rpx;font-weight: bold;color: #333;" <rich-text style="font-size: 32rpx;font-weight: bold;color: #333;"
:nodes="article.title"> </rich-text> :nodes="article.title"></rich-text>
<rich-text style="font-size: 28rpx;margin-top: 16rpx;color: #555;" <rich-text style="font-size: 28rpx;margin-top: 16rpx;color: #555;"
:nodes="article.content"> </rich-text> :nodes="article.content"></rich-text>
<text style="font-size: 24rpx;margin-top: 24rpx;color:#888"> <text style="font-size: 24rpx;margin-top: 24rpx;color:#888">
发布日期{{ { d: article.publishTimestamp, f: 'yyyy年MM月dd日' } | formatTime }} 发布日期{{ {d: article.publishTimestamp, f: 'yyyy年MM月dd日'} | formatTime }}
</text> </text>
</view> </view>
</tm-translate> </tm-translate>
<tm-flotbutton @click="fnToTopPage" size="m" color="light-blue" icon="icon-angle-up"></tm-flotbutton> <tm-flotbutton @click="fnToTopPage" size="m" color="light-blue" icon="icon-angle-up"></tm-flotbutton>
<view class="load-text">{{ loadMoreText }}</view> <view class="load-text">{{ loadMoreText }}</view>
</block> </block>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue'; import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmSearch from '@/tm-vuetify/components/tm-search/tm-search.vue'; import tmSearch from '@/tm-vuetify/components/tm-search/tm-search.vue';
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue'; import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
import tmTabs from '@/tm-vuetify/components/tm-tabs/tm-tabs.vue'; import tmTabs from '@/tm-vuetify/components/tm-tabs/tm-tabs.vue';
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue'; import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue'; import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
export default { export default {
components: { components: {
tmSkeleton, tmSkeleton,
tmSearch, tmSearch,
tmTranslate, tmTranslate,
tmTabs, tmTabs,
tmFlotbutton, tmFlotbutton,
tmEmpty tmEmpty
}, },
data() { data() {
return { return {
isBlackTheme: false, isBlackTheme: false,
loading: 'loading', loading: 'loading',
tab: { tab: {
activeIndex: 0, activeIndex: 0,
list: ['全部', '最新文章', '热门文章', '最近更新', '最多点赞'] list: ['全部', '最新文章', '热门文章', '最近更新', '最多点赞']
}, },
queryParams: { queryParams: {
keyword: "", keyword: "",
limit: 5, limit: 5,
highlightPreTag: "<text>", highlightPreTag: "<text>",
highlightPostTag: "</text>" highlightPostTag: "</text>"
}, },
cache: { cache: {
dataList: [], dataList: [],
total: 0 total: 0
}, },
hasNext: false, hasNext: false,
isLoadMore: false, isLoadMore: false,
loadMoreText: '加载中...', loadMoreText: '加载中...',
dataList: [] dataList: []
}; };
}, },
onLoad() { onLoad() {
this.fnSetPageTitle('文章列表'); this.fnSetPageTitle('文章列表');
}, },
created() { created() {
if (!this.queryParams.keyword) { if (!this.queryParams.keyword) {
this.loading = 'success' this.loading = 'success'
} else { } else {
this.fnGetData(); this.fnGetData();
} }
}, },
onPullDownRefresh() { onPullDownRefresh() {
this.fnResetSetAniWaitIndex(); this.fnResetSetAniWaitIndex();
this.isLoadMore = false; this.isLoadMore = false;
this.fnGetData(); this.fnGetData();
}, },
methods: { methods: {
fnOnTabChange(index) { fnOnTabChange(index) {
this.fnResetSetAniWaitIndex(); this.fnResetSetAniWaitIndex();
this.dataList = []; this.dataList = [];
const _sorts = { const _sorts = {
0: '', 0: '',
1: 'topPriority,createTime,desc', 1: 'topPriority,createTime,desc',
2: 'topPriority,visits,desc', 2: 'topPriority,visits,desc',
3: 'topPriority,updateTime,desc', 3: 'topPriority,updateTime,desc',
4: 'topPriority,likes,desc' 4: 'topPriority,likes,desc'
}; };
this.queryParams.sort = _sorts[index]; this.queryParams.sort = _sorts[index];
this.dataList = []; this.dataList = [];
this.fnToTopPage(); this.fnToTopPage();
this.fnGetData(); this.fnGetData();
}, },
fnOnSearch() { fnOnSearch() {
this.fnResetSetAniWaitIndex(); this.fnResetSetAniWaitIndex();
this.isLoadMore = false; this.isLoadMore = false;
if (!this.queryParams.keyword) { if (!this.queryParams.keyword) {
this.dataList = [] this.dataList = []
} else { } else {
this.fnGetData(); this.fnGetData();
} }
}, },
fnGetData() { fnGetData() {
// uni.showLoading({ // uni.showLoading({
// mask: true, // mask: true,
// title: '加载中...' // title: '加载中...'
// }); // });
// 设置状态为加载中 // 设置状态为加载中
if (!this.isLoadMore) { if (!this.isLoadMore) {
this.loading = 'loading'; this.loading = 'loading';
} }
this.loadMoreText = '加载中...'; this.loadMoreText = '加载中...';
this.$httpApi.v2 this.$httpApi.v2
.getPostListByKeyword(this.queryParams) .getPostListByKeyword(this.queryParams)
.then(res => { .then(res => {
console.log('请求结果:'); console.log('请求结果:');
console.log(res); console.log(res);
this.loading = 'success'; this.loading = 'success';
this.loadMoreText = res.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~'; this.loadMoreText = res.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
this.hasNext = res.hasNext; this.hasNext = res.hasNext;
if (this.isLoadMore) { if (this.isLoadMore) {
this.dataList = this.dataList.concat(res.hits); this.dataList = this.dataList.concat(res.hits);
} else { } else {
this.dataList = res.hits; this.dataList = res.hits;
} }
}) })
.catch(err => { .catch(err => {
console.error(err); console.error(err);
this.loading = 'error'; this.loading = 'error';
this.loadMoreText = '加载失败,请下拉刷新!'; this.loadMoreText = '加载失败,请下拉刷新!';
}) })
.finally(() => { .finally(() => {
setTimeout(() => { setTimeout(() => {
uni.hideLoading(); uni.hideLoading();
uni.stopPullDownRefresh(); uni.stopPullDownRefresh();
}, 800); }, 800);
}); });
}, },
//跳转文章详情 //跳转文章详情
fnToArticleDetail(article) { fnToArticleDetail(article) {
uni.navigateTo({ uni.navigateTo({
url: '/pagesA/article-detail/article-detail?name=' + article.name, url: '/pagesA/article-detail/article-detail?name=' + article.name,
animationType: 'slide-in-right' animationType: 'slide-in-right'
}); });
} }
} }
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.app-page { .app-page {
width: 100vw; width: 100vw;
min-height: 100vh; min-height: 100vh;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
padding-bottom: 24rpx; padding-bottom: 24rpx;
background-color: #fafafd; background-color: #fafafd;
&.is-balck { &.is-balck {
background-color: #212121; background-color: #212121;
} }
} }
.content { .content {
padding-top: 24rpx; padding-top: 24rpx;
.content-empty { .content-empty {
height: 60vh; height: 60vh;
} }
} }
.article-card { .article-card {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
box-sizing: border-box; box-sizing: border-box;
margin: 0 24rpx; margin: 0 24rpx;
padding: 24rpx; padding: 24rpx;
border-radius: 12rpx; border-radius: 12rpx;
background-color: #ffff; background-color: #ffff;
box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.03); box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.03);
overflow: hidden; overflow: hidden;
margin-bottom: 24rpx; margin-bottom: 24rpx;
} }
</style> </style>
+143 -138
Zobrazit soubor
@@ -1,149 +1,154 @@
<template> <template>
<view class="app-page"> <view class="app-page">
<view v-if="loading != 'success'" class="loading-wrap"> <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>
<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>
<block v-else> <block v-else>
<view class="empty" v-if="dataList.length == 0"><tm-empty icon="icon-shiliangzhinengduixiang-" <view class="empty" v-if="dataList.length == 0">
label="该分类下暂无文章"></tm-empty></view> <tm-empty icon="icon-shiliangzhinengduixiang-"
<block v-else> label="该分类下暂无文章"></tm-empty>
<block v-for="(article, index) in dataList" :key="article.createTime"> </view>
<!-- 文章卡片 --> <block v-else>
<tm-translate animation-name="fadeUp" :wait="calcAniWait(index)"><article-card :article="article" <block v-for="(article, index) in dataList" :key="article.createTime">
@on-click="fnToArticleDetail"></article-card></tm-translate> <!-- 文章卡片 -->
</block> <tm-translate animation-name="fadeUp" :wait="calcAniWait(index)">
<view class="load-text">{{ loadMoreText }}</view> <article-card :article="article"
</block> @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> <tm-flotbutton @click="fnToTopPage" color="light-blue" size="m" icon="icon-angle-up"></tm-flotbutton>
</block> </block>
</view> </view>
</template> </template>
<script> <script>
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue'; import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue'; import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue'; import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue'; import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
import ArticleCard from '@/components/article-card/article-card.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: ''
};
},
onLoad(e) { export default {
this.name = e.name; components: {
this.pageTitle = e.title; tmSkeleton,
this.fnGetData(); tmTranslate,
}, tmFlotbutton,
onPullDownRefresh() { tmEmpty,
this.isLoadMore = false; ArticleCard
this.queryParams.page = 0; },
this.fnGetData(); data() {
}, return {
onReachBottom(e) { loading: 'loading',
if (this.hasNext) { queryParams: {
this.queryParams.page += 1; size: 10,
this.isLoadMore = true; page: 0
this.fnGetData(); },
} else { name: '',
uni.showToast({ pageTitle: '加载中...',
icon: 'none', hasNext: false,
title: '没有更多数据了' dataList: [],
}); isLoadMore: false,
} loadMoreText: ''
}, };
methods: { },
fnGetData() {
// uni.showLoading({ onLoad(e) {
// mask: true, this.name = e.name;
// title: '加载中...' this.pageTitle = e.title;
// }); this.fnGetData();
// 设置状态为加载中 },
if (!this.isLoadMore) { onPullDownRefresh() {
this.loading = 'loading'; this.isLoadMore = false;
} this.queryParams.page = 0;
this.loadMoreText = '加载中...'; this.fnGetData();
this.$httpApi.v2 },
.getCategoryPostList(this.name, this.queryParams) onReachBottom(e) {
.then(res => { if (this.hasNext) {
console.log("请求成功:", res) this.queryParams.page += 1;
this.fnSetPageTitle(`${this.pageTitle} (共${res.total}篇)`); this.isLoadMore = true;
this.hasNext = res.hasNext; this.fnGetData();
if (this.isLoadMore) { } else {
this.dataList = this.dataList.concat(res.items); uni.showToast({
} else { icon: 'none',
this.dataList = res.items; title: '没有更多数据了'
} });
this.loadMoreText = res.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~'; }
setTimeout(() => { },
this.loading = 'success'; methods: {
}, 500); fnGetData() {
}) // uni.showLoading({
.catch(err => { // mask: true,
console.error(err); // title: '加载中...'
this.loading = 'error'; // });
this.loadMoreText = '加载失败,请下拉刷新!'; // 设置状态为加载中
}) if (!this.isLoadMore) {
.finally(() => { this.loading = 'loading';
setTimeout(() => { }
uni.hideLoading(); this.loadMoreText = '加载中...';
uni.stopPullDownRefresh(); this.$httpApi.v2
}, 500); .getCategoryPostList(this.name, this.queryParams)
}); .then(res => {
}, console.log("请求成功:", res)
//跳转文章详情 this.fnSetPageTitle(`${this.pageTitle} (共${res.total}篇)`);
fnToArticleDetail(article) { this.hasNext = res.hasNext;
uni.navigateTo({ if (this.isLoadMore) {
url: '/pagesA/article-detail/article-detail?name=' + article.metadata.name, this.dataList = this.dataList.concat(res.items);
animationType: 'slide-in-right' } 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> </script>
<style lang="scss"> <style lang="scss">
.app-page { .app-page {
width: 100vw; width: 100vw;
min-height: 100vh; min-height: 100vh;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
padding: 24rpx 0; padding: 24rpx 0;
background-color: #fafafd; background-color: #fafafd;
} }
.loading-wrap { .loading-wrap {
padding: 0 24rpx; padding: 0 24rpx;
min-height: 100vh; min-height: 100vh;
} }
.empty { .empty {
height: 60vh; height: 60vh;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
</style> </style>
+185 -181
Zobrazit soubor
@@ -1,197 +1,201 @@
<template> <template>
<view class="app-page pa-6"> <view class="app-page pa-6">
<view class="content pt-24 pb-24 round-4"> <view class="content pt-24 pb-24 round-4">
<!-- 表单区域 --> <!-- 表单区域 -->
<tm-form @submit="fnOnSubmit"> <tm-form @submit="fnOnSubmit">
<tm-input :auto-focus="true" name="content" :vertical="true" required :height="220" <tm-input :auto-focus="true" name="content" :vertical="true" required :height="220"
input-type="textarea" bg-color="grey-lighten-5" :maxlength="200" :borderBottom="false" input-type="textarea" bg-color="grey-lighten-5" :maxlength="200" :borderBottom="false"
placeholder="请输入内容,不超过200字符..." v-model="form.content"></tm-input> placeholder="请输入内容,不超过200字符..." v-model="form.content"></tm-input>
<tm-input name="author" align="right" required title="我的昵称" placeholder="请输入您的昵称..." <tm-input name="author" align="right" required title="我的昵称" placeholder="请输入您的昵称..."
v-model="form.author"></tm-input> v-model="form.author"></tm-input>
<tm-input name="avatar" align="right" required title="我的头像" placeholder="请输入您的头像..." <tm-input name="avatar" align="right" required title="我的头像" placeholder="请输入您的头像..."
v-model="form.avatar"></tm-input> v-model="form.avatar"></tm-input>
<tm-input name="email" align="right" required title="邮箱地址" placeholder="请输入您的邮箱..." <tm-input name="email" align="right" required title="邮箱地址" placeholder="请输入您的邮箱..."
v-model="form.email"></tm-input> v-model="form.email"></tm-input>
<tm-input name="authorUrl" align="right" required title="我的网站" placeholder="请输入您的网址..." <tm-input name="authorUrl" align="right" required title="我的网站" placeholder="请输入您的网址..."
v-model="form.authorUrl"></tm-input> v-model="form.authorUrl"></tm-input>
<view class="pa-24 pl-30 pr-30"><tm-button navtie-type="form" theme="bg-gradient-blue-accent" <view class="pa-24 pl-30 pr-30">
block>提交</tm-button></view> <tm-button navtie-type="form" theme="bg-gradient-blue-accent"
</tm-form> block>提交
</view> </tm-button>
</view> </view>
</tm-form>
</view>
</view>
</template> </template>
<script> <script>
import tmForm from '@/tm-vuetify/components/tm-form/tm-form.vue'; import tmForm from '@/tm-vuetify/components/tm-form/tm-form.vue';
import tmInput from '@/tm-vuetify/components/tm-input/tm-input.vue'; import tmInput from '@/tm-vuetify/components/tm-input/tm-input.vue';
import tmSwitch from '@/tm-vuetify/components/tm-switch/tm-switch.vue'; import tmSwitch from '@/tm-vuetify/components/tm-switch/tm-switch.vue';
import tmButton from '@/tm-vuetify/components/tm-button/tm-button.vue'; import tmButton from '@/tm-vuetify/components/tm-button/tm-button.vue';
export default { export default {
components: { components: {
tmForm, tmForm,
tmInput, tmInput,
tmSwitch, tmSwitch,
tmButton tmButton
}, },
data() { data() {
return { return {
isComment: true, isComment: true,
params: { params: {
postName: '', postName: '',
title: '', // 被回复的标题 type=user =用户名 否则为文章标题 title: '', // 被回复的标题 type=user =用户名 否则为文章标题
form: '', form: '',
formPage: '', // 来自哪个页面 formPage: '', // 来自哪个页面
type: 'post' // 来源文章/页面 还是用户 user=用户 type: 'post' // 来源文章/页面 还是用户 user=用户
}, },
form: { form: {
allowNotification: true, allowNotification: true,
author: '', // 作者 author: '', // 作者
avatar: '', avatar: '',
authorUrl: '', // 作者主页 authorUrl: '', // 作者主页
content: '', // 评论内容 content: '', // 评论内容
email: '', // 邮件 email: '', // 邮件
postName: "" postName: ""
} }
}; };
}, },
onLoad() { onLoad() {
this.params = this.$Route.query; this.params = this.$Route.query;
this.isComment = this.params.isComment; this.isComment = this.params.isComment;
this.form.postName = this.params.postName; this.form.postName = this.params.postName;
if (!this.isComment) { if (!this.isComment) {
this.fnSetPageTitle('回复用户:' + this.params.title); this.fnSetPageTitle('回复用户:' + this.params.title);
} else { } else {
this.fnSetPageTitle(this.params.title); this.fnSetPageTitle(this.params.title);
} }
try { try {
let visitor = uni.getStorageSync('Visitor') let visitor = uni.getStorageSync('Visitor')
if (visitor) { if (visitor) {
visitor = JSON.parse(visitor) visitor = JSON.parse(visitor)
this.form.author = visitor.author; this.form.author = visitor.author;
this.form.avatar = visitor.avatar; this.form.avatar = visitor.avatar;
this.form.email = visitor.email; this.form.email = visitor.email;
this.form.authorUrl = visitor.authorUrl; this.form.authorUrl = visitor.authorUrl;
} }
} catch (e) {} } catch (e) {
}, }
methods: { },
fnOnSubmit(e) { methods: {
if (e === false) { fnOnSubmit(e) {
return uni.$tm.toast('请检查所有的必填项是否填写完整!'); if (e === false) {
} return uni.$tm.toast('请检查所有的必填项是否填写完整!');
if (!this.form.email) { }
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.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地址!'); if (this.form.authorUrl && !uni.$tm.test.url(this.form.authorUrl)) {
} return uni.$tm.toast('请输入正确的Url地址!');
this.fnHandle(); }
}, this.fnHandle();
handleSetVisitor() { },
uni.setStorageSync('Visitor', JSON.stringify({ handleSetVisitor() {
author: this.form.author, uni.setStorageSync('Visitor', JSON.stringify({
avatar: this.form.avatar, author: this.form.author,
email: this.form.email, avatar: this.form.avatar,
authorUrl: this.form.authorUrl, email: this.form.email,
})) authorUrl: this.form.authorUrl,
}, }))
fnHandle() { },
uni.showLoading({ fnHandle() {
title: '正在提交...' uni.showLoading({
}); title: '正在提交...'
});
// 评论 // 评论
if (this.isComment) { if (this.isComment) {
const commentForm = { const commentForm = {
allowNotification: true, allowNotification: true,
raw: this.form.content, raw: this.form.content,
content: this.form.content, content: this.form.content,
owner: { owner: {
avatar: this.form.avatar, avatar: this.form.avatar,
displayName: this.form.author, displayName: this.form.author,
email: this.form.email, email: this.form.email,
website: this.form.authorUrl, website: this.form.authorUrl,
}, },
subjectRef: { subjectRef: {
group: "content.halo.run", group: "content.halo.run",
kind: "Post", kind: "Post",
name: this.form.postName, name: this.form.postName,
version: "v1alpha1", version: "v1alpha1",
} }
} }
this.$httpApi.v2.addPostComment(commentForm) this.$httpApi.v2.addPostComment(commentForm)
.then(res => { .then(res => {
uni.$tm.toast('提交成功!'); uni.$tm.toast('提交成功!');
// 更新评论者信息 // 更新评论者信息
this.handleSetVisitor(); this.handleSetVisitor();
setTimeout(() => { setTimeout(() => {
uni.navigateBack() uni.navigateBack()
}, 1500) }, 1500)
}) })
.catch(err => { .catch(err => {
uni.$tm.toast("评论失败"); uni.$tm.toast("评论失败");
}); });
return; return;
} }
// 回复 // 回复
const replyForm = { const replyForm = {
allowNotification: true, allowNotification: true,
raw: this.form.content, raw: this.form.content,
content: this.form.content, content: this.form.content,
owner: { owner: {
avatar: this.form.avatar, avatar: this.form.avatar,
displayName: this.form.author, displayName: this.form.author,
email: this.form.email, email: this.form.email,
website: this.form.authorUrl, website: this.form.authorUrl,
}, },
quoteReply: this.form.postName quoteReply: this.form.postName
} }
this.$httpApi.v2.addPostCommentReply(this.form.postName, replyForm) this.$httpApi.v2.addPostCommentReply(this.form.postName, replyForm)
.then(res => { .then(res => {
uni.$tm.toast('提交成功!'); uni.$tm.toast('提交成功!');
// 更新评论者信息 // 更新评论者信息
this.handleSetVisitor(); this.handleSetVisitor();
setTimeout(() => { setTimeout(() => {
uni.navigateBack() uni.navigateBack()
}, 1500) }, 1500)
}) })
.catch(err => { .catch(err => {
uni.$tm.toast("回复失败"); uni.$tm.toast("回复失败");
}); });
} }
} }
}; };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.app-page { .app-page {
width: 100vw; width: 100vw;
min-height: 100vh; min-height: 100vh;
box-sizing: border-box; box-sizing: border-box;
// background-color: #fafafd; // background-color: #fafafd;
background-color: #ffffff; background-color: #ffffff;
.content { .content {
overflow: hidden; overflow: hidden;
background-color: #fff; background-color: #fff;
// box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.05); // box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.05);
} }
} }
.poup-content { .poup-content {
width: 500rpx; width: 500rpx;
::v-deep { ::v-deep {
.slider_id { .slider_id {
width: 100% !important; width: 100% !important;
} }
} }
} }
</style> </style>
+251 -238
Zobrazit soubor
@@ -1,256 +1,269 @@
<template> <template>
<view class="app-page flex flex-col felx-center bg-white"> <view class="app-page flex flex-col felx-center bg-white">
<!-- 信息 --> <!-- 信息 -->
<view class="profile flex flex-col flex-center pa-36"> <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="avatar">
<view class="nickname mt-24 text-weight-b text-size-g">{{ bloggerInfo.nickname }}</view> <image class="avatar-img" :src="bloggerInfo.avatar" mode="aspectFill"></image>
<view class="desc mt-24 text-size-m text-grey-darken-3"> </view>
{{ bloggerInfo.description || '这个博主很懒,竟然没写介绍~' }} <view class="nickname mt-24 text-weight-b text-size-g">{{ bloggerInfo.nickname }}</view>
</view> <view class="desc mt-24 text-size-m text-grey-darken-3">
<!-- 联系图标 --> {{ bloggerInfo.description || '这个博主很懒,竟然没写介绍~' }}
<view class="mt-24 contact-icons"> </view>
<!-- 放全部似乎显得有点拥挤 --> <!-- 联系图标 -->
<!-- <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> --> <view class="mt-24 contact-icons">
<!-- 考虑放几个常用的就行 --> <!-- 放全部似乎显得有点拥挤 -->
<text class="halocoloricon halocoloricon-qq"></text> <!-- <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> -->
<!-- #ifndef MP-QQ --> <!-- 考虑放几个常用的就行 -->
<text class="ml-12 halocoloricon halocoloricon-wechat"></text> <text class="halocoloricon halocoloricon-qq"></text>
<!-- #endif --> <!-- #ifndef MP-QQ -->
<text class="ml-12 halocoloricon halocoloricon-GitHub"></text> <text class="ml-12 halocoloricon halocoloricon-wechat"></text>
<text class="ml-12 halocoloricon halocoloricon-gitee"></text> <!-- #endif -->
<text class="ml-12 halocoloricon halocoloricon-ic_email_round"></text> <text class="ml-12 halocoloricon halocoloricon-GitHub"></text>
</view> <text class="ml-12 halocoloricon halocoloricon-gitee"></text>
<view v-if="false" class="mt-24 "> <text class="ml-12 halocoloricon halocoloricon-ic_email_round"></text>
<tm-button theme="bg-gradient-light-blue-accent" size="m" openType="contact">在线客服联系</tm-button> </view>
<tm-button theme="bg-gradient-orange-accent" size="m" @click="fnOnToWeb">访问PC端博客</tm-button> </view>
</view> <!-- 社交联系方式列表 -->
</view> <view class="contact ma-50 mt-0 pt-12">
<!-- 社交联系方式列表 --> <block v-if="calcIsNotEmpty">
<view class="contact ma-50 mt-0 pt-12">
<block v-for="(item, index) in result" :key="index"> <block v-for="(item, index) in result" :key="index">
<view v-if="item.value" class="item mt-24 flex" @click="fnOnClick(item)"> <view v-if="item.value" class="item mt-24 flex" @click="fnOnClick(item)">
<view class="left"> <view class="left">
<text class="icon halocoloricon" :class="[item.icon]"></text> <text class="icon halocoloricon" :class="[item.icon]"></text>
<text class="name">{{ item.name }}</text> <text class="name">{{ item.name }}</text>
</view> </view>
<view class="right flex-1">{{ item.value }}</view> <view class="right flex-1">{{ item.value }}</view>
</view> </view>
</block> </block>
</view> </block>
</view> <view v-else class="mt-12 pt-12">
<tm-empty icon="icon-shiliangzhinengduixiang-" label="暂无联系方式"/>
</view>
</view>
</view>
</template> </template>
<script> <script>
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue'; import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmButton from '@/tm-vuetify/components/tm-button/tm-button.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 { export default {
components: { components: {
tmSkeleton, tmSkeleton,
tmButton tmButton,
}, tmEmpty
data() { },
return { data() {
loading: 'loading', return {
queryParams: { loading: 'loading',
size: 10, queryParams: {
page: 0 size: 10,
}, page: 0
result: [ },
{ result: [
key: 'qq', {
icon: 'halocoloricon-qq', key: 'qq',
name: '企鹅号', icon: 'halocoloricon-qq',
value: '' name: '企鹅号',
}, value: ''
{ },
key: 'wechat', {
icon: 'halocoloricon-wechat', key: 'wechat',
name: '微信号', icon: 'halocoloricon-wechat',
value: '' name: '微信号',
}, value: ''
{ },
key: 'github', {
icon: 'halocoloricon-GitHub', key: 'github',
name: 'Github', icon: 'halocoloricon-GitHub',
value: '' name: 'Github',
}, value: ''
{ },
key: 'gitee', {
icon: 'halocoloricon-gitee', key: 'gitee',
name: 'Gitee', icon: 'halocoloricon-gitee',
value: '' name: 'Gitee',
}, value: ''
{ },
key: 'bilibili', {
icon: 'halocoloricon-bilibili', key: 'bilibili',
name: 'Bilibili', icon: 'halocoloricon-bilibili',
value: '' name: 'Bilibili',
}, value: ''
{ },
key: 'csdn', {
icon: 'halocoloricon-csdn1', key: 'csdn',
name: 'CSDN', icon: 'halocoloricon-csdn1',
value: '' name: 'CSDN',
}, value: ''
{ },
key: 'blog', {
icon: 'halocoloricon-url-monitor', key: 'blog',
name: '博客地址', icon: 'halocoloricon-url-monitor',
value: '' name: '博客地址',
}, value: ''
{ },
key: 'juejin', {
icon: 'halocoloricon-juejin', key: 'juejin',
name: '掘金地址', icon: 'halocoloricon-juejin',
value: '' name: '掘金地址',
}, value: ''
},
{ {
key: 'weibo', key: 'weibo',
icon: 'halocoloricon-social-weibo', icon: 'halocoloricon-social-weibo',
name: '微博地址', name: '微博地址',
value: '' value: ''
}, },
{ {
key: 'email', key: 'email',
icon: 'halocoloricon-ic_email_round', icon: 'halocoloricon-ic_email_round',
name: '邮箱地址', name: '邮箱地址',
value: '' value: ''
} }
] ]
}; };
}, },
computed: { computed: {
// 获取博主信息 authorConfig() {
bloggerInfo() { return this.$tm.vx.getters().getConfigs.authorConfig;
let blogger = this.$tm.vx.getters().getBlogger; },
blogger.avatar = this.$utils.checkAvatarUrl(blogger.avatar, true); bloggerInfo() {
return blogger; let blogger = this.authorConfig.blogger;
} blogger.avatar = this.$utils.checkAvatarUrl(blogger.avatar, true);
}, return blogger;
onLoad() { },
this.fnSetPageTitle('联系博主'); socialConfig() {
}, return this.authorConfig.social
created() { },
this.fnGetData(); calcIsNotEmpty() {
}, return this.result.some((item) => item.value !== "");
methods: { }
fnGetData() { },
for (let key in this.$haloConfig.social) { onLoad() {
this.result.find(x => x.key == key).value = this.$haloConfig.social[key]; this.fnSetPageTitle('联系博主');
} },
}, created() {
fnOnToWeb() { this.fnGetData();
uni.navigateTo({ },
url: methods: {
'/pagesC/website/website?data=' + fnGetData() {
JSON.stringify({ for (let key in this.socialConfig) {
title: this.$haloConfig.title, this.result.find(x => x.key === key).value = this.socialConfig[key];
url: this.$haloConfig.social.blog }
}) },
}); fnOnClick(item) {
}, if (this.globalAppSettings.contact.isLinkCopy && this.$utils.checkIsUrl(item.value)) {
fnOnClick(item) { uni.navigateTo({
if (this.globalAppSettings.contact.isLinkCopy && this.$utils.checkIsUrl(item.value)) { url: '/pagesC/website/website?data=' +
uni.navigateTo({ JSON.stringify({
url: title: item.name,
'/pagesC/website/website?data=' + url: item.value
JSON.stringify({ })
title: item.name, });
url: item.value } else {
}) this.$utils.copyText(item.value, item.name + ' 已复制!');
}); }
} else { }
this.$utils.copyText(item.value, item.name + ' 已复制!'); }
}
}
}
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.app-page { .app-page {
width: 100vw; width: 100vw;
min-height: 100vh; min-height: 100vh;
box-sizing: border-box; box-sizing: border-box;
padding-top: 160rpx; 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 { .profile {
box-sizing: border-box; .avatar {
border-radius: 12rpx; width: 170rpx;
background-color: #fafafa; height: 170rpx;
// background-color: rgba(0, 0, 0, 0.05); position: relative;
// padding-bottom: 12rpx; box-sizing: border-box;
// border-bottom: 2rpx solid #eee; border-radius: 50%;
padding: 16rpx; border: 6rpx solid #fff;
.left { box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.07);
position: relative; overflow: hidden;
width: 140rpx;
display: flex; &-img {
align-items: center; width: 100%;
box-sizing: border-box; height: 100%;
// background-color: rgba(0, 0, 0, 0.03); }
border-radius: 12rpx 0 0 12rpx; }
&::after {
display: none; .nickname {
content: ':'; font-size: 38rpx;
position: absolute; }
right: 18rpx; }
top: 50%;
transform: translateY(-50%); .contact-icons {
font-size: 24rpx; .halocoloricon {
color: #666; font-size: 42rpx;
} }
.icon { }
font-size: 24rpx;
} .contact {
.name { box-sizing: border-box;
margin-left: 10rpx; border-top: 2rpx solid #f2f2f2;
color: #555;
font-size: 24rpx; .item {
} box-sizing: border-box;
} border-radius: 12rpx;
.right { background-color: #fafafa;
width: 0; // background-color: rgba(0, 0, 0, 0.05);
display: flex; // padding-bottom: 12rpx;
align-items: center; // border-bottom: 2rpx solid #eee;
flex-wrap: wrap; padding: 16rpx;
box-sizing: border-box;
word-wrap: break-word; .left {
word-break: break-all; position: relative;
font-size: 24rpx; width: 140rpx;
box-sizing: border-box; display: flex;
padding-left: 12rpx; 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> </style>
+39 -30
Zobrazit soubor
@@ -1,42 +1,51 @@
<template> <template>
<view class="app-page bg-white round-3 pa-46"> <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 style="min-height: 100%;" v-html="disclaimersContent"></view>
<view class="mt-32">1本博客属于个人非赢利性质的网站所有转载的文章都以遵循原作者的版权声明注明了文章来源</view>
<view class="mt-24">2如果原文没有版权声明按照目前互联网开放的原则本博客将在不通知作者的情况下转载文章</view> <!-- 静态写法 -->
<view class="mt-24">3如果原文明确注明禁止转载本博客将不会转载</view> <block v-if="false">
<view class="mt-24"> <view class="text-weight-b text-size-lg text-align-center"> 本博客免责声明 </view>
4如果本博客转载的文章不符合作者的版权声明或者作者不想让本博客转载您的文章请邮件告知 <view v-if="false" class="text-size-s text-align-center mt-12 text-grey-darken-1"> 博主{{ bloggerInfo.nickname }} </view>
<text class="text-bg-gradient-light-blue-accent ml-12 mr-12 " @click="$utils.copyText(bloggerInfo.email, '邮箱复制成功!')"> <view class="mt-32">1本博客属于个人非赢利性质的网站所有转载的文章都以遵循原作者的版权声明注明了文章来源</view>
<text class="iconfont icon-mail-fill text-size-m mr-6"></text> <view class="mt-24">2如果原文没有版权声明按照目前互联网开放的原则本博客将在不通知作者的情况下转载文章</view>
{{ bloggerInfo.email }} <view class="mt-24">3如果原文明确注明禁止转载本博客将不会转载</view>
</text> <view class="mt-24">
博主将会在第一时间删除相关信息 4如果本博客转载的文章不符合作者的版权声明或者作者不想让本博客转载您的文章请邮件告知
</view> <text class="text-bg-gradient-light-blue-accent ml-12 mr-12 ">
<view class="mt-24">5本博客转载文章仅为留作备份和知识点分享的目的</view> <text class="iconfont icon-mail-fill text-size-m mr-6"></text>
<view class="mt-24">6本博客将尽力确保所提供信息的准确性及可靠性但不保证信息的正确性和完整性且不对因信息的不正确或遗漏导致的任何损失或损害承担相关责任</view> studio@925i.cn
<view class="mt-24"> </text>
7本博客所发布转载的文章其版权均归原作者所有如其他自媒体网站或个人从本博客下载使用请在转载有关文章时务必尊重该文章的著作权保留本博客注明的原文来源或者自行去原文处复制版权声明并自负版权等法律责任 博主将会在第一时间删除相关信息
</view> </view>
<view class="mt-24">8本博客的所有原创文章皆可以任意转载但转载时务必请注明出处</view> <view class="mt-24">5本博客转载文章仅为留作备份和知识点分享的目的</view>
<view class="mt-24">9尊重原创知识共享</view> <view class="mt-24">
</view> 6本博客将尽力确保所提供信息的准确性及可靠性但不保证信息的正确性和完整性且不对因信息的不正确或遗漏导致的任何损失或损害承担相关责任
</view>
<view class="mt-24">
7本博客所发布转载的文章其版权均归原作者所有如其他自媒体网站或个人从本博客下载使用请在转载有关文章时务必尊重该文章的著作权保留本博客注明的原文来源或者自行去原文处复制版权声明并自负版权等法律责任
</view>
<view class="mt-24">8本博客的所有原创文章皆可以任意转载但转载时务必请注明出处</view>
<view class="mt-24">9尊重原创知识共享</view>
</block>
</view>
</template> </template>
<script> <script>
export default { export default {
computed: { computed: {
bloggerInfo() { disclaimersContent() {
return this.$tm.vx.getters().getBlogger; const configs = this.$tm.vx.getters().getAppConfigs;
} return configs.basicConfig.disclaimers.content
} }
}
}; };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.app-page { .app-page {
line-height: 1.65; line-height: 1.65;
font-size: 30rpx; font-size: 30rpx;
color: var(--main-text-color); color: var(--main-text-color);
} }
</style> </style>
+21 -13
Zobrazit soubor
@@ -26,8 +26,8 @@
</view> </view>
<view class="flex flex-col pl-30 info-detail"> <view class="flex flex-col pl-30 info-detail">
<view class="link-card_name text-size-l text-weight-b text-red"> <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" <tm-tags style="margin-right: 12rpx;margin-left: -2rpx;"
:shadow="0" size="s" model="fill"> color="bg-gradient-light-blue-lighten" :shadow="0" size="s" model="fill">
{{ link.spec.groupName || '暂未分组' }} {{ link.spec.groupName || '暂未分组' }}
</tm-tags> </tm-tags>
{{ link.spec.displayName }} {{ link.spec.displayName }}
@@ -120,7 +120,8 @@
<!-- 返回顶部 --> <!-- 返回顶部 -->
<tm-flotbutton color="light-blue" @click="fnToTopPage" size="m" icon="icon-angle-up"></tm-flotbutton> <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> @click="toSubmitLinkPage"></tm-flotbutton>
<!-- 详情弹窗 --> <!-- 详情弹窗 -->
<tm-poup v-model="detail.show" :width="640" height="auto" position="center" :round="6"> <tm-poup v-model="detail.show" :width="640" height="auto" position="center" :round="6">
@@ -152,7 +153,7 @@
<!-- 博客预览图 --> <!-- 博客预览图 -->
<view class="mt-24"> <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> mode="aspectFill"></tm-images>
</view> </view>
</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 tmImages from '@/tm-vuetify/components/tm-images/tm-images.vue';
import tmPoup from '@/tm-vuetify/components/tm-poup/tm-poup.vue'; import tmPoup from '@/tm-vuetify/components/tm-poup/tm-poup.vue';
import {GetRandomNumberByRange} from '@/utils/random.js'; import {GetRandomNumberByRange} from '@/utils/random.js';
export default { export default {
@@ -200,14 +200,25 @@ export default {
isLoadMore: false, isLoadMore: false,
loadMoreText: '', loadMoreText: '',
dataList: [], dataList: [],
cacheDataList: [] cacheDataList: [],
colors: [
'#39B449',
'#E44C41',
'#8698A2',
'#0080FE',
'#1CBCB4',
'#6638B5'
]
}; };
}, },
computed: { computed: {
caclSiteThumbnail(val) { haloPluginConfigs(){
return this.$tm.vx.getters().getConfigs.pluginConfig;
},
calcSiteThumbnail(val) {
return val => { return val => {
if (!val) return ''; if (!val) return '';
if (val.charAt(val.length - 1) != '/') { if (val.charAt(val.length - 1) !== '/') {
val = val + '/'; val = val + '/';
} }
return 'https://image.thum.io/get/width/1000/crop/800/' + val; return 'https://image.thum.io/get/width/1000/crop/800/' + val;
@@ -239,8 +250,8 @@ export default {
}, },
methods: { methods: {
fnRandomColor() { fnRandomColor() {
const _r = GetRandomNumberByRange(0, this.$haloConfig.colors.length - 1); const _r = GetRandomNumberByRange(0, this.colors.length - 1);
return this.$haloConfig.colors[_r]; return this.colors[_r];
}, },
fnGetData() { fnGetData() {
if (!this.isLoadMore) { if (!this.isLoadMore) {
@@ -259,9 +270,6 @@ export default {
return item; return item;
}) })
this.dataList = this.dataList.concat(list); this.dataList = this.dataList.concat(list);
// this.cacheDataList = this.cacheDataList.concat(list);
// this.dataList = this.handleGroup(this.cacheDataList).reverse();
setTimeout(() => { setTimeout(() => {
this.loading = 'success'; this.loading = 'success';
this.loadMoreText = res.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~'; this.loadMoreText = res.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
+123 -121
Zobrazit soubor
@@ -1,135 +1,137 @@
<template> <template>
<view class="app-page"> <view class="app-page">
<view v-if="loading != 'success'" class="loading-wrap pa-24"> <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>
<tm-skeleton model="listAvatr"></tm-skeleton> <tm-skeleton model="listAvatr"></tm-skeleton>
</view> </view>
<!-- 内容区域 --> <!-- 内容区域 -->
<view v-else class="app-page-content pa-24"> <view v-else class="app-page-content pa-24">
<view v-if="dataList.length == 0" class="content-empty flex flex-center"> <view v-if="dataList.length == 0" class="content-empty flex flex-center">
<!-- 空布局 --> <!-- 空布局 -->
<tm-empty icon="icon-shiliangzhinengduixiang-" label="博主还没有写任何日记"></tm-empty> <tm-empty icon="icon-shiliangzhinengduixiang-" label="博主还没有写任何日记"></tm-empty>
</view> </view>
<block v-else> <block v-else>
<block v-for="(journal, index) in dataList" :key="index"> <block v-for="(journal, index) in dataList" :key="index">
<tm-translate animation-name="fadeUp" :wait="calcAniWait(index)"> <tm-translate animation-name="fadeUp" :wait="calcAniWait(index)">
<!-- 日记卡片 --> <!-- 日记卡片 -->
<journal-card :journal="journal" :useLike="true"></journal-card> <journal-card :journal="journal" :useLike="true"></journal-card>
</tm-translate> </tm-translate>
</block> </block>
<tm-flotbutton @click="fnToTopPage" color="light-blue" size="m" icon="icon-angle-up"></tm-flotbutton> <tm-flotbutton @click="fnToTopPage" color="light-blue" size="m" icon="icon-angle-up"></tm-flotbutton>
<view class="load-text">{{ loadMoreText }}</view> <view class="load-text">{{ loadMoreText }}</view>
</block> </block>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
import MarkdownConfig from '@/common/markdown/markdown.config.js'; import MarkdownConfig from '@/common/markdown/markdown.config.js';
import mpHtml from '@/components/mp-html/components/mp-html/mp-html.vue'; import mpHtml from '@/components/mp-html/components/mp-html/mp-html.vue';
import journalCard from '@/components/journal-card/journal-card.vue'; import journalCard from '@/components/journal-card/journal-card.vue';
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue'; import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue'; import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue'; import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue'; import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
export default { export default {
components: { mpHtml, tmSkeleton, tmEmpty, tmTranslate, tmFlotbutton, journalCard }, components: {mpHtml, tmSkeleton, tmEmpty, tmTranslate, tmFlotbutton, journalCard},
data() { data() {
return { return {
loading: 'loading', loading: 'loading',
markdownConfig: MarkdownConfig, markdownConfig: MarkdownConfig,
queryParams: { queryParams: {
size: 10, size: 10,
page: 0 page: 0
}, },
dataList: [],
hasNext:false,
isLoadMore: false,
loadMoreText: '加载中...'
};
},
onLoad() { dataList: [],
this.fnSetPageTitle('个人日记'); hasNext: false,
}, isLoadMore: false,
created() { loadMoreText: '加载中...'
this.fnGetData(); };
}, },
onPullDownRefresh() {
this.isLoadMore = false; onLoad() {
this.queryParams.page = 0; this.fnSetPageTitle('个人日记');
this.fnGetData(); },
}, created() {
onReachBottom(e) { this.fnGetData();
if (this.hasNext) { },
this.queryParams.page += 1; onPullDownRefresh() {
this.isLoadMore = true; this.isLoadMore = false;
this.fnGetData(); this.queryParams.page = 0;
} else { this.fnGetData();
uni.showToast({ },
icon: 'none', onReachBottom(e) {
title: '没有更多数据了' if (this.hasNext) {
}); this.queryParams.page += 1;
} this.isLoadMore = true;
}, this.fnGetData();
methods: { } else {
fnGetData() { uni.showToast({
// uni.showLoading({ icon: 'none',
// mask: true, title: '没有更多数据了'
// title: '加载中...' });
// }); }
// 设置状态为加载中 },
if (!this.isLoadMore) { methods: {
this.loading = 'loading'; fnGetData() {
} // uni.showLoading({
this.loadMoreText = '加载中...'; // mask: true,
this.$httpApi // title: '加载中...'
.getJournals(this.queryParams) // });
.then(res => { // 设置状态为加载中
this.loading = 'success'; if (!this.isLoadMore) {
this.loadMoreText = res.data.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~'; this.loading = 'loading';
// 处理数据 }
this.result = res.data; this.loadMoreText = '加载中...';
if (this.isLoadMore) { this.$httpApi
this.dataList = this.dataList.concat(res.data.content); .getJournals(this.queryParams)
} else { .then(res => {
this.dataList = res.data.content; this.loading = 'success';
} this.loadMoreText = res.data.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
this.loading = 'success'; // 处理数据
}) this.result = res.data;
.catch(err => { if (this.isLoadMore) {
console.error(err); this.dataList = this.dataList.concat(res.data.content);
this.loading = 'error'; } else {
this.loadMoreText = '加载失败,请下拉刷新!'; this.dataList = res.data.content;
}) }
.finally(() => { this.loading = 'success';
setTimeout(() => { })
uni.hideLoading(); .catch(err => {
uni.stopPullDownRefresh(); console.error(err);
}, 500); this.loading = 'error';
}); this.loadMoreText = '加载失败,请下拉刷新!';
} })
} .finally(() => {
}; setTimeout(() => {
uni.hideLoading();
uni.stopPullDownRefresh();
}, 500);
});
}
}
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.app-page { .app-page {
width: 100vw; width: 100vw;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.loading-wrap {} .loading-wrap {
}
.app-page-content {} .app-page-content {
}
.content-empty { .content-empty {
height: 60vh; height: 60vh;
} }
</style> </style>
+340 -333
Zobrazit soubor
@@ -1,78 +1,69 @@
<template> <template>
<view class="app-page"> <view class="app-page">
<view v-if="loading != 'success'" class="loading-wrap"> <view v-if="loading !== 'success'" class="loading-wrap">
<view v-if="loading == 'loading'" class="loading"> <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="loading-icon flex flex-center">
<view class="loadig-text ">相册正在努力加载中啦~</view> <text class="e-loading-icon iconfont icon-loading"></text>
</view> </view>
<tm-empty v-else icon="icon-shiliangzhinengduixiang-" color="red" label="啊偶,加载失败了呢~"> <view class="loadig-text ">相册正在努力加载中啦~</view>
<tm-button theme="red" :shadow="0" size="m" @click="fnRefresh()">刷新试试</tm-button> </view>
</tm-empty> <tm-empty v-else icon="icon-shiliangzhinengduixiang-" color="red" label="啊偶,加载失败了呢~">
</view> <tm-button theme="red" :shadow="0" size="m" @click="fnRefresh()">刷新试试</tm-button>
<!-- 内容区域 --> </tm-empty>
<view v-else class="app-page-content"> </view>
<view v-if="dataList.length == 0" color="light-blue" class="content-empty flex flex-center"> <!-- 内容区域 -->
<tm-empty icon="icon-shiliangzhinengduixiang-" label="相册暂时还没有数据~"> <view v-else class="app-page-content">
<tm-button :shadow="0" size="m" theme="light-blue" @click="fnRefresh()">刷新试试</tm-button> <view v-if="dataList.length === 0" color="light-blue" class="content-empty flex flex-center">
</tm-empty> <tm-empty icon="icon-shiliangzhinengduixiang-" label="相册暂时还没有数据~">
</view> <tm-button :shadow="0" size="m" theme="light-blue" @click="fnRefresh()">刷新试试</tm-button>
<block v-else> </tm-empty>
<swiper </view>
class="swiper-album" <block v-else>
:current="swiperIndex" <swiper class="swiper-album" :current="swiperIndex" :acceleration="true" :circular="true"
:acceleration="true" :vertical="false" :indicator-dots="false" :autoplay="false" @change="fnOnChange">
:circular="true" <block v-for="(item, index) in dataList" :key="index">
:vertical="false" <swiper-item class="swiper-album-item">
:indicator-dots="false" <view class="scroll-wrap">
:autoplay="false" <view class="card">
@change="fnOnChange" <cache-image class="card-image" width="100%" height="46vh" radius="12rpx"
> :url="item.image" :fileMd5="item.image" mode="aspectFill"
<block v-for="(item, index) in dataList" :key="index"> @on-click="fnOnPreview(item)"></cache-image>
<swiper-item class="swiper-album-item"> <view v-if="item.spec.description" class="card-desc">{{ item.spec.description }}
<view class="scroll-wrap"> </view>
<view class="card"> <view v-else class="card-desc is-empty flex flex-col">
<cache-image <view class="text-grey-darken-1">该照片没有记录任何信息</view>
class="card-image" <view class="text-size-m mt-24 text-grey-darken-1">记录一下拍照的瞬间会更精彩哟</view>
width="100%" </view>
height="46vh" </view>
radius="12rpx" </view>
:url="item.image" </swiper-item>
:fileMd5="item.image" </block>
mode="aspectFill" </swiper>
@on-click="fnOnPreview(item)" <view class="tabbar">
></cache-image> <view class="pre" @click="fnChange(false)">
<view v-if="item.description" class="card-desc">{{ item.description }}</view> <text class="icon">
<view v-else class="card-desc is-empty flex flex-col"> <text class="iconfont icon-arrow-left"></text>
<view class="text-grey-darken-1">该照片没有记录任何信息</view> </text>
<view class="text-size-m mt-24 text-grey-darken-1">记录一下拍照的瞬间会更精彩哟</view> <text class="text">上一张</text>
</view> </view>
</view> <view class="refresh" @click="fnRefresh()">
</view> <text class="refresh-text">点击</text>
</swiper-item> <text class="refresh-heart iconfont icon-diagnose"></text>
</block> <text class="refresh-text">刷新</text>
</swiper> </view>
<view class="tabbar"> <view class="next" @click="fnChange(true)">
<view class="pre" @click="fnChange(false)"> <text class="text">下一张</text>
<text class="icon"><text class="iconfont icon-arrow-left"></text></text> <text class="icon">
<text class="text">上一张</text> <text class="iconfont icon-arrow-right"></text>
</view> </text>
<view class="refresh" @click="fnRefresh()"> </view>
<text class="refresh-text">点击</text> </view>
<text class="refresh-heart iconfont icon-diagnose"></text> </block>
<text class="refresh-text">刷新</text> </view>
</view> </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> </template>
<script> <script>
import LoveConfig from '@/config/love.config.js';
import throttle from '@/utils/throttle.js'; import throttle from '@/utils/throttle.js';
import tmButton from '@/tm-vuetify/components/tm-button/tm-button.vue'; import tmButton from '@/tm-vuetify/components/tm-button/tm-button.vue';
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.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'; import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
export default { export default {
components: { components: {
tmButton, tmButton,
tmFlotbutton, tmFlotbutton,
tmTranslate, tmTranslate,
tmEmpty tmEmpty
}, },
data() { data() {
return { return {
loading: 'loading', loading: 'loading',
loveConfig: LoveConfig, queryParams: {
queryParams: { size: 100,
size: 99, page: 1,
page: 0, group: ""
sort: 'takeTime', },
team: LoveConfig.albumKeyName result: {},
}, dataList: [],
result: {}, swiperIndex: 0,
dataList: [], tabbar: {
cache: { list: []
dataList: [], }
total: 0 };
}, },
swiperIndex: 0, computed: {
tabbar: { loveConfig() {
list: [] return this.$tm.vx.getters().getConfigs.loveConfig;
} }
}; },
}, watch: {
loveConfig: {
deep: true,
immediate: true,
handler(newVal, oldVal) {
this.fnGetData()
}
}
},
onLoad() {
this.fnSetPageTitle('恋爱相册');
},
onLoad() { onPullDownRefresh() {
this.fnSetPageTitle('恋爱相册'); this.fnRefresh();
}, },
created() {
this.fnGetData();
},
onPullDownRefresh() {
this.fnRefresh();
},
methods: { methods: {
fnRefresh() { fnRefresh() {
this.queryParams.page = 0; this.queryParams.page = 0;
this.fnGetData(); this.fnGetData();
}, },
fnGetData() { fnGetData() {
this.loading = 'loading'; this.loading = 'loading';
this.$httpApi this.queryParams.group = this.loveConfig.lovePhoto.groupName
.getPhotoListByPage(this.queryParams) console.log('this.loveConfig------------',this.loveConfig)
.then(res => { this.$httpApi.v2
if (res.status == 200) { .getPhotoListByGroupName(this.queryParams)
this.loading = 'success'; .then(res => {
if (res.data.content.length != 0) { console.log("相册 res", res)
const _list = res.data.content.map((item, index) => { this.loading = 'success';
item['image'] = this.$utils.checkImageUrl(item.thumbnail); this.dataList = res.items.map((item, index) => {
item['takeTime'] = this.$tm.dayjs(item['takeTime']).format('DD/MM/YYYY'); item['image'] = this.$utils.checkImageUrl(item.spec.cover);
return item; item['takeTime'] = this.$tm.dayjs(item.metadata.creationTimestamp).format(
}); 'DD/MM/YYYY');
this.dataList = _list; return item;
this.swiperIndex = 0; });
} this.swiperIndex = 0;
} else { })
this.loading = 'error'; .catch(err => {
uni.$tm.toast('加载失败,请下拉刷新重试!'); console.error(err);
} this.loading = 'error';
}) uni.$tm.toast('加载失败,请下拉刷新重试!');
.catch(err => { })
console.error(err); .finally(() => {
this.loading = 'error'; setTimeout(() => {
uni.$tm.toast('加载失败,请下拉刷新重试!'); uni.stopPullDownRefresh();
}) }, 200);
.finally(() => { });
setTimeout(() => { },
uni.stopPullDownRefresh();
}, 200); fnOnPreview(item) {
}); uni.previewImage({
}, current: item.image,
// 缓存数据 urls: this.dataList.map(x => x.image)
fnCacheDataList(dataList) { });
if (this.queryParams.page == 0) { },
this.cache.dataList = dataList; fnOnChange(e) {
} else { this.swiperIndex = e.detail.current;
this.cache.dataList = [...this.cache.dataList, ...dataList]; },
} fnChange(isNext) {
}, throttle(() => {
fnOnPreview(item) { if (isNext) {
uni.previewImage({ if (this.swiperIndex == this.dataList.length - 1) {
current: item.image, this.swiperIndex = 0;
urls: this.dataList.map(x => x.image) } else {
}); this.swiperIndex += 1;
}, }
fnOnChange(e) { } else {
this.swiperIndex = e.detail.current; if (this.swiperIndex == 0) {
}, this.swiperIndex = this.dataList.length - 1;
fnChange(isNext) { } else {
throttle(() => { this.swiperIndex -= 1;
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> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.app-page { .app-page {
width: 100vw; width: 100vw;
min-height: 100vh; min-height: 100vh;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
box-sizing: border-box; box-sizing: border-box;
padding: 24rpx 0; padding: 24rpx 0;
padding-bottom: 144rpx; padding-bottom: 144rpx;
background: linear-gradient( background: linear-gradient(-135deg,
-135deg, rgba(247, 149, 51, 0.1),
rgba(247, 149, 51, 0.1), rgba(243, 112, 85, 0.1) 15%,
rgba(243, 112, 85, 0.1) 15%, rgba(239, 78, 123, 0.1) 30%,
rgba(239, 78, 123, 0.1) 30%, rgba(161, 102, 171, 0.1) 44%,
rgba(161, 102, 171, 0.1) 44%, rgba(80, 115, 184, 0.1) 58%,
rgba(80, 115, 184, 0.1) 58%, rgba(16, 152, 173, 0.1) 72%,
rgba(16, 152, 173, 0.1) 72%, rgba(7, 179, 155, 0.1) 86%,
rgba(7, 179, 155, 0.1) 86%, rgba(109, 186, 130, 0.1));
rgba(109, 186, 130, 0.1)
);
} }
.app-page-content { .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 { .loading-wrap {
.tm-icons { width: 100vw;
margin-right: -20rpx; 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 { .e-loading-icon {
font-size: 120rpx; font-size: 120rpx;
// color: #f88ca2; // color: #f88ca2;
color: #56bbf9; color: #56bbf9;
} }
.loadig-text { .loadig-text {
margin-top: 28rpx; margin-top: 28rpx;
font-size: 28rpx; font-size: 28rpx;
// color: #f88ca2; // color: #f88ca2;
color: #56bbf9; color: #56bbf9;
} }
.content-empty { .content-empty {
width: 100%; width: 100%;
height: 60vh; height: 60vh;
} }
.swiper-album { .swiper-album {
width: 100vw; width: 100vw;
height: calc(100vh - 24rpx - 144rpx); height: calc(100vh - 24rpx - 144rpx);
} }
.swiper-album-item { .swiper-album-item {
height: 100%; height: 100%;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
box-sizing: border-box; box-sizing: border-box;
padding: 36rpx; padding: 36rpx;
/* #ifdef H5 */ /* #ifdef H5 */
padding-bottom: 110rpx; padding-bottom: 110rpx;
/* #endif */ /* #endif */
/* #ifndef H5 */ /* #ifndef H5 */
padding-bottom: 60rpx; padding-bottom: 60rpx;
/* #endif */ /* #endif */
} }
.scroll-wrap { .scroll-wrap {
width: 100%; width: 100%;
height: 100%; height: 100%;
box-sizing: border-box; box-sizing: border-box;
padding: 36rpx; padding: 36rpx;
background-color: #ffffff; background-color: #ffffff;
border-radius: 12rpx; border-radius: 12rpx;
box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.03); box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.03);
} }
.card { .card {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
width: 100%; width: 100%;
// height: 65vh; // height: 65vh;
height: 100%; height: 100%;
max-height: 100%; max-height: 100%;
border-radius: 12rpx; border-radius: 12rpx;
background-color: #ffffff; background-color: #ffffff;
box-sizing: border-box; box-sizing: border-box;
// box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.03); // box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.03);
overflow: hidden; overflow: hidden;
overflow-y: auto; overflow-y: auto;
::v-deep {
.cache-image { ::v-deep {
height: initial !important; .cache-image {
} height: initial !important;
} }
&-image { }
width: 100%;
height: initial !important; &-image {
border-radius: 12rpx; width: 100%;
} height: initial !important;
&-desc { border-radius: 12rpx;
margin-top: 24rpx; }
line-height: 1.6;
font-size: 30rpx; &-desc {
color: rgba(26, 26, 26, 0.9); margin-top: 24rpx;
&.is-empty { line-height: 1.6;
display: flex; font-size: 30rpx;
align-items: center; color: rgba(26, 26, 26, 0.9);
justify-content: center;
flex-grow: 1; &.is-empty {
font-size: 32rpx; display: flex;
} align-items: center;
} justify-content: center;
flex-grow: 1;
font-size: 32rpx;
}
}
} }
.tabbar { .tabbar {
width: 90vw; width: 90vw;
position: fixed; position: fixed;
left: 50%; left: 50%;
bottom: 40rpx; bottom: 40rpx;
transform: translateX(-50%); transform: translateX(-50%);
border-radius: 25rpx; border-radius: 25rpx;
box-sizing: border-box; box-sizing: border-box;
padding: 24rpx; padding: 24rpx;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
// background-color: rgba(0, 0, 0, 0.5); // background-color: rgba(0, 0, 0, 0.5);
background-color: #ffffff; background-color: #ffffff;
color: #333; color: #333;
box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.05); box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.05);
.refresh {
animation: refreshAni 6s ease-in-out infinite; .refresh {
color: #56bbf9; animation: refreshAni 6s ease-in-out infinite;
&-heart { color: #56bbf9;
font-size: 42rpx;
color: inherit; &-heart {
margin: 0 6rpx; font-size: 42rpx;
} color: inherit;
&-text { margin: 0 6rpx;
font-size: 24rpx; }
}
} &-text {
.pre { font-size: 24rpx;
color: #56bbf9; }
transition: transform 0.1s ease-in-out; }
&:hover {
transform: scale(1.05); .pre {
} color: #56bbf9;
.text { transition: transform 0.1s ease-in-out;
padding-left: 12rpx;
} &:hover {
} transform: scale(1.05);
.next { }
color: #f88ca2;
transition: transform 0.1s ease-in-out; .text {
&:hover { padding-left: 12rpx;
transform: scale(1.03); }
} }
.text {
padding-right: 12rpx; .next {
} color: #f88ca2;
} transition: transform 0.1s ease-in-out;
&:hover {
transform: scale(1.03);
}
.text {
padding-right: 12rpx;
}
}
} }
@keyframes refreshAni { @keyframes refreshAni {
0% { 0% {
color: #f88ca2; color: #f88ca2;
} }
50% {
color: #56bbf9; 50% {
} color: #56bbf9;
100% { }
color: #f88ca2;
} 100% {
color: #f88ca2;
}
} }
</style> </style>
+88 -74
Zobrazit soubor
@@ -1,92 +1,106 @@
<template> <template>
<view class="app-page"> <view class="app-page">
<view class="page-title">我们的故事</view> <view class="page-title">我们的故事</view>
<view class="html-typed" v-html="html">内容渲染</view> <view class="html-typed" v-html="html">内容渲染</view>
<scroll-btn bottom="160rpx" :scrollTop.sync="scrollTop"></scroll-btn> <scroll-btn bottom="160rpx" :scrollTop.sync="scrollTop"></scroll-btn>
</view> </view>
</template> </template>
<script> <script>
import LoveConfig from '@/config/love.config.js';
import ScrollBtn from '@/components/scroll-btn/scroll-btn.vue'; import ScrollBtn from '@/components/scroll-btn/scroll-btn.vue';
export default { export default {
components: { ScrollBtn }, components: {
data() { ScrollBtn
return { },
scrollTop: 0, data() {
html: '', return {
timer: null scrollTop: 0,
}; html: '',
}, timer: null
created() { };
this.fnInit(); },
}, computed: {
onPageScroll(e) { loveConfig() {
this.scrollTop = e.scrollTop; return this.$tm.vx.getters().getConfigs.loveConfig;
}, }
onBackPress() { },
clearTimeout(this.timer); watch: {
}, loveConfig: {
methods: { deep: true,
fnInit() { immediate: true,
clearTimeout(this.timer); handler(newVal, oldVal) {
const _html = LoveConfig.journey; if (!newVal) return;
let _index = 0; this.fnInit();
const _typing = () => { }
this.timer = setTimeout(() => { }
if (_index >= _html.length) { },
clearTimeout(this.timer); onPageScroll(e) {
} else { this.scrollTop = e.scrollTop;
this.html += _html.substring(_index, _index + 1); },
_index += 1; onBackPress() {
_typing(); clearTimeout(this.timer);
} },
}, 100); methods: {
}; fnInit() {
_typing(); 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> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.app-page { .app-page {
width: 100vw; width: 100vw;
min-height: 100vh; min-height: 100vh;
box-sizing: border-box; box-sizing: border-box;
padding: 36rpx; padding: 36rpx;
/* #ifdef APP-PLUS */ /* #ifdef APP-PLUS */
padding-top: 100rpx; padding-top: 100rpx;
/* #endif */ /* #endif */
/* #ifdef H5 */ /* #ifdef H5 */
padding-top: 80rpx; padding-top: 80rpx;
/* #endif */ /* #endif */
/* #ifdef MP-WEIXIN */ /* #ifdef MP-WEIXIN */
padding-top: 120rpx; padding-top: 120rpx;
/* #endif */ /* #endif */
background: linear-gradient( background: linear-gradient(-45deg,
-45deg, rgba(247, 149, 51, 0.1),
rgba(247, 149, 51, 0.1), rgba(243, 112, 85, 0.1) 15%,
rgba(243, 112, 85, 0.1) 15%, rgba(239, 78, 123, 0.1) 30%,
rgba(239, 78, 123, 0.1) 30%, rgba(161, 102, 171, 0.1) 44%,
rgba(161, 102, 171, 0.1) 44%, rgba(80, 115, 184, 0.1) 58%,
rgba(80, 115, 184, 0.1) 58%, rgba(16, 152, 173, 0.1) 72%,
rgba(16, 152, 173, 0.1) 72%, rgba(7, 179, 155, 0.1) 86%,
rgba(7, 179, 155, 0.1) 86%, rgba(109, 186, 130, 0.1));
rgba(109, 186, 130, 0.1) color: rgba(26, 26, 26, 1);
);
color: rgba(26, 26, 26, 1);
} }
.page-title { .page-title {
font-size: 42rpx; font-size: 42rpx;
font-weight: bold; font-weight: bold;
text-align: center; text-align: center;
text-shadow: 0rpx 4rpx 24rpx #bfe9ef; text-shadow: 0rpx 4rpx 24rpx #bfe9ef;
} }
.html-typed { .html-typed {
margin-top: 52rpx; margin-top: 52rpx;
line-height: 1.8; line-height: 1.8;
font-size: 30rpx; font-size: 30rpx;
} }
</style> </style>
+394 -385
Zobrazit soubor
@@ -1,421 +1,430 @@
<template> <template>
<view class="app-page" @touchstart="fnOnTouchstart" @touchend="fnOnTouchend" @touchcancel="fnOnTouchend"> <view class="app-page" @touchstart="fnOnTouchstart" @touchend="fnOnTouchend" @touchcancel="fnOnTouchend">
<view class="love-card" :class="{ ani: isDoAni }"> <view class="love-card" :class="{ ani: isDoAni }">
<view class="head"> <view class="head">
<image class="avatar" :src="loveConfig.boy.avatar" mode="scaleToFill"></image> <image class="avatar" :src="$utils.checkAvatarUrl(loveConfig.loveInfo.boyAvatar)" mode="scaleToFill"></image>
<view class="love-days"> <view class="love-days">
<view class="tip-text">相恋</view> <view class="tip-text">相恋</view>
<view class="number"> <view class="number">
<text class="boy">-</text> <text class="boy">-</text>
<text class="days">{{ calcLoveDays }}</text> <text class="days">{{ calcLoveDays }}</text>
<text class="girl">-</text> <text class="girl">-</text>
</view> </view>
<view class="tip-text"></view> <view class="tip-text"></view>
</view> </view>
<image class="avatar" :src="loveConfig.girl.avatar" mode="scaleToFill"></image> <image class="avatar" :src="$utils.checkAvatarUrl(loveConfig.loveInfo.girlAvatar)" mode="scaleToFill"></image>
</view> </view>
<view class="foot"> <view class="foot">
<view class="text" v-if="false"> <view class="text" v-if="false">
我们已经相恋 我们已经相恋
<text class="number">- {{ calcLoveDays }} -</text> <text class="number">- {{ calcLoveDays }} -</text>
天啦 天啦
</view> </view>
看看我们的恋爱清单都完成了哪些吧 看看我们的恋爱清单都完成了哪些吧
</view> </view>
</view> </view>
<view v-if="list.length == 0" class="list empty"> <view v-if="list.length == 0" class="list empty">
<view class="card"> <view class="card">
<image class="empty-image" :src="loveConfig.loveImageUrl" mode="scaleToFill"></image> <image class="empty-image" :src="$utils.checkImageUrl(loveConfig.pageImages.heartImageUrl)" mode="scaleToFill"></image>
<view class="empty-text">暂时还没有恋爱清单快去制定你们的恋爱清单吧~</view> <view class="empty-text">暂时还没有恋爱清单快去制定你们的恋爱清单吧~</view>
</view> </view>
</view> </view>
<view v-else class="list"> <view v-else class="list">
<block v-for="(item, index) in list" :key="index"> <block v-for="(item, index) in list" :key="index">
<view class="card" :class="{ ani: isDoAni }" :style="{ '--delay': calcCardDelay(index) }"> <view class="card" :class="{ ani: isDoAni }" :style="{ '--delay': calcCardDelay(index) }">
<view class="head"> <view class="head">
<view class="status"> <view class="status">
<view v-if="!item.finish" class="text">进行中</view> <view v-if="item.status==='wait'" class="text">未开始</view>
<view v-else class="text finish">已完成</view> <view v-else-if="item.status==='doing'" class="text">进行中</view>
</view> <view v-else-if="item.status==='complete'" class="text finish">已完成</view>
<view class="title"> </view>
<view class="title-name">{{ item.title }}</view> <view class="title">
<view class="title-desc">{{ item.desc }}</view> <view class="title-name">{{ item.title }}</view>
</view> </view>
<view class="actions" @click="fnOnItemOpen(item)"> <view class="actions" @click="fnOnItemOpen(item)">
<text class="icon">{{ item.open ? '-' : '+' }}</text> <text class="icon">{{ item.open ? '-' : '+' }}</text>
</view> </view>
</view> </view>
<view v-if="item.open" class="body"> <view v-if="item.open && item.content" class="body">
<view class="desc"> <view v-if="item.content" class="desc">
<view class="desc-label">开始时间</view> <view class="desc-label">事件内容</view>
<view class="desc-value">{{ item.detail.start || '暂无计划' }}</view> <view class="desc-value">{{ item.content || "-" }}</view>
</view> </view>
<view class="desc" v-if="item.detail.desc"> <view v-if="item.status==='complete' && item.completeDate" class="desc">
<view class="desc-label">事件描述</view> <view class="desc-label">完成时间</view>
<view class="desc-value">{{ item.detail.desc }}</view> <view class="desc-value">{{ item.completeDate || '-' }}</view>
</view> </view>
<view class="desc"> </view>
<view class="desc-label">完成时间</view> </view>
<view class="desc-value">{{ item.detail.end || '未开始或正在进行中...' }}</view> </block>
</view> </view>
<view class="desc"> <scroll-btn :scrollTop.sync="scrollTop" @on-status="fnOnScrollStatus"></scroll-btn>
<view class="desc-label">完成打卡</view> </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>
</template> </template>
<script> <script>
import LoveConfig from '@/config/love.config.js';
import ScrollBtn from '@/components/scroll-btn/scroll-btn.vue'; import ScrollBtn from '@/components/scroll-btn/scroll-btn.vue';
export default { export default {
components: { ScrollBtn }, components: {
data() { ScrollBtn
return { },
isDoAni: true, data() {
scrollTop: 0, return {
loveConfig: LoveConfig, isDoAni: true,
list: [] scrollTop: 0,
}; list: []
}, };
computed: { },
calcLoveDays() { computed: {
const formatStartDate = this.loveConfig.loveStartDate.replace(/-/g, '/'); loveConfig() {
const start = new Date(formatStartDate), return this.$tm.vx.getters().getConfigs.loveConfig;
now = new Date(); },
const T = now.getTime() - start.getTime(); calcLoveDays() {
const i = 24 * 60 * 60 * 1000; const formatStartDate = this.loveConfig.loveDate.replace(/-/g, '/');
const d = T / i; const start = new Date(formatStartDate),
const D = Math.floor(d); now = new Date();
return D; const T = now.getTime() - start.getTime();
}, const i = 24 * 60 * 60 * 1000;
calcCardDelay() { const d = T / i;
return index => { const D = Math.floor(d);
return Math.random() * index + 1 + 's'; return D;
}; },
} calcCardDelay() {
}, return index => {
created() { return Math.random() * index + 1 + 's';
this.fnGetList(); };
}, }
onPageScroll(e) { },
this.scrollTop = e.scrollTop; watch: {
}, loveConfig: {
methods: { deep: true,
fnGetList() { immediate: true,
if (LoveConfig.loveList.useApi && LoveConfig.loveList.api) { handler(newVal) {
uni.request({ if (!newVal) return;
url: LoveConfig.loveList.api, this.fnGetList();
header: { }
ContentType: 'application/json' }
}, },
method: 'GET', onPageScroll(e) {
dataType: 'json', this.scrollTop = e.scrollTop;
success: res => { },
if (res.statusCode == 200 && res.data.status == 200) { methods: {
this.list = res.data.data.map(item => { fnGetList() {
item['open'] = false; this.list = this.loveConfig.loveDaily.list.map(item => {
return item; item['open'] = false;
}); return item;
} else { });
uni.$tm.toast('数据请求失败,请检查接口!'); },
} fnOnItemOpen(item) {
}, item.open = !item.open;
fail: err => { this.$forceUpdate();
uni.$tm.toast('数据请求失败,请检查接口!'); },
} fnOnScrollStatus(isEnd) {
}); this.isDoAni = isEnd;
} else { },
this.list = LoveConfig.loveList.data.map(item => { fnOnTouchstart() {
item['open'] = false; this.isDoAni = false;
return item; },
}); fnOnTouchend() {
} this.isDoAni = true;
}, }
fnOnItemOpen(item) { }
item.open = !item.open;
this.$forceUpdate();
},
fnOnScrollStatus(isEnd) {
this.isDoAni = isEnd;
},
fnOnTouchstart() {
this.isDoAni = false;
},
fnOnTouchend() {
this.isDoAni = true;
}
}
}; };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.app-page { .app-page {
width: 100vw; width: 100vw;
min-height: 100vh; min-height: 100vh;
box-sizing: border-box; box-sizing: border-box;
padding: 36rpx; padding: 36rpx;
/* #ifdef H5 */ /* #ifdef H5 */
padding-top: 60rpx; padding-top: 60rpx;
/* #endif */ /* #endif */
/* #ifndef H5 */ /* #ifndef H5 */
padding-top: 180rpx; padding-top: 180rpx;
/* #endif */ /* #endif */
background: linear-gradient( background: linear-gradient(135deg,
135deg, rgba(247, 149, 51, 0.1),
rgba(247, 149, 51, 0.1), rgba(243, 112, 85, 0.1) 15%,
rgba(243, 112, 85, 0.1) 15%, rgba(239, 78, 123, 0.1) 30%,
rgba(239, 78, 123, 0.1) 30%, rgba(161, 102, 171, 0.1) 44%,
rgba(161, 102, 171, 0.1) 44%, rgba(80, 115, 184, 0.1) 58%,
rgba(80, 115, 184, 0.1) 58%, rgba(16, 152, 173, 0.1) 72%,
rgba(16, 152, 173, 0.1) 72%, rgba(7, 179, 155, 0.1) 86%,
rgba(7, 179, 155, 0.1) 86%, rgba(109, 186, 130, 0.1));
rgba(109, 186, 130, 0.1)
);
} }
.love-card { .love-card {
width: 100%; width: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
box-sizing: border-box; box-sizing: border-box;
padding: 0 24rpx; padding: 0 24rpx;
padding-top: 66rpx; padding-top: 66rpx;
padding-bottom: 52rpx; padding-bottom: 52rpx;
border-radius: 50rpx; border-radius: 50rpx;
border: 4rpx solid rgba(96, 77, 68, 0.9); border: 4rpx solid rgba(96, 77, 68, 0.9);
border-color: #faf8eb; border-color: #faf8eb;
background-color: rgba(255, 199, 184, 0.9); background-color: rgba(255, 199, 184, 0.9);
margin-bottom: 52rpx; margin-bottom: 52rpx;
box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.1); box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.1);
&.ani {
animation: loveCardAni 3s ease-in-out infinite;
}
.head { &.ani {
display: flex; animation: loveCardAni 3s ease-in-out infinite;
.avatar { }
width: 150rpx;
height: 150rpx;
box-sizing: border-box;
border-radius: 50%;
border: 6rpx solid rgba(255, 255, 255, 0.7);
&.boy { .head {
border-color: #56bbf9; display: flex;
}
&.girl { .avatar {
border-color: #f88ca2; width: 150rpx;
} height: 150rpx;
} box-sizing: border-box;
.love-days { border-radius: 50%;
margin: 0 12rpx; border: 6rpx solid rgba(255, 255, 255, 0.7);
display: flex;
flex-direction: column; &.boy {
align-items: center; border-color: #56bbf9;
justify-content: center; }
font-size: 26rpx;
.tip-text { &.girl {
color: #333; border-color: #f88ca2;
} }
.number { }
font-size: 46rpx;
padding: 12rpx 0; .love-days {
> .boy { margin: 0 12rpx;
color: #56bbf9; display: flex;
margin-right: 12rpx; flex-direction: column;
} align-items: center;
> .girl { justify-content: center;
color: #f88ca2; font-size: 26rpx;
margin-left: 12rpx;
} .tip-text {
} color: #333;
.days { }
animation: daysAni 6s ease-in-out infinite;
font-weight: bold; .number {
} font-size: 46rpx;
} padding: 12rpx 0;
}
.foot { > .boy {
display: none; color: #56bbf9;
margin-top: 36rpx; margin-right: 12rpx;
font-size: 24rpx; }
}
> .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 { @keyframes daysAni {
0% { 0% {
color: #f88ca2; color: #f88ca2;
} }
50% {
color: #56bbf9; 50% {
} color: #56bbf9;
100% { }
color: #f88ca2;
} 100% {
color: #f88ca2;
}
} }
@keyframes loveCardAni { @keyframes loveCardAni {
0% { 0% {
transform: scale(1); transform: scale(1);
} }
50% {
transform: scale(1.03); 50% {
} transform: scale(1.03);
100% { }
transform: scale(1);
} 100% {
transform: scale(1);
}
} }
.list { .list {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
box-sizing: border-box; box-sizing: border-box;
} }
.empty { .empty {
height: calc(100vh - 180rpx - 280rpx - 36rpx); height: calc(100vh - 180rpx - 280rpx - 36rpx);
.card {
height: 100%; .card {
padding: 100rpx; height: 100%;
margin-bottom: 0; padding: 100rpx;
text-align: center; margin-bottom: 0;
justify-content: center; text-align: center;
color: rgba(96, 77, 68, 0.9); justify-content: center;
} color: rgba(96, 77, 68, 0.9);
&-image { }
width: 300rpx;
height: 300rpx; &-image {
} width: 300rpx;
&-text { height: 300rpx;
margin-top: 36rpx; }
line-height: 50rpx;
} &-text {
margin-top: 36rpx;
line-height: 50rpx;
}
} }
.card { .card {
width: 100%; width: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
box-sizing: border-box; box-sizing: border-box;
padding: 24rpx; padding: 24rpx;
border-radius: 50rpx; border-radius: 50rpx;
border: 4rpx solid rgba(96, 77, 68, 0.9); border: 4rpx solid rgba(96, 77, 68, 0.9);
border-color: #fff; border-color: #fff;
// background-color: #faf8eb; // background-color: #faf8eb;
background-color: #ffffff; background-color: #ffffff;
margin-bottom: 36rpx; margin-bottom: 36rpx;
box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.05); box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.05);
animation-delay: var(--delay); 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;
}
}
}
.body { &.ani {
margin-top: 24rpx; // animation: cardAni 3s ease-in-out infinite;
width: 100%; }
background-color: #ffffff;
// background-color: #faf8eb; .head {
background-color: rgba(96, 77, 68, 0.05); width: 100%;
border-radius: 24rpx; display: flex;
box-sizing: border-box; align-items: center;
padding: 24rpx; box-sizing: border-box;
padding-bottom: 12rpx;
font-size: 26rpx; .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 { @keyframes cardAni {
0% { 0% {
transform: translateY(0rpx); transform: translateY(0rpx);
} }
50% { 50% {
transform: translateY(-10rpx); transform: translateY(-10rpx);
} }
100% { 100% {
transform: translateY(0rpx); transform: translateY(0rpx);
} }
} }
.desc { .desc {
display: flex; display: flex;
margin-bottom: 12rpx; margin-bottom: 12rpx;
&-label {
color: #333; &-label {
width: 140rpx; color: #333;
// font-weight: bold; width: 140rpx;
} // font-weight: bold;
&-value { }
width: 0;
flex-grow: 1; &-value {
line-height: 1.5; width: 0;
color: #333; flex-grow: 1;
} line-height: 1.5;
color: #333;
}
} }
</style> </style>
+382 -322
Zobrazit soubor
@@ -1,358 +1,418 @@
<template> <template>
<view class="app-page bg-white"> <view class="app-page bg-white">
<!-- 情侣信息 --> <!-- 情侣信息 -->
<view class="lover-wrap" :style="[loveWrapStyle]"> <view class="lover-wrap" :style="[loveWrapStyle]">
<view class="lover-card"> <view class="lover-card">
<view class="boy"> <view class="boy">
<image class="avatar" :src="loveConfig.boy.avatar" mode="aspectFit"></image> <image class="avatar" :src="$utils.checkAvatarUrl(loveConfig.loveInfo.boyAvatar)" mode="aspectFit"></image>
<view class="name">{{ loveConfig.boy.name }}</view> <view class="name">{{ loveConfig.loveInfo.boyNickname }}</view>
</view> </view>
<image class="like" :src="loveConfig.loveImageUrl" mode="scaleToFill"></image> <image class="like" :src="$utils.checkImageUrl(loveConfig.loveImageUrl)" mode="scaleToFill"></image>
<view class="girl"> <view class="girl">
<image class="avatar" :src="loveConfig.girl.avatar" mode="aspectFit"></image> <image class="avatar" :src="$utils.checkAvatarUrl(loveConfig.loveInfo.girlAvatar)" mode="aspectFit"></image>
<view class="name">{{ loveConfig.girl.name }}</view> <view class="name">{{ loveConfig.loveInfo.girlNickname }}</view>
</view> </view>
</view> </view>
<image class="wave-image" :src="loveConfig.waveImageUrl" mode="scaleToFill"></image> <image class="wave-image" :src="$utils.checkImageUrl(loveConfig.pageImages.waveImageUrl)" mode="scaleToFill"></image>
</view> </view>
<!-- 恋爱记时 --> <!-- 恋爱记时 -->
<view class="love-time-wrap"> <view class="love-time-wrap">
<view class="title">{{ loveConfig.timeTitle }}</view> <view class="title">{{ loveConfig.loveDateTitle }}</view>
<view class="content"> <view class="content">
<text class="text"> <text class="text">
<text class="number">{{ loveDayCount.d }}</text> <text class="number">{{ loveDayCount.d }}</text>
</text> </text>
<text class="text"> <text class="text">
<text class="number">{{ loveDayCount.h }}</text> <text class="number">{{ loveDayCount.h }}</text>
小时 小时
</text> </text>
<text class="text"> <text class="text">
<text class="number">{{ loveDayCount.m }}</text> <text class="number">{{ loveDayCount.m }}</text>
分钟 分钟
</text> </text>
<text class="text"> <text class="text">
<text class="number">{{ loveDayCount.s }}</text> <text class="number">{{ loveDayCount.s }}</text>
</text> </text>
</view> </view>
</view> </view>
<!-- 功能导航 --> <!-- 功能导航 -->
<view class="list-wrap"> <view class="list-wrap">
<block v-for="(nav, index) in loveConfig.nav" :key="index"> <block v-for="(nav, index) in navList" :key="index">
<view v-if="nav.use" class="list-item" @click="fnToPage(nav.key)"> <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="left">
<view class="right"> <image class="icon" :src="nav.iconImageUrl" mode="aspectFit"></image>
<view class="name">{{ nav.title }}</view> </view>
<view class="desc">{{ nav.desc }}</view> <view class="right">
</view> <view class="name">{{ nav.title }}</view>
</view> <view class="desc">{{ nav.desc }}</view>
</block> </view>
</view> </view>
</view> </block>
</view>
</view>
</template> </template>
<script> <script>
import LoveConfig from '@/config/love.config.js';
export default { export default {
data() { data() {
return { return {
loveConfig: LoveConfig, loveDayTimer: null,
loveDayTimer: null, loveDayCount: {
loveDayCount: { d: 0,
d: 0, h: 0,
h: 0, m: 0,
m: 0, s: 0
s: 0 },
} navList: []
}; };
}, },
computed: { computed: {
loveWrapStyle() { loveConfig() {
return { return this.$tm.vx.getters().getConfigs.loveConfig;
backgroundImage: `url(${this.loveConfig.bgImageUrl})` },
}; loveWrapStyle() {
} return {
}, backgroundImage: `url(${this.$utils.checkImageUrl(this.loveConfig.pageImages.bgImageUrl)})`
onLoad() { };
this.fnSetPageTitle('恋爱日记'); }
this.fnInitLoveDayCount(); },
}, watch: {
methods: { loveConfig: {
fnInitLoveDayCount() { deep: true,
clearTimeout(this.loveDayTimer); immediate: true,
const _countDownFn = () => { handler(newVal, oldVal) {
this.loveDayTimer = setTimeout(_countDownFn, 1000); if (!newVal) return;
const formatStartDate = this.loveConfig.loveStartDate.replace(/-/g, '/'); this.initList(newVal)
const start = new Date(formatStartDate), this.fnInitLoveDayCount();
now = new Date(); }
const T = now.getTime() - start.getTime(); }
const i = 24 * 60 * 60 * 1000; },
const d = T / i; onLoad() {
const D = Math.floor(d); this.fnSetPageTitle('恋爱日记');
const h = (d - D) * 24; },
const H = Math.floor(h); methods: {
const m = (h - H) * 60; initList(configs) {
const M = Math.floor(m); this.navList = [
const s = (m - M) * 60; {
const S = Math.floor(s); key: 'journey',
this.loveDayCount = { use: configs.ourStory.enabled,
d: D, iconImageUrl: 'https://b.925i.cn/uni_halo_love/diandian.png',
h: H, title: '关于我们',
m: M, desc: '我们一起度过的那些经历'
s: S },
}; {
}; key: 'album',
_countDownFn(); use: configs.lovePhoto.enabled,
}, iconImageUrl: 'https://b.925i.cn/uni_halo_love/diandian.png',
fnToPage(pageName) { title: '恋爱相册',
uni.navigateTo({ desc: '定格了我们的那些小美好'
url: `/pagesA/love/${pageName}` },
}); {
} 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> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.app-page { .app-page {
width: 100vw; width: 100vw;
min-height: 100vh; min-height: 100vh;
background: linear-gradient( background: linear-gradient(
-45deg, -45deg,
rgba(247, 149, 51, 0.1), rgba(247, 149, 51, 0.1),
rgba(243, 112, 85, 0.1) 15%, rgba(243, 112, 85, 0.1) 15%,
rgba(239, 78, 123, 0.1) 30%, rgba(239, 78, 123, 0.1) 30%,
rgba(161, 102, 171, 0.1) 44%, rgba(161, 102, 171, 0.1) 44%,
rgba(80, 115, 184, 0.1) 58%, rgba(80, 115, 184, 0.1) 58%,
rgba(16, 152, 173, 0.1) 72%, rgba(16, 152, 173, 0.1) 72%,
rgba(7, 179, 155, 0.1) 86%, rgba(7, 179, 155, 0.1) 86%,
rgba(109, 186, 130, 0.1) rgba(109, 186, 130, 0.1)
); );
} }
.lover-wrap { .lover-wrap {
position: relative; position: relative;
width: 100vw; width: 100vw;
height: 50vh; height: 50vh;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
background-size: cover; background-size: cover;
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 50% 50%; background-position: 50% 50%;
&::before { &::before {
position: absolute; position: absolute;
left: 0; left: 0;
top: 0; top: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
content: ''; content: '';
background-color: rgba(255, 255, 255, 0.1); background-color: rgba(255, 255, 255, 0.1);
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAKUlEQVQImU3IMREAIAgAwJfNkQCEsH8cijjpMf6vnXlQaIiJFx+omEBfmqIEZLe2jzcAAAAASUVORK5CYII=); background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAKUlEQVQImU3IMREAIAgAwJfNkQCEsH8cijjpMf6vnXlQaIiJFx+omEBfmqIEZLe2jzcAAAAASUVORK5CYII=);
z-index: 0; z-index: 0;
backdrop-filter: blur(4rpx); backdrop-filter: blur(4rpx);
overflow: hidden; 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);
}
}
.like { &::after {
width: 120rpx; content: '';
height: 120rpx; position: absolute;
animation: likeani 1s ease-in-out infinite; left: 0;
} bottom: -60rpx;
} width: 100vw;
.wave-image { height: 60rpx;
width: 100%; background-image: linear-gradient(to bottom, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0));
height: 120rpx; }
position: absolute;
left: 0; .lover-card {
bottom: 0; position: absolute;
mix-blend-mode: screen; 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 { .love-time-wrap {
margin-top: 80rpx; margin-top: 80rpx;
width: 100vw; width: 100vw;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
.title { .title {
font-size: 46rpx; font-size: 46rpx;
letter-spacing: 4rpx; letter-spacing: 4rpx;
// background-image: linear-gradient(270deg, #ff4500, #ffa500, #ffd700, #90ee90, #00ffff, #1e90ff, #9370db, #ff69b4, #ff4500); // background-image: linear-gradient(270deg, #ff4500, #ffa500, #ffd700, #90ee90, #00ffff, #1e90ff, #9370db, #ff69b4, #ff4500);
// -webkit-background-clip: text; // -webkit-background-clip: text;
// color: #000; // color: #000;
color: #333; color: #333;
font-size: 42rpx; font-size: 42rpx;
font-weight: bold; font-weight: bold;
// animation: loveTimeTitleAni 80s linear infinite; // animation: loveTimeTitleAni 80s linear infinite;
} }
.content {
margin-top: 24rpx;
display: flex;
align-items: center;
justify-content: center;
.text { .content {
font-size: 28rpx; margin-top: 24rpx;
} display: flex;
.number { align-items: center;
margin: 0 8rpx; justify-content: center;
font-size: 46rpx;
// color: #ff69b4; .text {
color: #f83856; font-size: 28rpx;
font-weight: bold; }
}
} .number {
margin: 0 8rpx;
font-size: 46rpx;
// color: #ff69b4;
color: #f83856;
font-weight: bold;
}
}
} }
.list-wrap { .list-wrap {
margin-top: 75rpx; margin-top: 75rpx;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
box-sizing: border-box; box-sizing: border-box;
padding: 0 36rpx; padding: 0 36rpx;
.list-item { .list-item {
width: 100%; width: 100%;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-around; justify-content: space-around;
box-sizing: border-box; box-sizing: border-box;
padding: 28rpx 32rpx; padding: 28rpx 32rpx;
background-color: #ffffff; background-color: #ffffff;
border-radius: 50rpx; border-radius: 50rpx;
margin-bottom: 32rpx; margin-bottom: 32rpx;
box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.03); box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.03);
&:nth-child(1) { &:nth-child(1) {
animation: listItemAni1 3s ease-in-out infinite; animation: listItemAni1 3s ease-in-out infinite;
} }
&:nth-child(2) {
animation: listItemAni1 3s ease-in-out infinite; &:nth-child(2) {
animation-delay: 1.5s; animation: listItemAni1 3s ease-in-out infinite;
} animation-delay: 1.5s;
&:nth-child(3) { }
animation: listItemAni1 3s ease-in-out infinite;
animation-delay: 2s; &:nth-child(3) {
} animation: listItemAni1 3s ease-in-out infinite;
.left { animation-delay: 2s;
width: 120rpx; }
height: 120rpx;
.icon { .left {
width: 100%; width: 120rpx;
height: 100%; height: 120rpx;
}
} .icon {
.right { width: 100%;
flex-grow: 1; height: 100%;
display: flex; }
flex-direction: column; }
justify-content: center;
box-sizing: border-box; .right {
padding-left: 40rpx; flex-grow: 1;
.name { display: flex;
font-size: 32rpx; flex-direction: column;
font-weight: bold; justify-content: center;
color: #333333; box-sizing: border-box;
} padding-left: 40rpx;
.desc {
margin-top: 8px; .name {
font-size: 26rpx; font-size: 32rpx;
color: #777777; font-weight: bold;
} color: #333333;
} }
}
.desc {
margin-top: 8px;
font-size: 26rpx;
color: #777777;
}
}
}
} }
@keyframes likeani { @keyframes likeani {
0% { 0% {
transform: scale(1); transform: scale(1);
} }
25% { 25% {
transform: scale(1.2); transform: scale(1.2);
} }
50% { 50% {
transform: scale(1.1); transform: scale(1.1);
} }
75% { 75% {
transform: scale(1.3); transform: scale(1.3);
} }
100% { 100% {
transform: scale(1); transform: scale(1);
} }
} }
@keyframes loveTimeTitleAni { @keyframes loveTimeTitleAni {
to { to {
background-position: -200rem; background-position: -200rem;
} }
} }
@keyframes listItemAni1 { @keyframes listItemAni1 {
0% { 0% {
transform: translateY(0rpx); transform: translateY(0rpx);
} }
50% { 50% {
transform: translateY(-10rpx); transform: translateY(-10rpx);
} }
100% { 100% {
transform: translateY(0rpx); transform: translateY(0rpx);
} }
} }
</style> </style>
+316 -273
Zobrazit soubor
@@ -1,400 +1,443 @@
<template> <template>
<view class="app-page bg-gradient-blue-lighten-b" :style="pageStyle"> <view class="app-page bg-gradient-blue-lighten-b" :style="pageStyle">
<view class="tn-satr"> <view class="tn-satr">
<view class="sky"></view> <view class="sky"></view>
<view class="stars"> <view class="stars">
<view class="falling-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 class="star-fall"></view> <view class="star-fall"></view>
<view class="star-fall"></view> <view class="star-fall"></view>
</view> </view>
<view class="small-stars"> <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 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 class="medium-stars"> <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 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>
</view> </view>
<view class="user-info__container flex flex-col flex-center"> <view class="user-info__container flex flex-col flex-center">
<image class="user-info__avatar" :src="startInfo.logo" mode="aspectFill"></image> <image class="user-info__avatar" :src="startConfig.logo" mode="aspectFill"></image>
<view class="user-info__nick-name"> {{ startInfo.title }} </view> <view class="user-info__nick-name"> {{ startConfig.title }} </view>
</view> </view>
<view class="text-align-center text-white" style="padding: 60vh 0 0 0;"> <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="" style="font-size: 44rpx;" v-if="startConfig.desc1">{{ startConfig.desc1 }}</view>
<view class="mt-30 text-size-m" v-if="startInfo.desc2">{{ startInfo.desc2 }}</view> <view class="mt-30 text-size-m" v-if="startConfig.desc2">{{ startConfig.desc2 }}</view>
</view> </view>
<view class="" style="padding: 120rpx 200rpx;z-index: 999;position: relative;"> <view class="" style="padding: 120rpx 200rpx;z-index: 999;position: relative;">
<view class="start-btn" @click="fnStart()">{{ startInfo.btnText || '开始体验' }}</view> <view class="start-btn" @click="fnStart()">{{ startConfig.btnText || '开始体验' }}</view>
</view> </view>
<!-- 波浪效果 --> <!-- 波浪效果 -->
<wave></wave> <wave></wave>
</view> </view>
</template> </template>
<script> <script>
import wave from '@/components/wave/wave.vue'; import wave from '@/components/wave/wave.vue';
export default { export default {
components: { wave }, components: {
computed: { wave
startInfo() { },
return getApp().globalData.start; computed: {
}, startConfig() {
pageStyle() { return this.$tm.vx.getters().getConfigs.startConfig;
if (this.startInfo.bg) { },
const _bg = this.$utils.checkIsUrl(this.startInfo.bg) ? `url(${this.startInfo.bg})` : this.startInfo.bg; pageStyle() {
return { if (this.startConfig.bg) {
background: _bg + '!important' const _bg = this.$utils.checkIsUrl(this.startConfig.bg) ? `url(${this.startConfig.bg})` : this
}; .startConfig.bg;
} return {
return {}; background: _bg + '!important'
} };
}, }
methods: { return {};
fnStart() { }
uni.switchTab({ },
url: '/pages/tabbar/home/home', methods: {
success: () => { fnStart() {
uni.setStorageSync('APP_HAS_STARTED', true); uni.switchTab({
} url: '/pages/tabbar/home/home',
}); success: () => {
} uni.setStorageSync('APP_HAS_STARTED', true);
} }
});
}
}
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.app-page { .app-page {
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
} }
.start-btn { .start-btn {
box-sizing: border-box; box-sizing: border-box;
background-color: transparent; background-color: transparent;
padding: 16rpx 50rpx; padding: 16rpx 50rpx;
border-radius: 50rpx; border-radius: 50rpx;
border: 2rpx solid #ffffff; border: 2rpx solid #ffffff;
color: #ffffff; color: #ffffff;
text-align: center; text-align: center;
font-size: 28rpx; font-size: 28rpx;
} }
/* 用户信息 start */ /* 用户信息 start */
.user-info { .user-info {
&__container { &__container {
position: absolute; position: absolute;
top: 25vh; top: 25vh;
left: 50%; left: 50%;
-webkit-transform: translate(-50%, -50%); -webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
} }
&__avatar { &__avatar {
width: 200rpx; width: 200rpx;
height: 200rpx; height: 200rpx;
border: 8rpx solid rgba(255, 255, 255, 0.05); border: 8rpx solid rgba(255, 255, 255, 0.05);
border-radius: 50%; border-radius: 50%;
overflow: hidden; overflow: hidden;
box-shadow: 0rpx 0rpx 80rpx 0rpx rgba(0, 0, 0, 0.15); box-shadow: 0rpx 0rpx 80rpx 0rpx rgba(0, 0, 0, 0.15);
} }
&__nick-name { &__nick-name {
color: #ffffff; color: #ffffff;
margin-top: 26rpx; margin-top: 26rpx;
font-size: 36rpx; font-size: 36rpx;
font-weight: 600; font-weight: 600;
text-align: center; text-align: center;
} }
} }
/* 用户信息 end */ /* 用户信息 end */
/* 流星*/ /* 流星*/
.tn-satr { .tn-satr {
position: fixed; position: fixed;
width: 100%; width: 100%;
height: 600px; height: 600px;
overflow: hidden; overflow: hidden;
flex-shrink: 0; flex-shrink: 0;
z-index: 998; z-index: 998;
} }
.stars { .stars {
position: absolute; position: absolute;
z-index: 1; z-index: 1;
width: 100%; width: 100%;
height: 400px; height: 400px;
} }
.star { .star {
border-radius: 50%; border-radius: 50%;
background: #ffffff; background: #ffffff;
box-shadow: 0px 0px 6px 0px rgba(255, 255, 255, 0.8); box-shadow: 0px 0px 6px 0px rgba(255, 255, 255, 0.8);
} }
.small-stars .star { .small-stars .star {
position: absolute; position: absolute;
width: 3px; width: 3px;
height: 3px; height: 3px;
} }
.small-stars .star:nth-child(2n) { .small-stars .star:nth-child(2n) {
opacity: 0; opacity: 0;
-webkit-animation: star-blink 1.2s linear infinite alternate; -webkit-animation: star-blink 1.2s linear infinite alternate;
animation: star-blink 1.2s linear infinite alternate; animation: star-blink 1.2s linear infinite alternate;
} }
.small-stars .star:nth-child(1) { .small-stars .star:nth-child(1) {
left: 40px; left: 40px;
bottom: 50px; bottom: 50px;
} }
.small-stars .star:nth-child(2) { .small-stars .star:nth-child(2) {
left: 200px; left: 200px;
bottom: 40px; bottom: 40px;
} }
.small-stars .star:nth-child(3) { .small-stars .star:nth-child(3) {
left: 60px; left: 60px;
bottom: 120px; bottom: 120px;
} }
.small-stars .star:nth-child(4) { .small-stars .star:nth-child(4) {
left: 140px; left: 140px;
bottom: 250px; bottom: 250px;
} }
.small-stars .star:nth-child(5) { .small-stars .star:nth-child(5) {
left: 400px; left: 400px;
bottom: 300px; bottom: 300px;
} }
.small-stars .star:nth-child(6) { .small-stars .star:nth-child(6) {
left: 170px; left: 170px;
bottom: 80px; bottom: 80px;
} }
.small-stars .star:nth-child(7) { .small-stars .star:nth-child(7) {
left: 200px; left: 200px;
bottom: 360px; bottom: 360px;
-webkit-animation-delay: 0.2s; -webkit-animation-delay: 0.2s;
animation-delay: 0.2s; animation-delay: 0.2s;
} }
.small-stars .star:nth-child(8) { .small-stars .star:nth-child(8) {
left: 250px; left: 250px;
bottom: 320px; bottom: 320px;
} }
.small-stars .star:nth-child(9) { .small-stars .star:nth-child(9) {
left: 300px; left: 300px;
bottom: 340px; bottom: 340px;
} }
.small-stars .star:nth-child(10) { .small-stars .star:nth-child(10) {
left: 130px; left: 130px;
bottom: 320px; bottom: 320px;
-webkit-animation-delay: 0.5s; -webkit-animation-delay: 0.5s;
animation-delay: 0.5s; animation-delay: 0.5s;
} }
.small-stars .star:nth-child(11) { .small-stars .star:nth-child(11) {
left: 230px; left: 230px;
bottom: 330px; bottom: 330px;
-webkit-animation-delay: 7s; -webkit-animation-delay: 7s;
animation-delay: 7s; animation-delay: 7s;
} }
.small-stars .star:nth-child(12) { .small-stars .star:nth-child(12) {
left: 300px; left: 300px;
bottom: 360px; bottom: 360px;
-webkit-animation-delay: 0.3s; -webkit-animation-delay: 0.3s;
animation-delay: 0.3s; animation-delay: 0.3s;
} }
@-webkit-keyframes star-blink { @-webkit-keyframes star-blink {
50% { 50% {
width: 3px; width: 3px;
height: 3px; height: 3px;
opacity: 1; opacity: 1;
} }
} }
@keyframes star-blink { @keyframes star-blink {
50% { 50% {
width: 3px; width: 3px;
height: 3px; height: 3px;
opacity: 1; opacity: 1;
} }
} }
.medium-stars .star { .medium-stars .star {
position: absolute; position: absolute;
width: 3px; width: 3px;
height: 3px; height: 3px;
opacity: 0; opacity: 0;
-webkit-animation: star-blink 1.2s ease-in infinite alternate; -webkit-animation: star-blink 1.2s ease-in infinite alternate;
animation: star-blink 1.2s ease-in infinite alternate; animation: star-blink 1.2s ease-in infinite alternate;
} }
.medium-stars .star:nth-child(1) { .medium-stars .star:nth-child(1) {
left: 300px; left: 300px;
bottom: 50px; bottom: 50px;
} }
.medium-stars .star:nth-child(2) { .medium-stars .star:nth-child(2) {
left: 400px; left: 400px;
bottom: 40px; bottom: 40px;
-webkit-animation-delay: 0.4s; -webkit-animation-delay: 0.4s;
animation-delay: 0.4s; animation-delay: 0.4s;
} }
.medium-stars .star:nth-child(3) { .medium-stars .star:nth-child(3) {
left: 330px; left: 330px;
bottom: 300px; bottom: 300px;
-webkit-animation-delay: 0.2s; -webkit-animation-delay: 0.2s;
animation-delay: 0.2s; animation-delay: 0.2s;
} }
.medium-stars .star:nth-child(4) { .medium-stars .star:nth-child(4) {
left: 460px; left: 460px;
bottom: 300px; bottom: 300px;
-webkit-animation-delay: 0.9s; -webkit-animation-delay: 0.9s;
animation-delay: 0.9s; animation-delay: 0.9s;
} }
.medium-stars .star:nth-child(5) { .medium-stars .star:nth-child(5) {
left: 300px; left: 300px;
bottom: 150px; bottom: 150px;
-webkit-animation-delay: 1.2s; -webkit-animation-delay: 1.2s;
animation-delay: 1.2s; animation-delay: 1.2s;
} }
.medium-stars .star:nth-child(6) { .medium-stars .star:nth-child(6) {
left: 440px; left: 440px;
bottom: 120px; bottom: 120px;
-webkit-animation-delay: 1s; -webkit-animation-delay: 1s;
animation-delay: 1s; animation-delay: 1s;
} }
.medium-stars .star:nth-child(7) { .medium-stars .star:nth-child(7) {
left: 200px; left: 200px;
bottom: 140px; bottom: 140px;
-webkit-animation-delay: 0.8s; -webkit-animation-delay: 0.8s;
animation-delay: 0.8s; animation-delay: 0.8s;
} }
.medium-stars .star:nth-child(8) { .medium-stars .star:nth-child(8) {
left: 30px; left: 30px;
bottom: 480px; bottom: 480px;
-webkit-animation-delay: 0.3s; -webkit-animation-delay: 0.3s;
animation-delay: 0.3s; animation-delay: 0.3s;
} }
.medium-stars .star:nth-child(9) { .medium-stars .star:nth-child(9) {
left: 460px; left: 460px;
bottom: 400px; bottom: 400px;
-webkit-animation-delay: 1.2s; -webkit-animation-delay: 1.2s;
animation-delay: 1.2s; animation-delay: 1.2s;
} }
.medium-stars .star:nth-child(10) { .medium-stars .star:nth-child(10) {
left: 150px; left: 150px;
bottom: 10px; bottom: 10px;
-webkit-animation-delay: 1s; -webkit-animation-delay: 1s;
animation-delay: 1s; animation-delay: 1s;
} }
.medium-stars .star:nth-child(11) { .medium-stars .star:nth-child(11) {
left: 420px; left: 420px;
bottom: 450px; bottom: 450px;
-webkit-animation-delay: 1.2s; -webkit-animation-delay: 1.2s;
animation-delay: 1.2s; animation-delay: 1.2s;
} }
.medium-stars .star:nth-child(12) { .medium-stars .star:nth-child(12) {
left: 340px; left: 340px;
bottom: 180px; bottom: 180px;
-webkit-animation-delay: 1.1s; -webkit-animation-delay: 1.1s;
animation-delay: 1.1s; animation-delay: 1.1s;
} }
@keyframes star-blink { @keyframes star-blink {
50% { 50% {
width: 4px; width: 4px;
height: 4px; height: 4px;
opacity: 1; opacity: 1;
} }
} }
.star-fall { .star-fall {
position: relative; position: relative;
border-radius: 2px; border-radius: 2px;
width: 80px; width: 80px;
height: 2px; height: 2px;
overflow: hidden; overflow: hidden;
-webkit-transform: rotate(-20deg); -webkit-transform: rotate(-20deg);
transform: rotate(-20deg); transform: rotate(-20deg);
} }
.star-fall:after { .star-fall:after {
content: ''; content: '';
position: absolute; position: absolute;
width: 50px; width: 50px;
height: 2px; height: 2px;
background: -webkit-gradient(linear, right top, left top, from(rgba(0, 0, 0, 0)), to(rgba(255, 255, 255, 0.4))); 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%); background: linear-gradient(to left, rgba(0, 0, 0, 0) 0%, rgba(255, 255, 255, 0.4) 100%);
left: 100%; left: 100%;
-webkit-animation: star-fall 3.6s linear infinite; -webkit-animation: star-fall 3.6s linear infinite;
animation: star-fall 3.6s linear infinite; animation: star-fall 3.6s linear infinite;
} }
.star-fall:nth-child(1) { .star-fall:nth-child(1) {
left: 80px; left: 80px;
bottom: -100px; bottom: -100px;
} }
.star-fall:nth-child(1):after { .star-fall:nth-child(1):after {
-webkit-animation-delay: 2.4s; -webkit-animation-delay: 2.4s;
animation-delay: 2.4s; animation-delay: 2.4s;
} }
.star-fall:nth-child(2) { .star-fall:nth-child(2) {
left: 200px; left: 200px;
bottom: -200px; bottom: -200px;
} }
.star-fall:nth-child(2):after { .star-fall:nth-child(2):after {
-webkit-animation-delay: 2s; -webkit-animation-delay: 2s;
animation-delay: 2s; animation-delay: 2s;
} }
.star-fall:nth-child(3) { .star-fall:nth-child(3) {
left: 430px; left: 430px;
bottom: -50px; bottom: -50px;
} }
.star-fall:nth-child(3):after { .star-fall:nth-child(3):after {
-webkit-animation-delay: 3.6s; -webkit-animation-delay: 3.6s;
animation-delay: 3.6s; animation-delay: 3.6s;
} }
.star-fall:nth-child(4) { .star-fall:nth-child(4) {
left: 400px; left: 400px;
bottom: 100px; bottom: 100px;
} }
.star-fall:nth-child(4):after { .star-fall:nth-child(4):after {
-webkit-animation-delay: 0.2s; -webkit-animation-delay: 0.2s;
animation-delay: 0.2s; animation-delay: 0.2s;
} }
@-webkit-keyframes star-fall { @-webkit-keyframes star-fall {
20% { 20% {
left: -100%; left: -100%;
} }
100% {
left: -100%; 100% {
} left: -100%;
}
} }
@keyframes star-fall { @keyframes star-fall {
20% { 20% {
left: -100%; left: -100%;
} }
100% {
left: -100%; 100% {
} left: -100%;
}
} }
</style> </style>
+20 -15
Zobrazit soubor
@@ -53,12 +53,12 @@
<view class="poup pa-36" scroll-y="auto"> <view class="poup pa-36" scroll-y="auto">
<view class="info flex"> <view class="info flex">
<view class="poup-logo pa-4 shadow-24"> <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>
<view class="pl-24 info-detail"> <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"> <view class="poup-tag ml--10 text-size-n mt-10 text-grey">
{{ blogDetail.description }} {{ blogDetail.blogDesc }}
</view> </view>
</view> </view>
</view> </view>
@@ -69,12 +69,12 @@
<!-- 博客预览图 --> <!-- 博客预览图 -->
<view class="mt-24"> <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> mode="aspectFill"></tm-images>
</view> </view>
</view> </view>
<view class="poup-link flex flex-center mb-24"> <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> <tm-button text theme="white" @click="blogDetailPoupShow = false">关闭</tm-button>
</view> </view>
</tm-poup> </tm-poup>
@@ -117,7 +117,6 @@ export default {
data() { data() {
return { return {
blogDetailPoupShow: false, blogDetailPoupShow: false,
blogDetail: this.$haloPluginsConfig.autoSubmitLink.blogDetail,
form: { form: {
url: '', // 网址 url: '', // 网址
name: '', // 名称 name: '', // 名称
@@ -129,10 +128,16 @@ export default {
}; };
}, },
computed: { computed: {
caclSiteThumbnail(val) { haloPluginConfigs(){
return this.$tm.vx.getters().getConfigs.pluginConfig;
},
blogDetail() {
return this.haloPluginConfigs.submitLink;
},
calcSiteThumbnail(val) {
return val => { return val => {
if (!val) return ''; if (!val) return '';
if (val.charAt(val.length - 1) != '/') { if (val.charAt(val.length - 1) !== '/') {
val = val + '/'; val = val + '/';
} }
return 'https://image.thum.io/get/width/1000/crop/800/' + val; return 'https://image.thum.io/get/width/1000/crop/800/' + val;
@@ -140,17 +145,17 @@ export default {
}, },
calcBlogContent() { calcBlogContent() {
return ` return `
博客名称:${this.blogDetail.name} 博客名称:${this.blogDetail.blogName}
博客地址:${this.blogDetail.url} 博客地址:${this.blogDetail.blogUrl}
博客logo${this.blogDetail.logo} 博客logo${this.blogDetail.blogLogo}
博客简介:${this.blogDetail.description} 博客简介:${this.blogDetail.blogDesc}
` `
}, },
calcBlogCoupon() { calcBlogCoupon() {
return { return {
img: this.blogDetail.logo, img: this.blogDetail.blogLogo,
title: this.blogDetail.name, title: this.blogDetail.blogName,
time: this.blogDetail.description, time: this.blogDetail.blogDesc,
btnText: '友链详情' btnText: '友链详情'
} }
} }
+144 -140
Zobrazit soubor
@@ -1,151 +1,155 @@
<template> <template>
<view class="app-page"> <view class="app-page">
<view v-if="loading != 'success'" class="loading-wrap"> <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>
<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>
<block v-else> <block v-else>
<view class="empty" v-if="dataList.length == 0"><tm-empty icon="icon-shiliangzhinengduixiang-" <view class="empty" v-if="dataList.length == 0">
label="该标签下暂无文章"></tm-empty></view> <tm-empty icon="icon-shiliangzhinengduixiang-"
<block v-else> label="该标签下暂无文章"></tm-empty>
<block v-for="(article, index) in dataList" :key="article.metadata.name"> </view>
<!-- 文章卡片 --> <block v-else>
<tm-translate animation-name="fadeUp" :wait="calcAniWait(index)"> <block v-for="(article, index) in dataList" :key="article.metadata.name">
<article-card :article="article" @on-click="fnToArticleDetail"></article-card></tm-translate> <!-- 文章卡片 -->
</block> <tm-translate animation-name="fadeUp" :wait="calcAniWait(index)">
<view class="load-text">{{ loadMoreText }}</view> <article-card :article="article" @on-click="fnToArticleDetail"></article-card>
</block> </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> <tm-flotbutton @click="fnToTopPage" color="light-blue" size="m" icon="icon-angle-up"></tm-flotbutton>
</block> </block>
</view> </view>
</template> </template>
<script> <script>
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue'; import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue'; import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue'; import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue'; import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
import ArticleCard from '@/components/article-card/article-card.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: '加载中...',
dataList: [],
hasNext:false,
isLoadMore: false,
loadMoreText: ''
};
},
onLoad(e) { export default {
this.name = e.name; components: {
this.queryParams.name = this.name; tmSkeleton,
this.pageTitle = e.title; tmTranslate,
this.fnGetData(); tmFlotbutton,
}, tmEmpty,
onPullDownRefresh() { ArticleCard
this.isLoadMore = false; },
this.queryParams.page = 0; data() {
this.fnGetData(); return {
}, loading: 'loading',
onReachBottom(e) { queryParams: {
if (this.hasNext) { name: "",
this.queryParams.page += 1; size: 10,
this.isLoadMore = true; page: 0
this.fnGetData(); },
} else { name: '',
uni.showToast({ pageTitle: '加载中...',
icon: 'none',
title: '没有更多数据了' dataList: [],
}); hasNext: false,
} isLoadMore: false,
}, loadMoreText: ''
methods: { };
fnGetData() { },
// uni.showLoading({
// mask: true, onLoad(e) {
// title: '加载中...' this.name = e.name;
// }); this.queryParams.name = this.name;
// 设置状态为加载中 this.pageTitle = e.title;
if (!this.isLoadMore) { this.fnGetData();
this.loading = 'loading'; },
} onPullDownRefresh() {
this.loadMoreText = '加载中...'; this.isLoadMore = false;
this.$httpApi.v2 this.queryParams.page = 0;
.getPostByTagName(this.name, this.queryParams) this.fnGetData();
.then(res => { },
this.fnSetPageTitle(`${this.pageTitle} (共${res.total}篇)`); onReachBottom(e) {
this.hasNext = res.hasNext; if (this.hasNext) {
if (this.isLoadMore) { this.queryParams.page += 1;
this.dataList = this.dataList.concat(res.items); this.isLoadMore = true;
} else { this.fnGetData();
this.dataList = res.items; } else {
} uni.showToast({
this.loadMoreText = res.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~'; icon: 'none',
setTimeout(() => { title: '没有更多数据了'
this.loading = 'success'; });
}, 500); }
}) },
.catch(err => { methods: {
console.error(err); fnGetData() {
this.loading = 'error'; // uni.showLoading({
this.loadMoreText = '加载失败,请下拉刷新!'; // mask: true,
}) // title: '加载中...'
.finally(() => { // });
setTimeout(() => { // 设置状态为加载中
uni.hideLoading(); if (!this.isLoadMore) {
uni.stopPullDownRefresh(); this.loading = 'loading';
}, 500); }
}); this.loadMoreText = '加载中...';
}, this.$httpApi.v2
//跳转文章详情 .getPostByTagName(this.name, this.queryParams)
fnToArticleDetail(article) { .then(res => {
uni.navigateTo({ this.fnSetPageTitle(`${this.pageTitle} (共${res.total}篇)`);
url: '/pagesA/article-detail/article-detail?name=' + article.metadata.name, this.hasNext = res.hasNext;
animationType: 'slide-in-right' 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> </script>
<style lang="scss"> <style lang="scss">
.app-page { .app-page {
width: 100vw; width: 100vw;
min-height: 100vh; min-height: 100vh;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
padding: 24rpx 0; padding: 24rpx 0;
background-color: #fafafd; background-color: #fafafd;
} }
.loading-wrap { .loading-wrap {
padding: 0 24rpx; padding: 0 24rpx;
min-height: 100vh; min-height: 100vh;
} }
.empty { .empty {
height: 60vh; height: 60vh;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
</style> </style>
+5 -5
Zobrazit soubor
@@ -1,13 +1,13 @@
<template> <template>
<view>文章标签页面</view> <view>文章标签页面</view>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return {}; return {};
}, },
methods: {} methods: {}
}; };
</script> </script>
+15 -13
Zobrazit soubor
@@ -1,25 +1,27 @@
<template> <template>
<view class="app-page"><web-view :src="webUrl"></web-view></view> <view class="app-page">
<web-view :src="webUrl"></web-view>
</view>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
title: '', title: '',
webUrl: '' webUrl: ''
}; };
}, },
onLoad(e) { onLoad(e) {
const { title, url } = JSON.parse(e.query.data); const {title, url} = JSON.parse(e.query.data);
this.webUrl = url; this.webUrl = url;
this.fnSetPageTitle(title); this.fnSetPageTitle(title);
} }
}; };
</script> </script>
<style scoped> <style scoped>
.app-page { .app-page {
width: 100vw; width: 100vw;
} }
</style> </style>
+1 -6
Zobrazit soubor
@@ -8,11 +8,6 @@ const router = createRouter({
platform: process.env.VUE_APP_PLATFORM, platform: process.env.VUE_APP_PLATFORM,
routes: [...ROUTES] routes: [...ROUTES]
}); });
import {
checkHasWxLogin,
checkHasAdminLogin
} from '@/utils/auth.js'
//全局路由前置守卫 //全局路由前置守卫
router.beforeEach((to, from, next) => { router.beforeEach((to, from, next) => {
@@ -26,4 +21,4 @@ router.afterEach((to, from) => {
export { export {
router, router,
RouterMount RouterMount
} }
-49
Zobrazit soubor
@@ -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
Zobrazit soubor
@@ -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
Zobrazit soubor
@@ -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
Zobrazit soubor
@@ -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: ''
})
}
},
},
};
+3 -3
Zobrazit soubor
@@ -7,7 +7,7 @@ export const Platform = {
* 检查当前环境是什么环境 * 检查当前环境是什么环境
*/ */
export const checkPlatform = (name) => { export const checkPlatform = (name) => {
return uni.getSystemInfoSync().platform == name; return uni.getSystemInfoSync().platform === name;
} }
// 默认的应用设置 // 默认的应用设置
@@ -20,7 +20,7 @@ export const _DefaultAppSettings = {
}, },
// 布局配置 // 布局配置
layout: { layout: {
// h_row_col1 = 一行一列 // h_row_col1 = 一行一列
// h_row_col2 = 一行两列 // h_row_col2 = 一行两列
home: 'h_row_col1', home: 'h_row_col1',
// lr_image_text=左图右文 // lr_image_text=左图右文
@@ -51,7 +51,7 @@ export const _DefaultAppSettings = {
}, },
about: { about: {
showAdmin: false, // 显示后台登录入口 showAdmin: false, // 显示后台登录入口
showAllCount: false, // 默认显示所有的统计信息(关于页面) showAllCount: false, // 默认显示所有的统计信息(关于页面)
}, },
// 文章配置 // 文章配置
article: { article: {
+144 -147
Zobrazit soubor
@@ -10,160 +10,157 @@
* 修改时间: * 修改时间:
*/ */
import HaloConfig from '@/config/halo.config.js';
import HaloTokenConfig from '@/config/token.config.js' import HaloTokenConfig from '@/config/token.config.js'
import { import {getAppConfigs} from '@/config/index.js'
logTypes,
logUtils
} from '@/utils/halo.logs.js'
const utils = { const utils = {
/** /**
* 检查是否为http/https链接 * 检查是否为http/https链接
*/ */
checkIsUrl: function(s) { checkIsUrl: function (s) {
var reg = /^(http(s)?:\/\/)/i; var reg = /^(http(s)?:\/\/)/i;
return reg.test(s) return reg.test(s)
}, },
// 检查链接 // 检查链接
checkUrl: function(url) { checkUrl: function (url) {
if (!url) return ''; if (!url) return '';
if (!this.checkIsUrl(url)) return HaloTokenConfig.BASE_API + url; if (!this.checkIsUrl(url)) return HaloTokenConfig.BASE_API + url;
return url return url
}, },
// 检查封面图 // 检查封面图
checkThumbnailUrl: function(thumbnail, mustRealUrl = false) { checkThumbnailUrl: function (thumbnail, mustRealUrl = false) {
if (!thumbnail && mustRealUrl) { if (!thumbnail && mustRealUrl) {
return HaloConfig.defaultStaticThumbnailUrl return this.checkUrl(getAppConfigs().imagesConfig.defaultStaticThumbnailUrl);
} }
let _url = HaloConfig.defaultThumbnailUrl let _url = this.checkUrl(getAppConfigs().imagesConfig.defaultThumbnailUrl);
if (_url) { if (_url) {
if (_url.indexOf('?') == -1) { if (_url.indexOf('?') === -1) {
_url += `?next-v=${new Date().getTime()}` _url += `?next-v=${new Date().getTime()}`
} else { } else {
_url += `&next-v=${new Date().getTime()}` _url += `&next-v=${new Date().getTime()}`
} }
} }
if (!thumbnail) return _url; if (!thumbnail) return _url;
if (!this.checkIsUrl(thumbnail)) return HaloTokenConfig.BASE_API + thumbnail; if (!this.checkIsUrl(thumbnail)) return HaloTokenConfig.BASE_API + thumbnail;
return thumbnail return thumbnail
}, },
// 检查图片 // 检查图片
checkImageUrl: function(image) { checkImageUrl: function (image) {
let _url = HaloConfig.defaultImageUrl let _url
if (_url) { this.checkUrl(getAppConfigs().imagesConfig.defaultImageUrl);
if (_url.indexOf('?') == -1) { if (_url) {
_url += `?next-v=${new Date().getTime()}` if (_url.indexOf('?') === -1) {
} else { _url += `?next-v=${new Date().getTime()}`
_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; if (!image) return _url;
return image if (!this.checkIsUrl(image)) return HaloTokenConfig.BASE_API + image;
}, return image
},
// 检查头像 // 检查头像
checkAvatarUrl: function(avatar, isAdmin = false) { checkAvatarUrl: function (avatar) {
if (isAdmin) return HaloConfig.author.avatar; if (!avatar) {
if (!avatar) { let _url = this.checkUrl(getAppConfigs().imagesConfig.defaultAvatarUrl);
let _url = HaloConfig.defaultAvatarUrl if (_url) {
if (_url) { if (_url.indexOf('?') === -1) {
if (_url.indexOf('?') == -1) { _url += `?next-v=${new Date().getTime()}`
_url += `?next-v=${new Date().getTime()}` } else {
} else { _url += `&next-v=${new Date().getTime()}`
_url += `&next-v=${new Date().getTime()}` }
} }
} return _url;
return _url; }
} if (!this.checkIsUrl(avatar)) return HaloTokenConfig.BASE_API + avatar;
if (!this.checkIsUrl(avatar)) return HaloTokenConfig.BASE_API + avatar; return avatar
return avatar },
},
// 检查文件类型 // 检查文件类型
fnCheckIsFileType(type, attachment) { fnCheckIsFileType(type, attachment) {
if (!attachment) return false; if (!attachment) return false;
if (!attachment.mediaType) return false; if (!attachment.mediaType) return false;
if (type == 'video') return attachment.mediaType.indexOf('video/') != -1; if (type === 'video') return attachment.mediaType.indexOf('video/') !== -1;
else if (type == 'image') return attachment.mediaType.indexOf('image/') != -1; else if (type === 'image') return attachment.mediaType.indexOf('image/') !== -1;
else return false; else return false;
}, },
groupData: function(arr, fun) { groupData: function (arr, fun) {
const groups = {} const groups = {}
arr.forEach((el) => { arr.forEach((el) => {
const group = fun(el) const group = fun(el)
groups[group] = groups[group] || [] groups[group] = groups[group] || []
groups[group].push(el) groups[group].push(el)
}) })
return Object.keys(groups).map((group) => { return Object.keys(groups).map((group) => {
// 更改data的数据结构 可以改变新数据的结构 data即为newData的数组中每个数据的结构 // 更改data的数据结构 可以改变新数据的结构 data即为newData的数组中每个数据的结构
let data = { let data = {
groupName: group, groupName: group,
data: groups[group] data: groups[group]
} }
return data return data
}) })
}, },
/** /**
* 数据分组 * 数据分组
* @param {Object} oldData 数据源 * @param {Object} oldData 数据源
* @param {Object} prop 分组属性 * @param {Object} prop 分组属性
*/ */
arrayGroupBy: function(oldData, prop) { arrayGroupBy: function (oldData, prop) {
const newData = this.groupData(oldData, (item) => { const newData = this.groupData(oldData, (item) => {
return item[prop] return item[prop]
}) })
return newData return newData
}, },
/** /**
* 深克隆 * 深克隆
* @param {Object} obj 数据源 * @param {Object} obj 数据源
*/ */
deepClone(obj) { deepClone(obj) {
var objClone = Array.isArray(obj) ? [] : {}; var objClone = Array.isArray(obj) ? [] : {};
if (obj && typeof obj === "object") { if (obj && typeof obj === "object") {
for (const key in obj) { for (const key in obj) {
if (obj.hasOwnProperty(key)) { if (obj.hasOwnProperty(key)) {
if (obj[key] && typeof obj[key] === "object") { if (obj[key] && typeof obj[key] === "object") {
objClone[key] = this.deepClone(obj[key]); objClone[key] = this.deepClone(obj[key]);
} else { } else {
objClone[key] = obj[key]; objClone[key] = obj[key];
} }
} }
} }
} }
return objClone; return objClone;
}, },
/** /**
* 复制内容到剪贴板 * 复制内容到剪贴板
* @param {Object} obj 数据源 * @param {Object} obj 数据源
*/ */
copyText(content, tips = '复制成功') { copyText(content, tips = '复制成功') {
uni.setClipboardData({ uni.setClipboardData({
data: content, data: content,
showToast: false, showToast: false,
success: () => { success: () => {
if (tips) { if (tips) {
uni.showToast({ uni.showToast({
icon: 'none', icon: 'none',
title: tips title: tips
}) })
} }
} }
}) })
}, },
previewImage(list) { previewImage(list) {
list = list.map(item => { list = list.map(item => {
return this.checkUrl(item) return this.checkUrl(item)
}) })
uni.previewImage({ uni.previewImage({
urls: list, urls: list,
loop: true loop: true
}) })
} }
}; };