add memo
This commit is contained in:
24
miniprogram/api/ToolApi.ts
Normal file
24
miniprogram/api/ToolApi.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { Network } from "../utils/Network";
|
||||
|
||||
/**
|
||||
* Tool 工具 API
|
||||
*/
|
||||
export class ToolApi {
|
||||
/**
|
||||
* 获取备忘录内容
|
||||
*/
|
||||
static getMemo(): Promise<string> {
|
||||
return Network.get<string>("/journal/tool/memo");
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新备忘录内容
|
||||
*
|
||||
* @param data - 备忘录内容
|
||||
*/
|
||||
static updateMemo(data: string): Promise<void> {
|
||||
return Network.post<void>("/journal/tool/memo/update", {
|
||||
data
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -10,6 +10,7 @@
|
||||
"pages/main/journal/editor/index",
|
||||
"pages/main/journal/map/index",
|
||||
"pages/main/journal/date/index",
|
||||
"pages/main/other/memo/index",
|
||||
"pages/main/other/portfolio/index",
|
||||
"pages/main/travel/detail/index",
|
||||
"pages/main/travel/editor/index",
|
||||
|
||||
BIN
miniprogram/assets/image/logo.jpg
Normal file
BIN
miniprogram/assets/image/logo.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 128 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 68 KiB |
@ -1,12 +1,12 @@
|
||||
const envArgs = {
|
||||
develop: {
|
||||
url: "http://localhost:8091"
|
||||
// url: "http://localhost:8091"
|
||||
// url: "https://api.imyeyu.dev"
|
||||
// url: "https://api.imyeyu.com"
|
||||
// url: "http://192.168.3.123:8091"
|
||||
// url: "http://192.168.3.137:8091"
|
||||
// url: "http://192.168.3.173:8091"
|
||||
// url: "http://192.168.3.174:8091"
|
||||
url: "http://192.168.3.174:8091"
|
||||
},
|
||||
trial: {
|
||||
url: "https://api.imyeyu.com"
|
||||
|
||||
@ -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>
|
||||
|
||||
7
miniprogram/pages/main/other/memo/index.json
Normal file
7
miniprogram/pages/main/other/memo/index.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
"t-icon": "tdesign-miniprogram/icon/icon",
|
||||
"t-navbar": "tdesign-miniprogram/navbar/navbar"
|
||||
},
|
||||
"disableScroll": true
|
||||
}
|
||||
66
miniprogram/pages/main/other/memo/index.less
Normal file
66
miniprogram/pages/main/other/memo/index.less
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
162
miniprogram/pages/main/other/memo/index.ts
Normal file
162
miniprogram/pages/main/other/memo/index.ts
Normal 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(/ /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 });
|
||||
}
|
||||
}
|
||||
});
|
||||
65
miniprogram/pages/main/other/memo/index.wxml
Normal file
65
miniprogram/pages/main/other/memo/index.wxml
Normal 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>
|
||||
@ -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>
|
||||
|
||||
@ -14,7 +14,7 @@ Page({
|
||||
{
|
||||
title: "备忘录",
|
||||
icon: "task-checked",
|
||||
url: "/pages/main/other/portfolio/index"
|
||||
url: "/pages/main/other/memo/index"
|
||||
},
|
||||
{
|
||||
title: "专拍",
|
||||
|
||||
Reference in New Issue
Block a user