@@ -9,15 +9,19 @@ import http from '@/utils/request';
9
9
import store from '@/utils/store';
10
10
import { onMounted, ref, watch, nextTick } from 'vue';
11
11
import { useRoute, useRouter } from 'vue-router';
12
- import { setTitle } from '@/utils/tools';
12
+ import { FormatTime, setTitle } from '@/utils/tools';
13
13
import { Poster } from '@/utils/types';
14
- import { UploadFileInfo, AutoCompleteInst } from 'naive-ui';
14
+ import { UploadFileInfo, AutoCompleteInst, useMessage } from 'naive-ui';
15
15
16
16
const route = useRoute();
17
17
const router = useRouter();
18
18
19
19
// 初始化数据
20
- const poster = ref({
20
+ const draftData = store.last_draft[router.currentRoute.value.fullPath]
21
+ console.debug(draftData)
22
+ const hasDraft = ref(!!draftData);
23
+
24
+ const BLANK_POSTER = JSON.stringify({
21
25
id: 0,
22
26
title: "",
23
27
text: "",
@@ -30,6 +34,7 @@ const poster = ref({
30
34
plugins: "[]",
31
35
tags: [] as string[],
32
36
} as Poster)
37
+ const poster = ref<Poster>(JSON.parse(BLANK_POSTER))
33
38
34
39
// 上传图片
35
40
const fileList = ref<UploadFileInfo[]>([])
@@ -183,12 +188,61 @@ function PostPoster() {
183
188
}
184
189
}
185
190
191
+ const draft_use_modal = ref(false);
192
+ let ConfirmUseDraft: (res: boolean) => void;
193
+ const OnUseDraft = () => {
194
+ draft_use_modal.value = true;
195
+ return new Promise<null>((resolve, reject) => {
196
+ ConfirmUseDraft = (res) => {
197
+ draft_use_modal.value = false;
198
+ if (res) resolve(null)
199
+ else reject()
200
+ }
201
+ })
202
+ }
203
+
204
+ const original = ref<Poster>();
205
+ const DiscardDraft = () => {
206
+ delete store.last_draft[router.currentRoute.value.fullPath];
207
+ if (original.value) {
208
+ poster.value = original.value;
209
+ }
210
+ else {
211
+ poster.value = JSON.parse(BLANK_POSTER);
212
+ }
213
+ hasDraft.value = false;
214
+ }
215
+
216
+ watch(() => poster.value, () => {
217
+ if (JSON.stringify(poster.value) === BLANK_POSTER) return;
218
+ store.last_draft[router.currentRoute.value.fullPath] = {
219
+ poster: JSON.stringify(poster.value),
220
+ timestamp: Date.now()
221
+ };
222
+ }, { deep: true })
223
+
186
224
onMounted(async () => {
187
225
LoadClaims();
188
226
poster.value.id = Number(route.params.id);
189
- if (poster.value.id == 0) setTitle('发布', '话廊');
227
+ const isCreate = poster.value.id == 0;
228
+ if (isCreate) {
229
+ setTitle('发布', '话廊');
230
+ if (hasDraft.value) {
231
+ poster.value = JSON.parse(draftData.poster);
232
+ window.$message.success(`已恢复 ${FormatTime(draftData.timestamp / 1000)} 的草稿 OvO`);
233
+ }
234
+ }
190
235
else {
191
236
await LoadPoster()
237
+ if (hasDraft.value) {
238
+ original.value = poster.value;
239
+ OnUseDraft().then(() => {
240
+ poster.value = JSON.parse(draftData.poster);
241
+ window.$message.success(`已恢复 ${FormatTime(draftData.timestamp / 1000)} 的草稿 OvO`);
242
+ }).catch(() => {
243
+ DiscardDraft()
244
+ })
245
+ }
192
246
setTitle('编辑', '话廊');
193
247
}
194
248
})
@@ -223,8 +277,9 @@ onMounted(async () => {
223
277
<n-dynamic-tags v-model:value="poster.tags">
224
278
<template #input="{ submit, deactivate }">
225
279
<n-auto-complete ref="autoCompleteInstRef" v-model:value="rawTag" size="small" :clear-after-select="true"
226
- :options="tags" @select="($event: any) => { submit($event); deactivate() }" @blur="() => { deactivate(); rawTag = ''; }" placeholder="选一个吧,或者输入你想要的" :get-show="() => true"
227
- :status="rawTagLengthLimit"/>
280
+ :options="tags" @select="($event: any) => { submit($event); deactivate() }"
281
+ @blur="() => { deactivate(); rawTag = ''; }" placeholder="选一个吧,或者输入你想要的" :get-show="() => true"
282
+ :status="rawTagLengthLimit" />
228
283
</template>
229
284
</n-dynamic-tags>
230
285
</n-space>
@@ -241,6 +296,12 @@ onMounted(async () => {
241
296
</n-space>
242
297
243
298
<n-space justify="end">
299
+ <n-popconfirm v-if="hasDraft" @positive-click="DiscardDraft" positive-text="确定" negative-text="取消">
300
+ <template #trigger>
301
+ <n-button type="error" ghost>放弃草稿</n-button>
302
+ </template>
303
+ 汝真放弃耶?放弃的草稿无法恢复。
304
+ </n-popconfirm>
244
305
<n-popconfirm @positive-click="PostPoster" :show-icon="false" positive-text="确定" negative-text="取消">
245
306
<template #trigger>
246
307
<n-button :disabled="posting" type="success" ghost>张贴Poster</n-button>
@@ -253,5 +314,10 @@ onMounted(async () => {
253
314
254
315
<n-modal v-model:show="image_remove_modal" preset="dialog" title="汝真断舍离耶?" positive-text="确认" negative-text="取消"
255
316
@positive-click="ConfirmRemoveImage(true)" @negative-click="ConfirmRemoveImage(false)" />
317
+
318
+ <n-modal v-if="hasDraft" v-model:show="draft_use_modal" preset="dialog" title="要对 话廊 使用 草稿 吗?"
319
+ :content="`现有一个 ${FormatTime(draftData.timestamp / 1000)} 的草稿, 放弃后无法恢复`"
320
+ positive-text="使用" negative-text="放弃" :closable="false" :closeOnEsc="false" :maskClosable="false"
321
+ @positive-click="ConfirmUseDraft(true)" @negative-click="ConfirmUseDraft(false)" />
256
322
</div>
257
323
</template>
0 commit comments