This commit is contained in:
Timi
2026-01-28 16:35:31 +08:00
parent 965743be38
commit e67d9eeecc
13 changed files with 331 additions and 6 deletions

View File

@ -2,7 +2,7 @@
<scroll-view class="index" scroll-y type="list">
<view class="container">
<view class="header">
<image class="logo" src="/assets/image/logo.png"></image>
<image class="logo" src="/assets/image/logo.jpg"></image>
<text>
<text class="name gao">小糕</text>
<text>和</text>

View File

@ -0,0 +1,7 @@
{
"usingComponents": {
"t-icon": "tdesign-miniprogram/icon/icon",
"t-navbar": "tdesign-miniprogram/navbar/navbar"
},
"disableScroll": true
}

View File

@ -0,0 +1,66 @@
// pages/main/other/memo/index.less
.memo {
width: 100%;
min-height: 100vh;
position: relative;
.content {
width: 100%;
min-height: 100vh;
position: relative;
}
.status-card {
padding: 2rem 1.5rem;
display: flex;
justify-content: center;
}
.empty-hint {
padding: 1.5rem 1rem 0 1rem;
}
.container {
top: 0;
left: 0;
width: 100%;
position: absolute;
.editor {
width: 100%;
height: 100%;
border: .0625rem solid var(--theme-border-light);
padding: 1rem 1rem 2rem 1rem;
overflow: auto;
font-size: 1rem;
background: var(--theme-bg-primary);
box-sizing: border-box;
line-height: 1.5;
}
}
.toolbar {
left: 0;
width: 100%;
right: 100%;
height: 3.125rem;
bottom: 0;
border: .0625rem solid var(--theme-border-light);
padding: 0 1rem;
display: flex;
position: fixed;
background: var(--theme-bg-primary);
box-sizing: border-box;
align-items: center;
border-left: none;
border-right: none;
justify-content: space-between;
.icon {
&.active {
color: var(--theme-wx);
}
}
}
}

View File

@ -0,0 +1,162 @@
// 备忘录页面逻辑
import { ToolApi } from "../../../../api/ToolApi";
type EditorInputEvent = WechatMiniprogram.CustomEvent<{
html?: string;
text?: string;
}>;
interface MemoData {
formats: Record<string, unknown>;
placeholder: string;
editorHeight: number;
keyboardHeight: number;
isIOS: boolean;
isSaving: boolean;
isEditorReady: boolean;
contentHtml: string;
contentText: string;
}
Page({
data: <MemoData>{
formats: {},
placeholder: "开始输入...",
editorHeight: 300,
keyboardHeight: 0,
isIOS: false,
isSaving: false,
isEditorReady: false,
contentHtml: "",
contentText: ""
},
editorCtx: null as WechatMiniprogram.EditorContext | null,
pendingHtml: "",
hasSavedOnLeave: false,
hasLoadFailed: false,
async onLoad() {
const platform = wx.getSystemInfoSync().platform;
const isIOS = platform === "ios";
this.setData({ isIOS });
this.updatePosition(0);
this.bindKeyboardHeightChange();
await this.loadMemo();
},
onShow() {
this.hasSavedOnLeave = false;
},
async onUnload() {
await this.saveMemoOnLeave();
},
async onHide() {
await this.saveMemoOnLeave();
},
bindKeyboardHeightChange() {
let keyboardHeight = 0;
wx.onKeyboardHeightChange((res) => {
if (res.height === keyboardHeight) {
return;
}
const duration = 0 < res.height ? res.duration * 1000 : 0;
keyboardHeight = res.height;
setTimeout(() => {
wx.pageScrollTo({
scrollTop: 0,
success: () => {
this.updatePosition(keyboardHeight);
this.editorCtx?.scrollIntoView();
}
});
}, duration);
});
},
updatePosition(keyboardHeight: number) {
const toolbarHeight = 50;
const { windowHeight } = wx.getSystemInfoSync();
const editorHeight = 0 < keyboardHeight
? windowHeight - keyboardHeight - toolbarHeight
: windowHeight;
this.setData({ editorHeight, keyboardHeight });
},
onEditorReady() {
const query = wx.createSelectorQuery();
query.select("#memo-editor").context((res) => {
this.editorCtx = (res as { context?: WechatMiniprogram.EditorContext }).context || null;
this.setData({ isEditorReady: true });
this.applyPendingContent();
});
query.exec();
},
applyPendingContent() {
if (!this.editorCtx || !this.pendingHtml) {
return;
}
this.editorCtx.setContents({
html: this.pendingHtml
});
this.pendingHtml = "";
},
onStatusChange(e: WechatMiniprogram.CustomEvent<Record<string, unknown>>) {
this.setData({ formats: e.detail || {} });
},
format(e: WechatMiniprogram.BaseEvent) {
const { name, value } = e.target.dataset as { name?: string; value?: string | number };
if (!name || !this.editorCtx) {
return;
}
this.editorCtx.format(name, value);
},
onEditorInput(e: EditorInputEvent) {
const { html = "", text = "" } = e.detail || {};
this.setData({
contentHtml: html,
contentText: text
});
},
async loadMemo() {
wx.showLoading({ title: "加载中..", mask: true });
let shouldGoBack = false;
try {
const contentHtml = await ToolApi.getMemo();
this.pendingHtml = contentHtml;
this.setData({
contentHtml,
contentText: this.normalizeMemoText(contentHtml)
});
this.applyPendingContent();
} catch (error) {
console.error("加载备忘录失败", error);
this.hasLoadFailed = true;
shouldGoBack = true;
} finally {
wx.hideLoading();
if (shouldGoBack) {
wx.navigateBack({ delta: 1 });
}
}
},
normalizeMemoText(html: string) {
const normalized = html
.replace(/<[^>]*>/g, "")
.replace(/&nbsp;/g, " ")
.replace(/\s+/g, " ")
.trim();
return normalized;
},
async saveMemoOnLeave() {
if (this.hasLoadFailed || this.data.isSaving || this.hasSavedOnLeave) {
return;
}
this.hasSavedOnLeave = true;
this.setData({ isSaving: true });
wx.showLoading({ title: "保存中..", mask: true });
try {
await ToolApi.updateMemo(this.data.contentHtml || "");
} catch (error) {
console.error("保存备忘录失败", error);
} finally {
wx.hideLoading();
this.setData({ isSaving: false });
}
}
});

