Files
YelayMaths/yelaymaths/pages/index/index.js
T
2026-09-30 16:47:27 +08:00

184 lines
5.4 KiB
JavaScript

// pages/index/index.js
const api = require('../../utils/api');
const store = require('../../utils/store');
const config = require('../../config/index');
const app = getApp();
const updateManager = wx.getUpdateManager();
const PAGE_SIZE = 10;
/** 广播文字默认色(红),配置里没填或填得不像颜色时用它 */
const DEFAULT_BROADCAST_COLOR = '#e60012';
/**
* 只认安全的颜色写法,其余一律回退默认色。
* 后台是文本框,填错一个字符不该把首页样式搞坏,也不该让这个值变成注入点。
*/
function safeColor(value) {
const v = String(value || '').trim();
if (/^#[0-9a-fA-F]{3}$|^#[0-9a-fA-F]{6}$|^#[0-9a-fA-F]{8}$/.test(v)) return v;
if (/^rgba?\([\d\s.,%]+\)$/.test(v)) return v;
if (/^hsla?\([\d\s.,%]+\)$/.test(v)) return v;
if (/^[a-zA-Z]{3,20}$/.test(v)) return v; // red / orange / tomato ...
return DEFAULT_BROADCAST_COLOR;
}
Page({
data: {
staticBase: config.STATIC_BASE_URL,
banners: [],
courseList: [],
freeCourseList: [],
articles: [],
page: 1,
articleTotal: 0,
loadingMore: false,
noMore: false,
title1: '',
title2: '',
title3: '',
footerText: '',
/** 首页信息广播文案,空则不显示整条 */
broadcast: '',
/** 文案超出宽度时才横向滚动 */
broadcastScroll: false,
/** 广播文字颜色,取自 home.broadcast_color */
broadcastColor: DEFAULT_BROADCAST_COLOR,
},
onLoad() {
// 等应用初始化完成再取配置,避免首屏读到空缓存
app.ready().then(() => this.applyConfig());
this.loadAll();
},
applyConfig() {
this.setData(
{
title1: store.cfg('home.title.paid'),
title2: store.cfg('home.title.trial'),
title3: store.cfg('home.title.public'),
footerText: store.cfg('home.footer_text'),
broadcast: store.cfg('home.broadcast') || '',
broadcastColor: safeColor(store.cfg('home.broadcast_color')),
broadcastScroll: false,
},
// 等渲染完再量宽度:只有真放不下才让它滚动,短文案就静静居中
() => this.measureBroadcast(),
);
},
/** 量一下广播文字有没有超出容器,超了才加滚动动画。量不到就当不超。 */
measureBroadcast() {
if (!this.data.broadcast) return;
const query = wx.createSelectorQuery().in(this);
query.select('.broadcast-body').boundingClientRect();
query.select('.broadcast-text').boundingClientRect();
query.exec((res) => {
const box = res && res[0];
const text = res && res[1];
if (!box || !text) return;
if (text.width > box.width) this.setData({ broadcastScroll: true });
});
},
loadAll() {
this.setData({ page: 1, noMore: false });
api
.getBanners()
.then((list) => this.setData({ banners: list || [] }))
.catch((err) => console.error('[index] 轮播加载失败', err));
api
.getHomeCourses()
.then((list) => this.setData({ courseList: list || [] }))
.catch((err) => console.error('[index] 新课加载失败', err));
api
.getHomeFreeCourses()
.then((list) => this.setData({ freeCourseList: list || [] }))
.catch((err) => console.error('[index] 试听列表加载失败', err));
api
.getArticles(1, PAGE_SIZE)
.then((res) => this.setData({ articles: res.items || [], articleTotal: res.total || 0, page: 1 }))
.catch((err) => console.error('[index] 文章加载失败', err));
},
onShow() {
updateManager.onCheckForUpdate(() => {});
updateManager.onUpdateReady(() => {
wx.showModal({
title: '更新提示',
showCancel: false,
content: '新版本已准备好,即将重启应用',
success: (res) => {
if (res.confirm) updateManager.applyUpdate();
},
});
});
updateManager.onUpdateFailed(() => {});
},
onPullDownRefresh() {
Promise.all([this.reload()]).then(() => wx.stopPullDownRefresh());
},
async reload() {
try {
const cfg = await api.getConfig();
store.setSiteConfig(cfg);
this.applyConfig();
} catch (err) {
console.warn('[index] 配置刷新失败', err);
}
this.loadAll();
},
onReachBottom() {
if (this.data.loadingMore || this.data.noMore) return;
const next = this.data.page + 1;
this.setData({ loadingMore: true });
api
.getArticles(next, PAGE_SIZE)
.then((res) => {
const merged = this.data.articles.concat(res.items || []);
this.setData({
articles: merged,
page: next,
loadingMore: false,
noMore: merged.length >= (res.total || 0),
});
})
.catch((err) => {
console.error('[index] 加载更多失败', err);
this.setData({ loadingMore: false });
});
},
toArticle(e) {
wx.navigateTo({ url: '/pages/WebPageDetails/WebPageDetails?id=' + e.currentTarget.dataset.id });
},
toNewCourse(e) {
wx.navigateTo({ url: '/pages/IndexNewCourseDetails/IndexNewCourseDetails?id=' + e.currentTarget.dataset.id });
},
toFreeCourse(e) {
wx.navigateTo({
url: '/pages/IndexFreeCourseDetails/IndexFreeCourseDetails?seriesNo=' + e.currentTarget.dataset.series,
});
},
onShareAppMessage() {
return { title: '叶雷讲数学', path: '/pages/index/index' };
},
onShareTimeline() {
return { title: '叶雷讲数学' };
},
});