Initial project
This commit is contained in:
17
src/components/comment/form/emits.ts
Normal file
17
src/components/comment/form/emits.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { Comment } from "timi-web";
|
||||
|
||||
/**
|
||||
* emits
|
||||
*/
|
||||
export interface Emits {
|
||||
(event: "submit"): Promise<void>;
|
||||
}
|
||||
|
||||
export const useHandler = (emit: Emits) => {
|
||||
|
||||
const onSubmit = async (comment: Comment) => await emit("submit");
|
||||
|
||||
return {
|
||||
onSubmit,
|
||||
};
|
||||
};
|
||||
5
src/components/comment/form/index.ts
Normal file
5
src/components/comment/form/index.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import view from "./index.vue";
|
||||
import { Toolkit } from "timi-web";
|
||||
|
||||
export const CommentForm = Toolkit.withInstall(view);
|
||||
export default CommentForm;
|
||||
114
src/components/comment/form/index.vue
Normal file
114
src/components/comment/form/index.vue
Normal file
@ -0,0 +1,114 @@
|
||||
<template>
|
||||
<t-form class="tui-comment-form">
|
||||
<t-form-item label="昵称" name="nick">
|
||||
<t-input
|
||||
class="nick"
|
||||
v-model="formData.data.nick"
|
||||
:disabled="userStore.isLogged()"
|
||||
placeholder="昵称"
|
||||
/>
|
||||
</t-form-item>
|
||||
<t-form-item label="评论" name="content">
|
||||
<markdown-editor v-model:data="formData.data.content" />
|
||||
</t-form-item>
|
||||
<t-form-item label="验证码" name="captcha">
|
||||
<t-input class="captcha" v-model="formData.captcha" placeholder="" />
|
||||
<captcha
|
||||
ref="captchaRef"
|
||||
class="captcha-img"
|
||||
:api="CommonAPI.getCaptchaAPI()"
|
||||
:width="90"
|
||||
:height="28"
|
||||
:from="CaptchaFrom.COMMENT"
|
||||
/>
|
||||
<t-button
|
||||
type="submit"
|
||||
:loading="doSubmitting"
|
||||
:disabled="doSubmitting"
|
||||
@click="doSubmit"
|
||||
>提交</t-button>
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {
|
||||
Captcha,
|
||||
CaptchaData,
|
||||
CaptchaFrom,
|
||||
Comment,
|
||||
CommentAPI,
|
||||
CommentBizType,
|
||||
CommonAPI,
|
||||
MarkdownEditor,
|
||||
userStore
|
||||
} from "timi-web";
|
||||
import { Emits, useHandler } from "~/components/comment/form/emits";
|
||||
|
||||
defineOptions({
|
||||
name: "CommentForm"
|
||||
});
|
||||
|
||||
const emits = defineEmits<Emits>();
|
||||
const { onSubmit } = useHandler(emits);
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
bizType: CommentBizType,
|
||||
bizId: number,
|
||||
}>(), {});
|
||||
const { bizType, bizId } = toRefs(props);
|
||||
|
||||
const captchaRef = ref<{ update: () => void}>();
|
||||
const formData = reactive<CaptchaData<Comment>>({
|
||||
from: CaptchaFrom.COMMENT,
|
||||
captcha: "",
|
||||
data: {
|
||||
bizType: bizType.value,
|
||||
bizId: bizId.value,
|
||||
nick: "",
|
||||
content: ""
|
||||
}
|
||||
});
|
||||
const doSubmitting = ref(false);
|
||||
|
||||
async function doSubmit() {
|
||||
doSubmitting.value = true;
|
||||
|
||||
const loginUser = userStore.loginUser;
|
||||
if (userStore.isLogged() && loginUser.user) {
|
||||
formData.data.nick = loginUser.user.name;
|
||||
formData.data.userId = loginUser.user.id;
|
||||
}
|
||||
await CommentAPI.create(formData);
|
||||
formData.captcha = "";
|
||||
formData.data.content = "";
|
||||
captchaRef.value?.update();
|
||||
|
||||
doSubmitting.value = false;
|
||||
|
||||
await onSubmit(formData.data);
|
||||
}
|
||||
|
||||
// 登录用户
|
||||
const updateNick = () => formData.data.nick = userStore.loginUser?.user?.name || "";
|
||||
watch(userStore.loginUser, updateNick);
|
||||
onMounted(updateNick);
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.tui-comment-form {
|
||||
padding: 1rem;
|
||||
|
||||
.nick {
|
||||
width: 12rem;
|
||||
}
|
||||
|
||||
.captcha {
|
||||
width: 6rem;
|
||||
}
|
||||
|
||||
.captcha-img {
|
||||
margin: 0 1rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
20
src/components/comment/form/reply/emits.ts
Normal file
20
src/components/comment/form/reply/emits.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { CommentReply } from "timi-web";
|
||||
|
||||
/**
|
||||
* emits
|
||||
*/
|
||||
export interface Emits {
|
||||
(event: "cancel"): Promise<void>;
|
||||
(event: "submit", reply: CommentReply): Promise<void>;
|
||||
}
|
||||
|
||||
export const useHandler = (emit: Emits) => {
|
||||
|
||||
const onCancel = async () => await emit("cancel");
|
||||
const onSubmit = async (reply: CommentReply) => await emit("submit", reply);
|
||||
|
||||
return {
|
||||
onCancel,
|
||||
onSubmit
|
||||
};
|
||||
};
|
||||
5
src/components/comment/form/reply/index.ts
Normal file
5
src/components/comment/form/reply/index.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import view from "./index.vue";
|
||||
import { Toolkit } from "timi-web";
|
||||
|
||||
export const CommentReplyForm = Toolkit.withInstall(view);
|
||||
export default CommentReplyForm;
|
||||
168
src/components/comment/form/reply/index.vue
Normal file
168
src/components/comment/form/reply/index.vue
Normal file
@ -0,0 +1,168 @@
|
||||
<template>
|
||||
<t-form class="tui-comment-reply-form">
|
||||
<t-form-item label="昵称" name="nick">
|
||||
<t-input
|
||||
ref="nickRef"
|
||||
class="nick"
|
||||
v-model="formData.data.senderNick"
|
||||
placeholder="昵称"
|
||||
:disabled="userStore.isLogged()"
|
||||
/>
|
||||
<span v-if="replyToNick" class="gray selectable clip-text" v-text="` 回复 ${replyToNick}`"></span>
|
||||
</t-form-item>
|
||||
<t-form-item label="评论" name="content">
|
||||
<markdown-editor ref="contentRef" v-model:data="formData.data.content" />
|
||||
</t-form-item>
|
||||
<t-form-item label="验证码" name="captcha">
|
||||
<div class="captcha-box">
|
||||
<div>
|
||||
<t-input class="captcha" v-model="formData.captcha" placeholder="" />
|
||||
<captcha
|
||||
ref="captchaRef"
|
||||
class="captcha-img"
|
||||
:api="CommonAPI.getCaptchaAPI()"
|
||||
:width="90"
|
||||
:height="28"
|
||||
:from="CaptchaFrom.COMMENT_REPLY"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<t-button
|
||||
class="submit"
|
||||
type="submit"
|
||||
:loading="doSubmitting"
|
||||
:disabled="doSubmitting"
|
||||
@click="doSubmit"
|
||||
>提交</t-button>
|
||||
<t-button theme="default" @click="onCancel">取消</t-button>
|
||||
</div>
|
||||
</div>
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {
|
||||
Captcha,
|
||||
CaptchaData,
|
||||
CaptchaFrom,
|
||||
CommentAPI,
|
||||
CommentReply,
|
||||
CommonAPI,
|
||||
MarkdownEditor,
|
||||
Scroller,
|
||||
userStore
|
||||
} from "timi-web";
|
||||
import { Emits, useHandler } from "~/components/comment/form/reply/emits";
|
||||
|
||||
defineOptions({
|
||||
name: "CommentReplyForm"
|
||||
});
|
||||
|
||||
const emits = defineEmits<Emits>();
|
||||
const { onCancel, onSubmit } = useHandler(emits);
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
commentId: number,
|
||||
replyId?: number,
|
||||
replyToNick?: string,
|
||||
}>(), {});
|
||||
const { commentId, replyId, replyToNick } = toRefs(props);
|
||||
|
||||
const doSubmitting = ref(false);
|
||||
const nickRef = ref();
|
||||
const contentRef = ref();
|
||||
|
||||
const formData = reactive<CaptchaData<CommentReply>>({
|
||||
from: CaptchaFrom.COMMENT_REPLY,
|
||||
captcha: "",
|
||||
data: {
|
||||
commentId: commentId.value,
|
||||
replyId: replyId.value,
|
||||
senderNick: "",
|
||||
content: ""
|
||||
}
|
||||
});
|
||||
|
||||
/** 提交回复 */
|
||||
async function doSubmit() {
|
||||
doSubmitting.value = true;
|
||||
|
||||
formData.data.commentId = commentId.value;
|
||||
formData.data.replyId = replyId.value;
|
||||
const loginUser = userStore.loginUser;
|
||||
if (userStore.isLogged() && loginUser.user) {
|
||||
formData.data.senderNick = loginUser.user.name;
|
||||
formData.data.senderId = loginUser.user.id;
|
||||
}
|
||||
await CommentAPI.createReply(formData);
|
||||
formData.captcha = "";
|
||||
await onSubmit(formData.data);
|
||||
|
||||
doSubmitting.value = false;
|
||||
}
|
||||
|
||||
async function focus() {
|
||||
await nextTick();
|
||||
let focusEl: HTMLElement;
|
||||
if (userStore.isLogged()) {
|
||||
focusEl = nickRef.value[0].textArea;
|
||||
} else {
|
||||
focusEl = contentRef.value[0].inputRef;
|
||||
}
|
||||
focusEl.focus();
|
||||
Scroller.toElement(focusEl);
|
||||
}
|
||||
|
||||
// 登录用户
|
||||
const updateNick = () => formData.data.senderNick = userStore.loginUser?.user?.name || "";
|
||||
watch(userStore.loginUser, updateNick);
|
||||
onMounted(updateNick);
|
||||
|
||||
defineExpose({
|
||||
focus
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.tui-comment-reply-form {
|
||||
padding: 1rem 1rem 1rem 0;
|
||||
|
||||
.nick {
|
||||
width: 12rem;
|
||||
}
|
||||
|
||||
.captcha-box {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
div {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.captcha {
|
||||
width: 6rem;
|
||||
}
|
||||
|
||||
.captcha-img {
|
||||
margin: 0 1rem;
|
||||
}
|
||||
|
||||
.submit {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 650px) {
|
||||
.tui-comment-reply-form {
|
||||
|
||||
.captcha-box {
|
||||
|
||||
> div:first-child {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user