View File

@ -0,0 +1,65 @@
<!-- 备忘录页面 -->
<view class="custom-navbar">
<t-navbar class="custom-navbar" title="备忘录" left-arrow placeholder />
</view>
<view class="memo setting-bg">
<view class="content">
<view class="container" style="height:{{editorHeight}}px;">
<editor
id="memo-editor"
class="editor"
placeholder="{{placeholder}}"
bindready="onEditorReady"
bindinput="onEditorInput"
bindstatuschange="onStatusChange"
show-img-size="{{false}}"
show-img-toolbar="{{false}}"
show-img-resize="{{false}}"
/>
</view>
<view
class="toolbar"
catchtouchend="format"
hidden="{{0 < keyboardHeight ? false : true}}"
style="bottom: {{isIOS ? keyboardHeight : 0}}px"
>
<text
class="icon {{formats.header === 2 ? 'active' : ''}}"
data-name="header"
data-value="{{2}}"
>H2</text>
<text
class="icon {{formats.header === 3 ? 'active' : ''}}"
data-name="header"
data-value="{{3}}"
>H3</text>
<t-icon
class="icon {{formats.bold ? 'active' : ''}}"
name="textformat-bold"
data-name="bold"
/>
<t-icon
class="icon {{formats.italic ? 'active' : ''}}"
name="textformat-italic"
data-name="italic"
/>
<t-icon
class="icon {{formats.underline ? 'active' : ''}}"
name="textformat-underline"
data-name="underline"
/>
<t-icon
class="icon"
name="task"
data-name="list"
data-value="check"
/>
<t-icon
class="icon {{formats.list === 'bullet' ? 'active' : ''}}"
name="bulletpoint"
data-name="list"
data-value="bullet"
/>
</view>
</view>
</view>

View File

@ -4,7 +4,7 @@
<scroll-view class="info" scroll-y>
<view class="cotainer">
<view class="header">
<image class="logo" src="/assets/image/logo.png"></image>
<image class="logo" src="/assets/image/logo.jpg"></image>
<view>
<text>记录</text>
<text class="name gao">小糕</text>

View File

@ -14,7 +14,7 @@ Page({
{
title: "备忘录",
icon: "task-checked",
url: "/pages/main/other/portfolio/index"
url: "/pages/main/other/memo/index"
},
{
title: "专拍",