Skip to content

Commit

Permalink
帖子回复功能完成,编辑器代码封装
Browse files Browse the repository at this point in the history
  • Loading branch information
lvzhenbo committed May 6, 2024
1 parent da127a8 commit 554745c
Show file tree
Hide file tree
Showing 7 changed files with 295 additions and 43 deletions.
51 changes: 48 additions & 3 deletions src/api/forum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,14 @@ export interface RateParams {
pid: string;
}

export interface NotificationParams {
last_updated: string;
interface ReplyParams {
noticetrimstr: string;
reppid: string;
formhash: string;
clienthash: string;
message: string;
noticeauthor: string;
tid: string;
}

const API = {
Expand Down Expand Up @@ -118,6 +124,30 @@ const API = {
action: 'newthread',
},
} as HttpOptions,
ReplyInfo: {
method: 'GET',
url: '/forum.php',
params: {
mobile: 'yes',
tsdmapp: '1',
mod: 'post',
action: 'reply',
},
} as HttpOptions,
Reply: {
method: 'POST',
url: '/forum.php',
params: {
mobile: 'yes',
tsdmapp: '1',
mod: 'post',
action: 'reply',
replysubmit: 'yes',
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
} as HttpOptions,
};

export const forumGroup = () => request(API.ForumGroup);
Expand Down Expand Up @@ -181,7 +211,7 @@ export const coinRemain = (params: RateParams) =>
},
});

export const notification = (params: NotificationParams) =>
export const notification = (params: { last_updated: string }) =>
request({
...API.Notification,
params: {
Expand All @@ -198,3 +228,18 @@ export const newThreadType = (params: string) =>
fid: params,
},
});

export const replyInfo = (params: { tid: string; repquote: string }) =>
request({
...API.ReplyInfo,
params: {
...API.ReplyInfo.params,
...params,
},
});

export const reply = (params: ReplyParams) =>
request({
...API.Reply,
data: params,
});
4 changes: 4 additions & 0 deletions src/components/Editor/CommendTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@
type: Object as PropType<Editor>,
default: null,
},
mode: {
type: String,
default: 'add',
},
});
const editorCMD = computed(() => props.editor.chain().focus());
Expand Down
39 changes: 39 additions & 0 deletions src/composables/useMyEditor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { useEditor } from '@tiptap/vue-3';
import StarterKit from '@tiptap/starter-kit';
import Color from '@tiptap/extension-color';
import TextStyle from '@tiptap/extension-text-style';
import Underline from '@tiptap/extension-underline';
import TextAlign from '@tiptap/extension-text-align';
import Image from '@tiptap/extension-image';

export const useMyEditor = () => {
const content = ref('');
const editor = useEditor({
content: content.value,
extensions: [
StarterKit,
Color,
TextStyle,
Underline,
TextAlign.configure({
types: ['heading', 'paragraph'],
}),
Image.configure({
inline: true,
}),
],
onUpdate: ({ editor }) => {
content.value = editor.getHTML();
},
editorProps: {
attributes: {
class: 'focus:outline-none focus:caret-[--ion-color-primary]',
},
},
});

return {
content,
editor,
};
};
33 changes: 2 additions & 31 deletions src/views/Thread/add.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,9 @@

