Files
yunzerwebsiteallinone/uniapp/pages/tools/notepad/edit.vue
T

243 lines
5.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="page">
<view class="form-card">
<view class="field">
<text class="field-label">标题</text>
<u-input
v-model="form.title"
placeholder="输入标题"
placeholder-style="color:#94a3b8"
:maxlength="80"
border="none"
:font-size="15"
color="#0f172a"
clearable
/>
</view>
<view class="field content-field">
<text class="field-label">内容</text>
<NoteRichEditor
v-model="form.content"
class="note-editor"
placeholder="记录你的想法..."
/>
</view>
<u-cell class="switch-cell" :border="false" title="置顶笔记">
<template #icon>
<FaIcon name="thumbtack" :color="form.pinned ? '#2563eb' : '#909399'" :size="16" />
</template>
<template #value>
<u-switch v-model="form.pinned" active-color="#2563eb" size="20" />
</template>
</u-cell>
</view>
<view v-if="noteId && meta.updatedAt" class="meta">
<text>最近更新:{{ formatDate(meta.updatedAt, true) }}</text>
</view>
<view class="footer">
<view v-if="noteId" class="footer-btn">
<u-button type="error" plain text="删除" @click="onDelete" />
</view>
<view class="footer-btn">
<u-button
type="primary"
color="#2563eb"
shape="circle"
:loading="saving"
loading-text="保存中..."
text="保存"
@click="onSave"
/>
</view>
</view>
</view>
</template>
<script setup>
import { ref, reactive } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { getNote, createNote, updateNote, deleteNote } from '@/api/note.js'
import { formatDate } from '@/utils/date.js'
import { injectTableInlineStyles } from '@/utils/table-editor.js'
import NoteRichEditor from '@/components/NoteRichEditor.vue'
const noteId = ref('')
const saving = ref(false)
const form = reactive({
title: '',
content: '',
pinned: false
})
const meta = reactive({
updatedAt: 0
})
onLoad(async (query) => {
if (query?.id) {
noteId.value = query.id
uni.setNavigationBarTitle({ title: '编辑笔记' })
await loadNote(query.id)
} else {
uni.setNavigationBarTitle({ title: '新建笔记' })
}
})
async function loadNote(id) {
try {
const note = await getNote(id)
if (!note) {
uni.showToast({ title: '笔记不存在', icon: 'none' })
setTimeout(() => uni.navigateBack(), 800)
return
}
form.title = note.title
form.content = injectTableInlineStyles(note.content || '')
form.pinned = !!note.pinned
meta.updatedAt = note.updatedAt
} catch (e) {
uni.showToast({ title: '加载失败', icon: 'none' })
}
}
async function onSave() {
if (saving.value) return
if (!form.title.trim() && !form.content.trim()) {
uni.showToast({ title: '请输入标题或内容', icon: 'none' })
return
}
saving.value = true
try {
const formattedContent = injectTableInlineStyles(form.content)
if (noteId.value) {
await updateNote(noteId.value, {
title: form.title,
content: formattedContent,
pinned: form.pinned
})
} else {
await createNote({
title: form.title,
content: formattedContent,
pinned: form.pinned
})
}
uni.showToast({ title: '保存成功', icon: 'success' })
setTimeout(() => uni.navigateBack(), 400)
} catch (e) {
uni.showToast({ title: '保存失败', icon: 'none' })
} finally {
saving.value = false
}
}
function onDelete() {
uni.showModal({
title: '删除笔记',
content: '删除后无法恢复,确定继续吗?',
success: async (res) => {
if (!res.confirm) return
try {
await deleteNote(noteId.value)
uni.showToast({ title: '已删除', icon: 'success' })
setTimeout(() => uni.navigateBack(), 400)
} catch (e) {
uni.showToast({ title: '删除失败', icon: 'none' })
}
}
})
}
</script>
<style lang="scss" scoped>
@import '@/src/styles/page-common.scss';
.page {
min-height: 100vh;
background: $color-bg-page;
display: flex;
flex-direction: column;
padding: 24rpx $page-padding-x 0;
padding-bottom: calc(130rpx + env(safe-area-inset-bottom));
}
.form-card {
@include card;
padding: 8rpx 0;
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
}
.field {
padding: 24rpx 28rpx;
& + & {
border-top: 1rpx solid $color-divider;
}
}
.field-label {
display: block;
font-size: 24rpx;
color: $color-text-muted;
margin-bottom: 12rpx;
}
.content-field {
flex: 1;
display: flex;
flex-direction: column;
padding: 24rpx 28rpx 0 28rpx;
overflow: hidden;
border-top: 1rpx solid $color-divider;
min-height: 520rpx;
}
.note-editor {
width: 100%;
flex: 1;
min-height: 440rpx;
box-sizing: border-box;
display: flex;
flex-direction: column;
background: #f5f7fa;
border-radius: 12rpx;
padding: 20rpx;
}
.switch-cell {
border-top: 1rpx solid $color-divider;
}
.meta {
margin: 20rpx 0;
padding: 0 8rpx;
font-size: 24rpx;
color: $color-text-muted;
}
.footer {
position: fixed;
left: 0;
right: 0;
bottom: 0;
display: flex;
gap: 20rpx;
padding: 20rpx $page-padding-x;
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
background: $color-card;
border-top: 1rpx solid $color-border;
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.04);
z-index: 10;
}
.footer-btn {
flex: 1;
}
</style>