<script setup lang="ts">
import { htmlToBBCode } from '@/utils/html2bbcode';
import { useEditor } from '@tiptap/vue-3';
import StarterKit from '@tiptap/starter-kit';
import Color from '@tiptap/extension-color';
import TextStyle from '@tiptap/extension-text-style';
import Underline from '@tiptap/extension-underline';
import TextAlign from '@tiptap/extension-text-align';
import Image from '@tiptap/extension-image';
import { useSettingStore } from '@/stores/modules/setting';
import { newThreadType } from '@/api/forum';
import { useMyEditor } from '@/composables/useMyEditor';
interface ThreadType {
typeid: number;
Expand All @@ -64,30 +58,7 @@
});
const route = useRoute();
const content = ref('');
const editor = useEditor({
content: content.value,
extensions: [
StarterKit,
Color,
TextStyle,
Underline,
TextAlign.configure({
types: ['heading', 'paragraph'],
}),
Image.configure({
inline: true,
}),
],
onUpdate: ({ editor }) => {
content.value = editor.getHTML();
},
editorProps: {
attributes: {
class: 'focus:outline-none focus:caret-[--ion-color-primary]',
},
},
});
const { editor, content } = useMyEditor();
const settingStore = useSettingStore();
const fid = ref('');
const threadTypeList = ref<ThreadType[]>([]);
Expand Down
8 changes: 4 additions & 4 deletions src/views/Thread/components/rateModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
const isOpen = defineModel('isOpen', { type: Boolean, default: false });
const props = defineProps({
pid: {
ratePid: {
type: String,
required: true,
},
Expand All @@ -98,18 +98,18 @@
const settingStore = useSettingStore();
watch(
() => props.pid,
() => props.ratePid,
(val) => {
console.log(val);
getRemainCoin();
// getRemainCoin();
},
);
const getRemainCoin = async () => {
try {
modalContent.value = false;
loading.value = true;
const res = await coinRemain({ tid: route.params.tid as string, pid: props.pid });
const res = await coinRemain({ tid: route.params.tid as string, pid: props.ratePid });
if (res.data) {
const data = JSON.parse(res.data);
if (data.status === 0) {
Expand Down
177 changes: 177 additions & 0 deletions src/views/Thread/components/replyModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
<template>
<IonModal :is-open="isOpen" @did-dismiss="isOpen = false">
<IonHeader>
<IonToolbar
:color="settingStore.isDark ? undefined : 'primary'"
class="!pt-[var(--safe-area-inset-top)]"
>
<IonButtons slot="start">
<IonButton @click="closeFunc(false)">
<IonIcon slot="icon-only" :icon="close" />
</IonButton>
</IonButtons>
<IonTitle>回复</IonTitle>
<IonButtons slot="end">
<!-- 确认按钮 -->
<IonButton @click="handleReply">
<IonIcon slot="icon-only" :icon="checkmark" />
</IonButton>
</IonButtons>
</IonToolbar>
</IonHeader>
<IonContent color="light">
<IonList :inset="true">
<IonItem>
<IonLabel>
<Editor :editor="editor" />
</IonLabel>
</IonItem>
</IonList>
<CommendTab slot="fixed" :editor="editor" mode="reply" />
</IonContent>
</IonModal>
</template>

<script setup lang="ts">
import { useSettingStore } from '@/stores/modules/setting';
import { close, checkmark } from 'ionicons/icons';
import { htmlToBBCode } from '@/utils/html2bbcode';
import { replyInfo, reply } from '@/api/forum';
import ClientHash from '@/utils/clientHashPlugin';
import { useMyEditor } from '@/composables/useMyEditor';
import { alertController, loadingController } from '@ionic/vue';
const isOpen = defineModel('isOpen', { type: Boolean, default: false });
const props = defineProps({
replyPid: {
type: String,
required: true,
},
});
const emits = defineEmits(['close']);
const route = useRoute();
const settingStore = useSettingStore();
const { editor, content } = useMyEditor();
const info = reactive({
noticetrimstr: '',
formhash: '',
noticeauthor: '',
});
watch(isOpen, (val) => {
if (val) {
getReplyInfo();
}
});
const closeFunc = (val: boolean) => {
emits('close', val);
};
const getReplyInfo = async () => {
const loading = await loadingController.create({
message: '获取信息中...',
});
await loading.present();
try {
const res = await replyInfo({ repquote: props.replyPid, tid: route.params.tid as string });
if (res.data) {
const data = JSON.parse(
res.data
.replace(/\n/g, '\\n')
.replace(/\r/g, '\\r')
.replace(/\t/g, '\\t')
// eslint-disable-next-line no-control-regex
.replace(/\u0000/g, '')
// eslint-disable-next-line no-control-regex
.replace(/\u0014/g, '\\u0014'),
);
if (data.status === 0) {
info.noticetrimstr = data.noticetrimstr;
info.formhash = data.formhash;
info.noticeauthor = data.noticeauthor;
} else {
throw new Error(data);
}
}
await loading.dismiss();
} catch (error) {
await loading.dismiss();
const alert = await alertController.create({
header: '提示',
message: '获取信息失败,请重试!',
buttons: [
{
text: '确定',
role: 'cancel',
handler: () => {
closeFunc(false);
},
},
],
});
await alert.present();
console.error(error);
}
};
const handleReply = async () => {
const loading = await loadingController.create({
message: '回复发送中...',
});
await loading.present();
try {
const { value: clienthash } = await ClientHash.getClientHash({
value: `TSDM_APP_${info.formhash}`,
});
const res = await reply({
...info,
reppid: props.replyPid,
clienthash,
message: htmlToBBCode(content.value),
tid: route.params.tid as string,
});
if (res.data) {
const data = JSON.parse(res.data);
if (data.status === 0) {
await loading.dismiss();
const alert = await alertController.create({
header: '提示',
message: '回复成功!',
buttons: [
{
text: '确定',
role: 'cancel',
handler: () => {
closeFunc(true);
content.value = '';
},
},
],
});
await alert.present();
} else {
throw new Error(data);
}
}
} catch (error) {
await loading.dismiss();
const alert = await alertController.create({
header: '提示',
message: '回复失败,请重试!',
buttons: [
{
text: '确定',
role: 'cancel',
},
],
});
await alert.present();
console.error(error);
}
};
</script>

<style scoped></style>
Loading

0 comments on commit 554745c

Please sign in to comment.