chore: format code

pull/36/head
CXM 3 years ago
parent 33631a9806
commit b2a66c3788

@ -1,26 +1,17 @@
<template> <template>
<n-config-provider :theme="theme"> <n-config-provider :theme="theme">
<n-message-provider> <n-message-provider>
<div <div class="app-container" :class="{ dark: theme?.name === 'dark' }">
class="app-container"
:class="{ dark: theme?.name === 'dark' }"
>
<div has-sider class="main-wrap" position="static"> <div has-sider class="main-wrap" position="static">
<!-- --> <!-- -->
<sidebar /> <sidebar />
<div class="content-wrap"> <div class="content-wrap">
<router-view class="app-wrap" v-slot="{ Component }"> <router-view v-slot="{ Component }" class="app-wrap">
<keep-alive> <keep-alive>
<component <component :is="Component" v-if="$route.meta.keepAlive" />
v-if="$route.meta.keepAlive"
:is="Component"
/>
</keep-alive> </keep-alive>
<component <component :is="Component" v-if="!$route.meta.keepAlive" />
v-if="!$route.meta.keepAlive"
:is="Component"
/>
</router-view> </router-view>
</div> </div>

@ -75,7 +75,6 @@
} }
.dark { .dark {
.hash-link, .hash-link,
.user-link { .user-link {
color: #63e2b7; color: #63e2b7;

@ -41,9 +41,9 @@
</n-form-item-row> </n-form-item-row>
<n-form-item-row label="密码" path="password"> <n-form-item-row label="密码" path="password">
<n-input <n-input
v-model:value="loginForm.password"
type="password" type="password"
show-password-on="mousedown" show-password-on="mousedown"
v-model:value="loginForm.password"
placeholder="请输入账户密码" placeholder="请输入账户密码"
@keyup.enter.prevent="handleLogin" @keyup.enter.prevent="handleLogin"
/> />
@ -74,19 +74,19 @@
</n-form-item-row> </n-form-item-row>
<n-form-item-row label="密码" path="password"> <n-form-item-row label="密码" path="password">
<n-input <n-input
v-model:value="registerForm.password"
type="password" type="password"
show-password-on="mousedown" show-password-on="mousedown"
placeholder="密码不少于6位" placeholder="密码不少于6位"
v-model:value="registerForm.password"
@keyup.enter.prevent="handleRegister" @keyup.enter.prevent="handleRegister"
/> />
</n-form-item-row> </n-form-item-row>
<n-form-item-row label="重复密码" path="repassword"> <n-form-item-row label="重复密码" path="repassword">
<n-input <n-input
v-model:value="registerForm.repassword"
type="password" type="password"
show-password-on="mousedown" show-password-on="mousedown"
placeholder="请再次输入密码" placeholder="请再次输入密码"
v-model:value="registerForm.repassword"
@keyup.enter.prevent="handleRegister" @keyup.enter.prevent="handleRegister"
/> />
</n-form-item-row> </n-form-item-row>

@ -7,28 +7,22 @@
<template #header> <template #header>
<span class="nickname-wrap"> <span class="nickname-wrap">
<router-link <router-link
@click.stop
class="username-link" class="username-link"
:to="{ :to="{
name: 'user', name: 'user',
query: { username: comment.user.username }, query: { username: comment.user.username },
}" }"
@click.stop
> >
{{ comment.user.nickname }} {{ comment.user.nickname }}
</router-link> </router-link>
</span> </span>
<span class="username-wrap"> <span class="username-wrap"> @{{ comment.user.username }} </span>
@{{ comment.user.username }}
</span>
</template> </template>
<template #header-extra> <template #header-extra>
<div class="opt-wrap"> <div class="opt-wrap">
<span class="timestamp"> <span class="timestamp">
{{ {{ comment.ip_loc ? comment.ip_loc + ' · ' : comment.ip_loc }}
comment.ip_loc
? comment.ip_loc + ' · '
: comment.ip_loc
}}
{{ formatRelativeTime(comment.created_on) }} {{ formatRelativeTime(comment.created_on) }}
</span> </span>
@ -42,12 +36,7 @@
@positive-click="execDelAction" @positive-click="execDelAction"
> >
<template #trigger> <template #trigger>
<n-button <n-button quaternary circle size="tiny" class="del-btn">
quaternary
circle
size="tiny"
class="del-btn"
>
<template #icon> <template #icon>
<n-icon> <n-icon>
<trash /> <trash />
@ -59,7 +48,7 @@
</n-popconfirm> </n-popconfirm>
</div> </div>
</template> </template>
<template #description v-if="comment.texts.length > 0"> <template v-if="comment.texts.length > 0" #description>
<span <span
v-for="content in comment.texts" v-for="content in comment.texts"
:key="content.id" :key="content.id"
@ -84,8 +73,8 @@
</div> </div>
<!-- --> <!-- -->
<compose-reply <compose-reply
ref="replyComposeRef"
v-if="store.state.userInfo.id > 0" v-if="store.state.userInfo.id > 0"
ref="replyComposeRef"
:comment-id="comment.id" :comment-id="comment.id"
:at-userid="replyAtUserID" :at-userid="replyAtUserID"
:at-username="replyAtUsername" :at-username="replyAtUsername"
@ -113,11 +102,14 @@ const replyAtUsername = ref('');
const replyComposeRef = ref(); const replyComposeRef = ref();
const emit = defineEmits<{ const emit = defineEmits<{
(e: "reload"): void (e: 'reload'): void;
}>(); }>();
const props = withDefaults(defineProps<{ const props = withDefaults(
comment: Item.CommentProps defineProps<{
}>(), {}) comment: Item.CommentProps;
}>(),
{},
);
const comment = computed(() => { const comment = computed(() => {
let comment: Item.CommentComponentProps = Object.assign( let comment: Item.CommentComponentProps = Object.assign(
@ -125,9 +117,9 @@ const comment = computed(() => {
texts: [], texts: [],
imgs: [], imgs: [],
}, },
props.comment props.comment,
); );
comment.contents.map((content :any) => { comment.contents.map((content: any) => {
if (+content.type === 1 || +content.type === 2) { if (+content.type === 1 || +content.type === 2) {
comment.texts.push(content); comment.texts.push(content);
} }

@ -1,13 +1,9 @@
<template> <template>
<div> <div>
<div class="compose-wrap" v-if="store.state.userInfo.id > 0"> <div v-if="store.state.userInfo.id > 0" class="compose-wrap">
<div class="compose-line"> <div class="compose-line">
<div class="compose-user"> <div class="compose-user">
<n-avatar <n-avatar round :size="30" :src="store.state.userInfo.avatar" />
round
:size="30"
:src="store.state.userInfo.avatar"
/>
</div> </div>
<n-mention <n-mention
type="textarea" type="textarea"
@ -19,14 +15,14 @@
:loading="loading" :loading="loading"
:value="content" :value="content"
:disabled="props.lock === 1" :disabled="props.lock === 1"
@update:value="changeContent"
@search="handleSearch"
@focus="focusComment"
:placeholder=" :placeholder="
props.lock === 1 props.lock === 1
? '' ? ''
: '...' : '...'
" "
@update:value="changeContent"
@search="handleSearch"
@focus="focusComment"
/> />
</div> </div>
@ -55,25 +51,21 @@
<n-upload-trigger #="{ handleClick }" abstract> <n-upload-trigger #="{ handleClick }" abstract>
<n-button <n-button
:disabled=" :disabled="
(fileQueue.length > 0 && (fileQueue.length > 0 && uploadType === 'public/video') ||
uploadType === 'public/video') ||
fileQueue.length === 9 fileQueue.length === 9
" "
quaternary
circle
type="primary"
@click=" @click="
() => { () => {
setUploadType('public/image'); setUploadType('public/image');
handleClick(); handleClick();
} }
" "
quaternary
circle
type="primary"
> >
<template #icon> <template #icon>
<n-icon <n-icon size="20" color="var(--primary-color)">
size="20"
color="var(--primary-color)"
>
<image-outline /> <image-outline />
</n-icon> </n-icon>
</template> </template>
@ -108,11 +100,11 @@
</n-button> </n-button>
<n-button <n-button
:loading="submitting" :loading="submitting"
@click="submitPost"
type="primary" type="primary"
secondary secondary
size="small" size="small"
round round
@click="submitPost"
> >
</n-button> </n-button>
@ -125,7 +117,7 @@
</n-upload> </n-upload>
</div> </div>
<div class="compose-wrap" v-else> <div v-else class="compose-wrap">
<div class="login-wrap"> <div class="login-wrap">
<span class="login-banner"> </span> <span class="login-banner"> </span>
</div> </div>
@ -153,7 +145,6 @@
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, ref } from 'vue'; import { onMounted, ref } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
@ -170,15 +161,18 @@ import { parsePostTag } from '@/utils/content';
import type { MentionOption, UploadFileInfo, UploadInst } from 'naive-ui'; import type { MentionOption, UploadFileInfo, UploadInst } from 'naive-ui';
const emit = defineEmits<{ const emit = defineEmits<{
(e: "post-success"): void (e: 'post-success'): void;
}>(); }>();
const props = withDefaults(defineProps<{ const props = withDefaults(
lock: number, defineProps<{
postId: number, lock: number;
}>(), { postId: number;
}>(),
{
lock: 0, lock: 0,
postId: 0 postId: 0,
}); },
);
const store = useStore(); const store = useStore();
@ -242,14 +236,17 @@ const beforeUpload = async (data: any) => {
if ( if (
uploadType.value === 'public/image' && uploadType.value === 'public/image' &&
!['image/png', 'image/jpg', 'image/jpeg', 'image/gif'].includes( !['image/png', 'image/jpg', 'image/jpeg', 'image/gif'].includes(
(data.file as any).file?.type (data.file as any).file?.type,
) )
) { ) {
window.$message.warning(' png/jpg/gif '); window.$message.warning(' png/jpg/gif ');
return false; return false;
} }
if (uploadType.value === 'image' && (data.file as any).file?.size > 10485760) { if (
uploadType.value === 'image' &&
(data.file as any).file?.size > 10485760
) {
window.$message.warning('10MB'); window.$message.warning('10MB');
return false; return false;
} }

@ -1,26 +1,24 @@
<template> <template>
<div class="reply-compose-wrap"> <div class="reply-compose-wrap">
<div class="reply-switch"> <div class="reply-switch">
<span class="show" v-if="!showReply" @click="switchReply(true)"> <span v-if="!showReply" class="show" @click="switchReply(true)">
</span> </span>
<span class="hide" v-if="showReply" @click="switchReply(false)"> <span v-if="showReply" class="hide" @click="switchReply(false)">
</span> </span>
</div> </div>
<div class="reply-input-wrap" v-if="showReply"> <div v-if="showReply" class="reply-input-wrap">
<n-input-group> <n-input-group>
<n-input <n-input
ref="inputInstRef" ref="inputInstRef"
v-model:value="replyContent"
size="small" size="small"
:placeholder=" :placeholder="
props.atUsername props.atUsername ? '@' + props.atUsername : '..'
? '@' + props.atUsername
: '..'
" "
maxlength="100" maxlength="100"
v-model:value="replyContent"
show-count show-count
clearable clearable
/> />
@ -43,18 +41,21 @@ import { ref } from 'vue';
import { createCommentReply } from '@/api/post'; import { createCommentReply } from '@/api/post';
import { InputInst } from 'naive-ui'; import { InputInst } from 'naive-ui';
const props = withDefaults(defineProps<{ const props = withDefaults(
commentId: number, defineProps<{
atUserid: number, commentId: number;
atUsername: string, atUserid: number;
}>(), { atUsername: string;
}>(),
{
commentId: 0, commentId: 0,
atUserid: 0, atUserid: 0,
atUsername: "" atUsername: '',
}); },
);
const emit = defineEmits<{ const emit = defineEmits<{
(e: "reload"): void, (e: 'reload'): void;
(e: "reset"): void (e: 'reset'): void;
}>(); }>();
const inputInstRef = ref<InputInst>(); const inputInstRef = ref<InputInst>();
const showReply = ref(false); const showReply = ref(false);

@ -1,13 +1,9 @@
<template> <template>
<div> <div>
<div class="compose-wrap" v-if="store.state.userInfo.id > 0"> <div v-if="store.state.userInfo.id > 0" class="compose-wrap">
<div class="compose-line"> <div class="compose-line">
<div class="compose-user"> <div class="compose-user">
<n-avatar <n-avatar round :size="30" :src="store.state.userInfo.avatar" />
round
:size="30"
:src="store.state.userInfo.avatar"
/>
</div> </div>
<n-mention <n-mention
type="textarea" type="textarea"
@ -18,9 +14,9 @@
:value="content" :value="content"
:prefix="['@', '#']" :prefix="['@', '#']"
:options="optionsRef" :options="optionsRef"
placeholder="说说您的新鲜事..."
@search="handleSearch" @search="handleSearch"
@update:value="changeContent" @update:value="changeContent"
placeholder="说说您的新鲜事..."
/> />
</div> </div>
@ -48,25 +44,21 @@
<n-upload-trigger #="{ handleClick }" abstract> <n-upload-trigger #="{ handleClick }" abstract>
<n-button <n-button
:disabled=" :disabled="
(fileQueue.length > 0 && (fileQueue.length > 0 && uploadType === 'public/video') ||
uploadType === 'public/video') ||
fileQueue.length === 9 fileQueue.length === 9
" "
quaternary
circle
type="primary"
@click=" @click="
() => { () => {
setUploadType('public/image'); setUploadType('public/image');
handleClick(); handleClick();
} }
" "
quaternary
circle
type="primary"
> >
<template #icon> <template #icon>
<n-icon <n-icon size="20" color="var(--primary-color)">
size="20"
color="var(--primary-color)"
>
<image-outline /> <image-outline />
</n-icon> </n-icon>
</template> </template>
@ -76,25 +68,21 @@
<n-upload-trigger #="{ handleClick }" abstract> <n-upload-trigger #="{ handleClick }" abstract>
<n-button <n-button
:disabled=" :disabled="
(fileQueue.length > 0 && (fileQueue.length > 0 && uploadType !== 'public/video') ||
uploadType !== 'public/video') ||
fileQueue.length === 9 fileQueue.length === 9
" "
quaternary
circle
type="primary"
@click=" @click="
() => { () => {
setUploadType('public/video'); setUploadType('public/video');
handleClick(); handleClick();
} }
" "
quaternary
circle
type="primary"
> >
<template #icon> <template #icon>
<n-icon <n-icon size="20" color="var(--primary-color)">
size="20"
color="var(--primary-color)"
>
<videocam-outline /> <videocam-outline />
</n-icon> </n-icon>
</template> </template>
@ -104,37 +92,28 @@
<n-upload-trigger #="{ handleClick }" abstract> <n-upload-trigger #="{ handleClick }" abstract>
<n-button <n-button
:disabled=" :disabled="
(fileQueue.length > 0 && (fileQueue.length > 0 && uploadType === 'public/video') ||
uploadType === 'public/video') ||
fileQueue.length === 9 fileQueue.length === 9
" "
quaternary
circle
type="primary"
@click=" @click="
() => { () => {
setUploadType('attachment'); setUploadType('attachment');
handleClick(); handleClick();
} }
" "
quaternary
circle
type="primary"
> >
<template #icon> <template #icon>
<n-icon <n-icon size="20" color="var(--primary-color)">
size="20"
color="var(--primary-color)"
>
<attach-outline /> <attach-outline />
</n-icon> </n-icon>
</template> </template>
</n-button> </n-button>
</n-upload-trigger> </n-upload-trigger>
<n-button <n-button quaternary circle type="primary" @click.stop="switchLink">
quaternary
circle
type="primary"
@click.stop="switchLink"
>
<template #icon> <template #icon>
<n-icon size="20" color="var(--primary-color)"> <n-icon size="20" color="var(--primary-color)">
<compass-outline /> <compass-outline />
@ -160,10 +139,10 @@
<n-button <n-button
:loading="submitting" :loading="submitting"
@click="submitPost"
type="primary" type="primary"
secondary secondary
round round
@click="submitPost"
> >
</n-button> </n-button>
@ -173,8 +152,8 @@
<div class="attachment-list-wrap"> <div class="attachment-list-wrap">
<n-upload-file-list /> <n-upload-file-list />
<div <div
class="attachment-price-wrap"
v-if="attachmentContents.length > 0" v-if="attachmentContents.length > 0"
class="attachment-price-wrap"
> >
<n-input-number <n-input-number
v-model:value="attachmentPrice" v-model:value="attachmentPrice"
@ -190,7 +169,7 @@
</div> </div>
</n-upload> </n-upload>
<div class="link-wrap" v-if="showLinkSet"> <div v-if="showLinkSet" class="link-wrap">
<n-dynamic-input <n-dynamic-input
v-model:value="links" v-model:value="links"
placeholder="请输入以http(s)://开头的链接" placeholder="请输入以http(s)://开头的链接"
@ -202,7 +181,7 @@
</div> </div>
</div> </div>
<div class="compose-wrap" v-else> <div v-else class="compose-wrap">
<div class="login-wrap"> <div class="login-wrap">
<span class="login-banner"> </span> <span class="login-banner"> </span>
</div> </div>
@ -230,7 +209,6 @@
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted } from 'vue'; import { ref, onMounted } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
@ -248,7 +226,7 @@ import { parsePostTag } from '@/utils/content';
import type { MentionOption, UploadFileInfo, UploadInst } from 'naive-ui'; import type { MentionOption, UploadFileInfo, UploadInst } from 'naive-ui';
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'post-success', post: Item.PostProps): void (e: 'post-success', post: Item.PostProps): void;
}>(); }>();
const store = useStore(); const store = useStore();
@ -348,7 +326,7 @@ const beforeUpload = async (data: any) => {
if ( if (
uploadType.value === 'public/image' && uploadType.value === 'public/image' &&
!['image/png', 'image/jpg', 'image/jpeg', 'image/gif'].includes( !['image/png', 'image/jpg', 'image/jpeg', 'image/gif'].includes(
data.file.file?.type data.file.file?.type,
) )
) { ) {
window.$message.warning(' png/jpg/gif '); window.$message.warning(' png/jpg/gif ');
@ -369,10 +347,7 @@ const beforeUpload = async (data: any) => {
return false; return false;
} }
if ( if (uploadType.value === 'public/video' && data.file.file?.size > 104857600) {
uploadType.value === 'public/video' &&
data.file.file?.size > 104857600
) {
window.$message.warning('100MB'); window.$message.warning('100MB');
return false; return false;
} }

@ -3,12 +3,12 @@
<template #header> <template #header>
<div class="navbar"> <div class="navbar">
<n-button <n-button
class="back-btn"
v-if="back" v-if="back"
@click="goBack" class="back-btn"
quaternary quaternary
circle circle
size="small" size="small"
@click="goBack"
> >
<template #icon> <template #icon>
<n-icon><chevron-left-round /></n-icon> <n-icon><chevron-left-round /></n-icon>
@ -19,9 +19,9 @@
<n-switch <n-switch
:value="store.state.theme === 'dark'" :value="store.state.theme === 'dark'"
@update:value="switchTheme"
size="small" size="small"
class="theme-switch-wrap" class="theme-switch-wrap"
@update:value="switchTheme"
> >
<template #icon> <template #icon>
<dark-mode-outlined /> <dark-mode-outlined />
@ -50,7 +50,7 @@ const props = withDefaults(
{ {
title: '', title: '',
back: false, back: false,
} },
); );
const switchTheme = (theme: boolean) => { const switchTheme = (theme: boolean) => {
if (theme) { if (theme) {

@ -15,9 +15,8 @@
: defaultavatar : defaultavatar
" "
/> />
<span class="nickname" v-if="message.sender_user.id > 0"> <span v-if="message.sender_user.id > 0" class="nickname">
<router-link <router-link
@click.stop
class="username-link" class="username-link"
:to="{ :to="{
name: 'user', name: 'user',
@ -25,14 +24,13 @@
username: message.sender_user.username, username: message.sender_user.username,
}, },
}" }"
@click.stop
> >
{{ message.sender_user.nickname }} {{ message.sender_user.nickname }}
</router-link> </router-link>
<span class="username"> <span class="username"> @{{ message.sender_user.username }} </span>
@{{ message.sender_user.username }}
</span>
</span> </span>
<span class="nickname" v-else> </span> <span v-else class="nickname"> </span>
</div> </div>
</template> </template>
<template #header-extra> <template #header-extra>
@ -53,8 +51,8 @@
{{ message.breif }} {{ message.breif }}
<span <span
v-if="message.type !== 4" v-if="message.type !== 4"
@click.stop="viewDetail(message)"
class="hash-link view-link" class="hash-link view-link"
@click.stop="viewDetail(message)"
> >
<n-icon><share-outline /></n-icon> <n-icon><share-outline /></n-icon>
</span> </span>
@ -83,7 +81,7 @@ const props = withDefaults(
defineProps<{ defineProps<{
message: Item.MessageProps; message: Item.MessageProps;
}>(), }>(),
{} {},
); );
const viewDetail = (message: Item.MessageProps) => { const viewDetail = (message: Item.MessageProps) => {
handleReadMessage(message); handleReadMessage(message);

@ -1,5 +1,5 @@
<template> <template>
<div class="skeleton-item" v-for="i in new Array(num)" :key="i"> <div v-for="i in new Array(num)" :key="i" class="skeleton-item">
<div class="content"> <div class="content">
<n-skeleton text :repeat="2" /> <n-skeleton text :repeat="2" />
<n-skeleton text style="width: 60%" /> <n-skeleton text style="width: 60%" />
@ -8,11 +8,14 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
const props = withDefaults(defineProps<{ const props = withDefaults(
num: number defineProps<{
}>(), { num: number;
num: 1 }>(),
}); {
num: 1,
},
);
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

@ -1,15 +1,15 @@
<template> <template>
<div class="attachment-wrap"> <div class="attachment-wrap">
<div <div
class="attach-item"
v-for="attachment in attachments" v-for="attachment in attachments"
:key="attachment.id" :key="attachment.id"
class="attach-item"
> >
<n-button <n-button
@click.stop="download(attachment)"
type="primary" type="primary"
size="tiny" size="tiny"
dashed dashed
@click.stop="download(attachment)"
> >
<template #icon> <template #icon>
<n-icon> <n-icon>
@ -48,7 +48,7 @@ const props = withDefaults(
{ {
attachments: () => [], attachments: () => [],
price: 0, price: 0,
} },
); );
const showDownloadModal = ref(false); const showDownloadModal = ref(false);
const downloadTip = ref<any>(''); const downloadTip = ref<any>('');
@ -67,7 +67,7 @@ const download = (attachment: Item.PostItemProps) => {
{}, {},
'' + '' +
(props.price / 100).toFixed(2) + (props.price / 100).toFixed(2) +
'元' '元',
), ),
]); ]);
@ -78,11 +78,7 @@ const download = (attachment: Item.PostItemProps) => {
if (res.paid) { if (res.paid) {
downloadTip.value = () => downloadTip.value = () =>
h('div', {}, [ h('div', {}, [
h( h('p', {}, ''),
'p',
{},
''
),
]); ]);
} }
}) })

@ -6,12 +6,12 @@
</template> </template>
<template #header> <template #header>
<router-link <router-link
@click.stop
class="username-link" class="username-link"
:to="{ :to="{
name: 'user', name: 'user',
query: { username: post.user.username }, query: { username: post.user.username },
}" }"
@click.stop
> >
{{ post.user.nickname }} {{ post.user.nickname }}
</router-link> </router-link>
@ -19,11 +19,11 @@
</template> </template>
<template #header-extra> <template #header-extra>
<div <div
class="options"
v-if=" v-if="
store.state.userInfo.is_admin || store.state.userInfo.is_admin ||
store.state.userInfo.id === post.user.id store.state.userInfo.id === post.user.id
" "
class="options"
> >
<n-dropdown <n-dropdown
placement="bottom-end" placement="bottom-end"
@ -60,9 +60,7 @@
preset="dialog" preset="dialog"
title="提示" title="提示"
:content=" :content="
'' + '' + (post.is_lock ? '' : '') + ''
(post.is_lock ? '' : '') +
''
" "
positive-text="确认" positive-text="确认"
negative-text="取消" negative-text="取消"
@ -75,9 +73,7 @@
preset="dialog" preset="dialog"
title="提示" title="提示"
:content=" :content="
'' + '' + (post.is_top ? '' : '') + ''
(post.is_top ? '' : '') +
''
" "
positive-text="确认" positive-text="确认"
negative-text="取消" negative-text="取消"
@ -119,10 +115,7 @@
<template #action> <template #action>
<div class="opts-wrap"> <div class="opts-wrap">
<n-space justify="space-between"> <n-space justify="space-between">
<div <div class="opt-item hover" @click.stop="handlePostStar">
class="opt-item hover"
@click.stop="handlePostStar"
>
<n-icon size="20" class="opt-item-icon"> <n-icon size="20" class="opt-item-icon">
<heart-outline v-if="!hasStarred" /> <heart-outline v-if="!hasStarred" />
<heart v-if="hasStarred" color="red" /> <heart v-if="hasStarred" color="red" />
@ -135,10 +128,7 @@
</n-icon> </n-icon>
{{ post.comment_count }} {{ post.comment_count }}
</div> </div>
<div <div class="opt-item hover" @click.stop="handlePostCollection">
class="opt-item hover"
@click.stop="handlePostCollection"
>
<n-icon size="20" class="opt-item-icon"> <n-icon size="20" class="opt-item-icon">
<bookmark-outline v-if="!hasCollected" /> <bookmark-outline v-if="!hasCollected" />
<bookmark v-if="hasCollected" color="#ff7600" /> <bookmark v-if="hasCollected" color="#ff7600" />
@ -184,7 +174,7 @@ const props = withDefaults(
defineProps<{ defineProps<{
post: Item.PostProps; post: Item.PostProps;
}>(), }>(),
{} {},
); );
const showDelModal = ref(false); const showDelModal = ref(false);
const showLockModal = ref(false); const showLockModal = ref(false);
@ -206,7 +196,7 @@ const post = computed({
attachments: [], attachments: [],
charge_attachments: [], charge_attachments: [],
}, },
props.post props.post,
); );
post.contents.map((content) => { post.contents.map((content) => {
if (+content.type === 1 || +content.type === 2) { if (+content.type === 1 || +content.type === 2) {
@ -306,7 +296,7 @@ const doClickText = (e: MouseEvent, id: number) => {
goPostDetail(id); goPostDetail(id);
}; };
const handlePostAction = ( const handlePostAction = (
item: 'delete' | 'lock' | 'unlock' | 'stick' | 'unstick' item: 'delete' | 'lock' | 'unlock' | 'stick' | 'unstick',
) => { ) => {
if (item === 'delete') { if (item === 'delete') {
showDelModal.value = true; showDelModal.value = true;

@ -5,12 +5,12 @@
<template v-for="img in props.imgs" :key="img.id"> <template v-for="img in props.imgs" :key="img.id">
<n-gi> <n-gi>
<n-image <n-image
@error="() => (img.content = defaultImg)"
@click.stop
class="post-img x1" class="post-img x1"
object-fit="cover" object-fit="cover"
:src="img.content + thumbnail" :src="img.content + thumbnail"
:preview-src="img.content" :preview-src="img.content"
@error="() => (img.content = defaultImg)"
@click.stop
/> />
</n-gi> </n-gi>
</template> </template>
@ -22,12 +22,12 @@
<template v-for="img in props.imgs" :key="img.id"> <template v-for="img in props.imgs" :key="img.id">
<n-gi> <n-gi>
<n-image <n-image
@error="() => (img.content = defaultImg)"
@click.stop
class="post-img x2" class="post-img x2"
object-fit="cover" object-fit="cover"
:src="img.content + thumbnail" :src="img.content + thumbnail"
:preview-src="img.content" :preview-src="img.content"
@error="() => (img.content = defaultImg)"
@click.stop
/> />
</n-gi> </n-gi>
</template> </template>
@ -39,12 +39,12 @@
<template v-for="img in props.imgs" :key="img.id"> <template v-for="img in props.imgs" :key="img.id">
<n-gi> <n-gi>
<n-image <n-image
@error="() => (img.content = defaultImg)"
@click.stop
class="post-img x3" class="post-img x3"
object-fit="cover" object-fit="cover"
:src="img.content + thumbnail" :src="img.content + thumbnail"
:preview-src="img.content" :preview-src="img.content"
@error="() => (img.content = defaultImg)"
@click.stop
/> />
</n-gi> </n-gi>
</template> </template>
@ -56,12 +56,12 @@
<template v-for="(img, idx) in props.imgs" :key="img.id"> <template v-for="(img, idx) in props.imgs" :key="img.id">
<n-gi v-if="idx < 3"> <n-gi v-if="idx < 3">
<n-image <n-image
@error="() => (img.content = defaultImg)"
@click.stop
class="post-img x2" class="post-img x2"
object-fit="cover" object-fit="cover"
:src="img.content + thumbnail" :src="img.content + thumbnail"
:preview-src="img.content" :preview-src="img.content"
@error="() => (img.content = defaultImg)"
@click.stop
/> />
</n-gi> </n-gi>
</template> </template>
@ -70,12 +70,12 @@
<template v-for="(img, idx) in props.imgs" :key="img.id"> <template v-for="(img, idx) in props.imgs" :key="img.id">
<n-gi v-if="idx >= 3"> <n-gi v-if="idx >= 3">
<n-image <n-image
@error="() => (img.content = defaultImg)"
@click.stop
class="post-img x1" class="post-img x1"
object-fit="cover" object-fit="cover"
:src="img.content + thumbnail" :src="img.content + thumbnail"
:preview-src="img.content" :preview-src="img.content"
@error="() => (img.content = defaultImg)"
@click.stop
/> />
</n-gi> </n-gi>
</template> </template>
@ -87,12 +87,12 @@
<template v-for="(img, idx) in props.imgs" :key="img.id"> <template v-for="(img, idx) in props.imgs" :key="img.id">
<n-gi v-if="idx < 3"> <n-gi v-if="idx < 3">
<n-image <n-image
@error="() => (img.content = defaultImg)"
@click.stop
class="post-img x2" class="post-img x2"
object-fit="cover" object-fit="cover"
:src="img.content + thumbnail" :src="img.content + thumbnail"
:preview-src="img.content" :preview-src="img.content"
@error="() => (img.content = defaultImg)"
@click.stop
/> />
</n-gi> </n-gi>
</template> </template>
@ -101,12 +101,12 @@
<template v-for="(img, idx) in props.imgs" :key="img.id"> <template v-for="(img, idx) in props.imgs" :key="img.id">
<n-gi v-if="idx >= 3"> <n-gi v-if="idx >= 3">
<n-image <n-image
@error="() => (img.content = defaultImg)"
@click.stop
class="post-img x2" class="post-img x2"
object-fit="cover" object-fit="cover"
:src="img.content + thumbnail" :src="img.content + thumbnail"
:preview-src="img.content" :preview-src="img.content"
@error="() => (img.content = defaultImg)"
@click.stop
/> />
</n-gi> </n-gi>
</template> </template>
@ -116,28 +116,28 @@
<n-image-group v-if="props.imgs.length === 7"> <n-image-group v-if="props.imgs.length === 7">
<n-grid :x-gap="4" :y-gap="4" :cols="4"> <n-grid :x-gap="4" :y-gap="4" :cols="4">
<template v-for="(img, idx) in props.imgs"> <template v-for="(img, idx) in props.imgs">
<n-gi :key="img.id" v-if="idx < 4"> <n-gi v-if="idx < 4" :key="img.id">
<n-image <n-image
@error="() => (img.content = defaultImg)"
@click.stop
class="post-img x3" class="post-img x3"
object-fit="cover" object-fit="cover"
:src="img.content + thumbnail" :src="img.content + thumbnail"
:preview-src="img.content" :preview-src="img.content"
@error="() => (img.content = defaultImg)"
@click.stop
/> />
</n-gi> </n-gi>
</template> </template>
</n-grid> </n-grid>
<n-grid :x-gap="4" :y-gap="4" :cols="3" style="margin-top: 4px"> <n-grid :x-gap="4" :y-gap="4" :cols="3" style="margin-top: 4px">
<template v-for="(img, idx) in props.imgs"> <template v-for="(img, idx) in props.imgs">
<n-gi :key="img.id" v-if="idx >= 4"> <n-gi v-if="idx >= 4" :key="img.id">
<n-image <n-image
@error="() => (img.content = defaultImg)"
@click.stop
class="post-img x2" class="post-img x2"
object-fit="cover" object-fit="cover"
:src="img.content + thumbnail" :src="img.content + thumbnail"
:preview-src="img.content" :preview-src="img.content"
@error="() => (img.content = defaultImg)"
@click.stop
/> />
</n-gi> </n-gi>
</template> </template>
@ -147,28 +147,28 @@
<n-image-group v-if="props.imgs.length === 8"> <n-image-group v-if="props.imgs.length === 8">
<n-grid :x-gap="4" :y-gap="4" :cols="4"> <n-grid :x-gap="4" :y-gap="4" :cols="4">
<template v-for="(img, idx) in props.imgs"> <template v-for="(img, idx) in props.imgs">
<n-gi :key="img.id" v-if="idx < 4"> <n-gi v-if="idx < 4" :key="img.id">
<n-image <n-image
@error="() => (img.content = defaultImg)"
@click.stop
class="post-img x3" class="post-img x3"
object-fit="cover" object-fit="cover"
:src="img.content + thumbnail" :src="img.content + thumbnail"
:preview-src="img.content" :preview-src="img.content"
@error="() => (img.content = defaultImg)"
@click.stop
/> />
</n-gi> </n-gi>
</template> </template>
</n-grid> </n-grid>
<n-grid :x-gap="4" :y-gap="4" :cols="4" style="margin-top: 4px"> <n-grid :x-gap="4" :y-gap="4" :cols="4" style="margin-top: 4px">
<template v-for="(img, idx) in props.imgs"> <template v-for="(img, idx) in props.imgs">
<n-gi :key="img.id" v-if="idx >= 4"> <n-gi v-if="idx >= 4" :key="img.id">
<n-image <n-image
@error="() => (img.content = defaultImg)"
@click.stop
class="post-img x3" class="post-img x3"
object-fit="cover" object-fit="cover"
:src="img.content + thumbnail" :src="img.content + thumbnail"
:preview-src="img.content" :preview-src="img.content"
@error="() => (img.content = defaultImg)"
@click.stop
/> />
</n-gi> </n-gi>
</template> </template>
@ -178,42 +178,42 @@
<n-image-group v-if="props.imgs.length === 9"> <n-image-group v-if="props.imgs.length === 9">
<n-grid :x-gap="4" :y-gap="4" :cols="3"> <n-grid :x-gap="4" :y-gap="4" :cols="3">
<template v-for="(img, idx) in props.imgs"> <template v-for="(img, idx) in props.imgs">
<n-gi :key="img.id" v-if="idx < 3"> <n-gi v-if="idx < 3" :key="img.id">
<n-image <n-image
@error="() => (img.content = defaultImg)"
@click.stop
class="post-img x2" class="post-img x2"
object-fit="cover" object-fit="cover"
:src="img.content + thumbnail" :src="img.content + thumbnail"
:preview-src="img.content" :preview-src="img.content"
@error="() => (img.content = defaultImg)"
@click.stop
/> />
</n-gi> </n-gi>
</template> </template>
</n-grid> </n-grid>
<n-grid :x-gap="4" :y-gap="4" :cols="3" style="margin-top: 4px"> <n-grid :x-gap="4" :y-gap="4" :cols="3" style="margin-top: 4px">
<template v-for="(img, idx) in props.imgs"> <template v-for="(img, idx) in props.imgs">
<n-gi :key="img.id" v-if="idx >= 3 && idx < 6"> <n-gi v-if="idx >= 3 && idx < 6" :key="img.id">
<n-image <n-image
@error="() => (img.content = defaultImg)"
@click.stop
class="post-img x2" class="post-img x2"
object-fit="cover" object-fit="cover"
:src="img.content + thumbnail" :src="img.content + thumbnail"
:preview-src="img.content" :preview-src="img.content"
@error="() => (img.content = defaultImg)"
@click.stop
/> />
</n-gi> </n-gi>
</template> </template>
</n-grid> </n-grid>
<n-grid :x-gap="4" :y-gap="4" :cols="3" style="margin-top: 4px"> <n-grid :x-gap="4" :y-gap="4" :cols="3" style="margin-top: 4px">
<template v-for="(img, idx) in props.imgs"> <template v-for="(img, idx) in props.imgs">
<n-gi :key="img.id" v-if="idx >= 6"> <n-gi v-if="idx >= 6" :key="img.id">
<n-image <n-image
@error="() => (img.content = defaultImg)"
@click.stop
class="post-img x2" class="post-img x2"
object-fit="cover" object-fit="cover"
:src="img.content + thumbnail" :src="img.content + thumbnail"
:preview-src="img.content" :preview-src="img.content"
@error="() => (img.content = defaultImg)"
@click.stop
/> />
</n-gi> </n-gi>
</template> </template>
@ -229,11 +229,14 @@ const defaultImg =
'https://paopao-assets.oss-cn-shanghai.aliyuncs.com/public/404.png'; 'https://paopao-assets.oss-cn-shanghai.aliyuncs.com/public/404.png';
const thumbnail = const thumbnail =
'?x-oss-process=image/resize,m_fill,w_300,h_300,limit_0/auto-orient,1/format,png'; '?x-oss-process=image/resize,m_fill,w_300,h_300,limit_0/auto-orient,1/format,png';
const props = withDefaults(defineProps<{ const props = withDefaults(
imgs: Item.PostItemProps[], defineProps<{
}>(), { imgs: Item.PostItemProps[];
imgs: () => [] }>(),
}); {
imgs: () => [],
},
);
</script> </script>
<style lang="less"> <style lang="less">

@ -7,12 +7,12 @@
<template #header> <template #header>
<span class="nickname-wrap"> <span class="nickname-wrap">
<router-link <router-link
@click.stop
class="username-link" class="username-link"
:to="{ :to="{
name: 'user', name: 'user',
query: { username: post.user.username }, query: { username: post.user.username },
}" }"
@click.stop
> >
{{ post.user.nickname }} {{ post.user.nickname }}
</router-link> </router-link>
@ -34,7 +34,7 @@
{{ formatRelativeTime(post.created_on) }} {{ formatRelativeTime(post.created_on) }}
</span> </span>
</template> </template>
<template #description v-if="post.texts.length > 0"> <template v-if="post.texts.length > 0" #description>
<span <span
v-for="content in post.texts" v-for="content in post.texts"
:key="content.id" :key="content.id"
@ -96,9 +96,12 @@ import {
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
const store = useStore(); const store = useStore();
const props = withDefaults(defineProps<{ const props = withDefaults(
post: Item.PostProps, defineProps<{
}>(), {}); post: Item.PostProps;
}>(),
{},
);
const post = computed(() => { const post = computed(() => {
let post: Item.PostComponentProps = Object.assign( let post: Item.PostComponentProps = Object.assign(
@ -110,7 +113,7 @@ const post = computed(() => {
attachments: [], attachments: [],
charge_attachments: [], charge_attachments: [],
}, },
props.post props.post,
); );
post.contents.map((content) => { post.contents.map((content) => {
if (+content.type === 1 || +content.type === 2) { if (+content.type === 1 || +content.type === 2) {

@ -1,13 +1,8 @@
<template> <template>
<div class="link-wrap"> <div class="link-wrap">
<div class="link-item" v-for="link in props.links" :key="link.id"> <div v-for="link in props.links" :key="link.id" class="link-item">
<n-icon class="hash-link"><link-outline /></n-icon> <n-icon class="hash-link"><link-outline /></n-icon>
<a <a :href="link.content" class="hash-link" target="_blank" @click.stop>
:href="link.content"
class="hash-link"
target="_blank"
@click.stop
>
<span class="link-txt">{{ link.content }}</span> <span class="link-txt">{{ link.content }}</span>
</a> </a>
</div> </div>
@ -16,11 +11,14 @@
<script setup lang="ts"> <script setup lang="ts">
import { LinkOutline } from '@vicons/ionicons5'; import { LinkOutline } from '@vicons/ionicons5';
const props = withDefaults(defineProps<{ const props = withDefaults(
links: Item.PostItemProps[] defineProps<{
}>(), { links: Item.PostItemProps[];
links: () => [] }>(),
}); {
links: () => [],
},
);
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

@ -1,5 +1,5 @@
<template> <template>
<div class="skeleton-item" v-for="i in new Array(num)" :key="i"> <div v-for="i in new Array(num)" :key="i" class="skeleton-item">
<div class="user"> <div class="user">
<n-skeleton circle size="small" /> <n-skeleton circle size="small" />
</div> </div>
@ -11,11 +11,14 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
const props = withDefaults(defineProps<{ const props = withDefaults(
num: number, defineProps<{
}>(), { num: number;
num: 1 }>(),
}); {
num: 1,
},
);
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

@ -3,13 +3,13 @@
<n-grid :x-gap="4" :y-gap="4" :cols="full ? 1 : 5"> <n-grid :x-gap="4" :y-gap="4" :cols="full ? 1 : 5">
<n-gi :span="full ? 1 : 3"> <n-gi :span="full ? 1 : 3">
<n-video <n-video
@click.stop
v-for="video in props.videos" v-for="video in props.videos"
:key="video.id" :key="video.id"
:src="video.content" :src="video.content"
:colors="['#18a058', '#2aca75']" :colors="['#18a058', '#2aca75']"
:hoverable="true" :hoverable="true"
theme="gradient" theme="gradient"
@click.stop
></n-video> ></n-video>
</n-gi> </n-gi>
</n-grid> </n-grid>
@ -28,6 +28,6 @@ const props = withDefaults(
{ {
videos: () => [], videos: () => [],
full: false, full: false,
} },
); );
</script> </script>

@ -16,21 +16,19 @@
</span> </span>
<router-link <router-link
v-if="props.reply.at_user_id > 0"
class="user-link" class="user-link"
:to="{ :to="{
name: 'user', name: 'user',
query: { username: props.reply.at_user.username }, query: { username: props.reply.at_user.username },
}" }"
v-if="props.reply.at_user_id > 0"
> >
{{ props.reply.at_user.username }} {{ props.reply.at_user.username }}
</router-link> </router-link>
</div> </div>
<div class="timestamp"> <div class="timestamp">
{{ {{
props.reply.ip_loc props.reply.ip_loc ? props.reply.ip_loc + ' · ' : props.reply.ip_loc
? props.reply.ip_loc + ' · '
: props.reply.ip_loc
}} }}
{{ formatRelativeTime(props.reply.created_on) }} {{ formatRelativeTime(props.reply.created_on) }}
<n-popconfirm <n-popconfirm
@ -58,7 +56,7 @@
<div class="base-wrap"> <div class="base-wrap">
<div class="content">{{ props.reply.content }}</div> <div class="content">{{ props.reply.content }}</div>
<div class="reply-switch" v-if="store.state.userInfo.id > 0"> <div v-if="store.state.userInfo.id > 0" class="reply-switch">
<span class="show" @click="focusReply"> </span> <span class="show" @click="focusReply"> </span>
</div> </div>
</div> </div>
@ -71,13 +69,16 @@ import { Trash } from '@vicons/tabler';
import { formatRelativeTime } from '@/utils/formatTime'; import { formatRelativeTime } from '@/utils/formatTime';
import { deleteCommentReply } from '@/api/post'; import { deleteCommentReply } from '@/api/post';
const props = withDefaults(defineProps<{ const props = withDefaults(
reply: Item.ReplyProps, defineProps<{
}>(), {}); reply: Item.ReplyProps;
}>(),
{},
);
const store = useStore(); const store = useStore();
const emit = defineEmits<{ const emit = defineEmits<{
(e: "focusReply", reply: Item.ReplyProps): void, (e: 'focusReply', reply: Item.ReplyProps): void;
(e: "reload"): void (e: 'reload'): void;
}>(); }>();
const focusReply = () => { const focusReply = () => {
@ -100,7 +101,6 @@ const execDelAction = () => {
}; };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.reply-item { .reply-item {
display: flex; display: flex;

@ -1,11 +1,11 @@
<template> <template>
<div class="rightbar-wrap" v-if="!store.state.collapsedRight"> <div v-if="!store.state.collapsedRight" class="rightbar-wrap">
<div class="search-wrap"> <div class="search-wrap">
<n-input <n-input
v-model:value="keyword"
round round
clearable clearable
placeholder="搜一搜..." placeholder="搜一搜..."
v-model:value="keyword"
@keyup.enter.prevent="handleSearch" @keyup.enter.prevent="handleSearch"
> >
<template #prefix> <template #prefix>
@ -15,7 +15,7 @@
</div> </div>
<n-card title="热门话题" embedded :bordered="false" size="small"> <n-card title="热门话题" embedded :bordered="false" size="small">
<n-spin :show="loading"> <n-spin :show="loading">
<div class="hot-tag-item" v-for="tag in tags" :key="tag.id"> <div v-for="tag in tags" :key="tag.id" class="hot-tag-item">
<router-link <router-link
class="hash-link" class="hash-link"
:to="{ :to="{
@ -49,17 +49,10 @@
</div> </div>
<div> <div>
<n-space> <n-space>
<a <a href="https://www.rocs.me" target="_blank" class="hash-link"
href="https://www.rocs.me"
target="_blank"
class="hash-link"
>Roc's Me</a >Roc's Me</a
> >
<a <a href="https://www.rocboss.com" target="_blank" class="hash-link">
href="https://www.rocboss.com"
target="_blank"
class="hash-link"
>
ROCBOSS ROCBOSS
</a> </a>
</n-space> </n-space>

@ -21,7 +21,7 @@
@update:value="goRouter" @update:value="goRouter"
/> />
<div class="user-wrap" v-if="store.state.userInfo.id > 0"> <div v-if="store.state.userInfo.id > 0" class="user-wrap">
<n-avatar <n-avatar
class="user-avatar" class="user-avatar"
round round
@ -50,19 +50,14 @@
</div> </div>
<div class="user-mini-wrap"> <div class="user-mini-wrap">
<n-button <n-button class="logout" quaternary circle @click="handleLogout">
class="logout"
quaternary
circle
@click="handleLogout"
>
<template #icon> <template #icon>
<n-icon :size="24"><log-out-outline /></n-icon> <n-icon :size="24"><log-out-outline /></n-icon>
</template> </template>
</n-button> </n-button>
</div> </div>
</div> </div>
<div class="user-wrap" v-else> <div v-else class="user-wrap">
<div class="login-wrap"> <div class="login-wrap">
<n-button <n-button
strong strong
@ -92,7 +87,7 @@ import { h, ref, watch, computed, onMounted } from 'vue';
import { useRoute, useRouter } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { NIcon, NBadge, useMessage } from 'naive-ui'; import { NIcon, NBadge, useMessage } from 'naive-ui';
import type { RouteRecordName } from "vue-router"; import type { RouteRecordName } from 'vue-router';
import { import {
HomeOutline, HomeOutline,
BookmarkOutline, BookmarkOutline,
@ -243,9 +238,9 @@ const renderMenuIcon = (option: AnyObject) => {
? 'var(--n-item-icon-color-active)' ? 'var(--n-item-icon-color-active)'
: 'var(--n-item-icon-color)', : 'var(--n-item-icon-color)',
}, },
{ default: option.icon } { default: option.icon },
), ),
} },
); );
} }
return h(NIcon, null, { default: option.icon }); return h(NIcon, null, { default: option.icon });

@ -1,7 +1,6 @@
<template> <template>
<n-modal <n-modal
:show="show" :show="show"
@update:show="closeModal"
class="whisper-card" class="whisper-card"
preset="card" preset="card"
size="small" size="small"
@ -11,6 +10,7 @@
:style="{ :style="{
width: '360px', width: '360px',
}" }"
@update:show="closeModal"
> >
<div class="whisper-wrap"> <div class="whisper-wrap">
<n-alert :show-icon="false"> <n-alert :show-icon="false">
@ -23,13 +23,13 @@
</n-alert> </n-alert>
<div class="whisper-line"> <div class="whisper-line">
<n-input <n-input
v-model:value="content"
type="textarea" type="textarea"
placeholder="请输入私信内容(请勿发送不和谐内容,否则将会被封号)" placeholder="请输入私信内容(请勿发送不和谐内容,否则将会被封号)"
:autosize="{ :autosize="{
minRows: 5, minRows: 5,
maxRows: 10, maxRows: 10,
}" }"
v-model:value="content"
maxlength="200" maxlength="200"
show-count show-count
/> />
@ -60,7 +60,7 @@ const props = withDefaults(
}>(), }>(),
{ {
show: false, show: false,
} },
); );
const content = ref(''); const content = ref('');
const loading = ref(false); const loading = ref(false);

@ -1,188 +1,182 @@
declare module NetParams { declare namespace NetParams {
interface AuthUserLogin { interface AuthUserLogin {
/** 用户名 */ /** 用户名 */
username: string, username: string;
/** 密码 */ /** 密码 */
password: string password: string;
} }
interface AuthUserRegister { interface AuthUserRegister {
/** 用户名 */ /** 用户名 */
username: string, username: string;
/** 密码 */ /** 密码 */
password: string password: string;
} }
type AuthUserInfo = string type AuthUserInfo = string;
interface AuthUpdateUserPassword { interface AuthUpdateUserPassword {
/** 新密码 */ /** 新密码 */
password: string, password: string;
/** 旧密码 */ /** 旧密码 */
old_password: string old_password: string;
} }
interface UserGetCollections { interface UserGetCollections {
page: number, page: number;
page_size: number page_size: number;
} }
interface UserPrecheckAttachment { interface UserPrecheckAttachment {
id: number id: number;
} }
interface UserGetAttachment { interface UserGetAttachment {
id: number id: number;
} }
interface UserGetUnreadMsgCount { interface UserGetUnreadMsgCount {}
}
interface UserGetMessages { interface UserGetMessages {
page: number, page: number;
page_size: number page_size: number;
} }
interface UserGetUserPosts { interface UserGetUserPosts {
/** 用户名 */ /** 用户名 */
username: string, username: string;
page: number, page: number;
page_size: number page_size: number;
} }
interface UserGetStars { interface UserGetStars {
page: number, page: number;
page_size: number page_size: number;
} }
interface UserGetUserProfile { interface UserGetUserProfile {
username: string username: string;
} }
interface UserGetBills { interface UserGetBills {
page: number, page: number;
page_size: number page_size: number;
} }
interface UserReqRecharge { interface UserReqRecharge {
amount: number amount: number;
} }
interface UserGetRecharge { interface UserGetRecharge {
id: number id: number;
} }
interface UserBindUserPhone { interface UserBindUserPhone {
phone: string, phone: string;
captcha: string captcha: string;
} }
interface UserGetCaptcha { interface UserGetCaptcha {}
}
interface UserWhisper { interface UserWhisper {
user_id: number, user_id: number;
content: string content: string;
} }
interface UserChangePassword { interface UserChangePassword {
/** 新密码 */ /** 新密码 */
password: string, password: string;
/** 旧密码 */ /** 旧密码 */
old_password: string old_password: string;
} }
interface UserChangeNickname { interface UserChangeNickname {
/** 昵称 */ /** 昵称 */
nickname: string nickname: string;
} }
interface PostGetPost { interface PostGetPost {
id: number id: number;
} }
interface PostGetPosts { interface PostGetPosts {
query: string | null, query: string | null;
type: string, type: string;
page: number, page: number;
page_size: number page_size: number;
} }
interface PostLockPost { interface PostLockPost {
id: number id: number;
} }
interface PostStickPost { interface PostStickPost {
id: number id: number;
} }
interface PostGetPostStar { interface PostGetPostStar {
id: number id: number;
} }
interface PostPostStar { interface PostPostStar {
id: number id: number;
} }
interface PostGetPostCollection { interface PostGetPostCollection {
id: number id: number;
} }
interface PostPostCollection { interface PostPostCollection {
id: number id: number;
} }
interface PostGetTags { interface PostGetTags {
type: "hot" | string, type: 'hot' | string;
num: number num: number;
} }
interface PostGetPostComments { interface PostGetPostComments {
id: number id: number;
} }
interface PostCreatePost { interface PostCreatePost {
/** 帖子内容列表 */ /** 帖子内容列表 */
contents: Partial<Item.PostItemProps>[], contents: Partial<Item.PostItemProps>[];
/** 标签列表 */ /** 标签列表 */
tags: string[], tags: string[];
/** 艾特用户列表 */ /** 艾特用户列表 */
users: string[], users: string[];
/** 附件价格 */ /** 附件价格 */
attachment_price: number attachment_price: number;
} }
interface PostDeletePost { interface PostDeletePost {
id: number id: number;
} }
interface PostCreateComment { interface PostCreateComment {
/** 内容ID */ /** 内容ID */
post_id: number, post_id: number;
/** 帖子内容列表 */ /** 帖子内容列表 */
contents: Partial<Item.CommentItemProps>[], contents: Partial<Item.CommentItemProps>[];
/** 艾特用户列表 */ /** 艾特用户列表 */
users: string[] users: string[];
} }
interface PostDeleteComment { interface PostDeleteComment {
id: number id: number;
} }
interface PostCreateCommentReply { interface PostCreateCommentReply {
/** 艾特的用户UID */ /** 艾特的用户UID */
at_user_id: number, at_user_id: number;
/** 回复的评论ID */ /** 回复的评论ID */
comment_id: number, comment_id: number;
/** 回复内容 */ /** 回复内容 */
content: string content: string;
} }
interface PostDeleteCommentReply{ interface PostDeleteCommentReply {
id: number id: number;
} }
} }

@ -1,158 +1,142 @@
declare module NetReq { declare namespace NetReq {
interface AuthUserLogin { interface AuthUserLogin {
token: string token: string;
} }
interface AuthUserRegister { interface AuthUserRegister {
/** 用户UID */ /** 用户UID */
id: number, id: number;
/** 用户名 */ /** 用户名 */
username: string username: string;
} }
type AuthUserInfo = Item.UserInfo type AuthUserInfo = Item.UserInfo;
interface AuthUpdateUserPassword {
} interface AuthUpdateUserPassword {}
interface UserGetCollections { interface UserGetCollections {
/** 帖子列表 */ /** 帖子列表 */
list: Item.PostProps[], list: Item.PostProps[];
/** 页码信息 */ /** 页码信息 */
pager: Item.PagerProps pager: Item.PagerProps;
} }
type UserGetSuggestUsers = string[] type UserGetSuggestUsers = string[];
type UserGetSuggestTags = string[] type UserGetSuggestTags = string[];
interface UserPrecheckAttachment { interface UserPrecheckAttachment {
paid: number paid: number;
} }
type UserGetAttachment = string type UserGetAttachment = string;
interface UserGetUnreadMsgCount { interface UserGetUnreadMsgCount {
count: number count: number;
} }
interface UserGetMessages { interface UserGetMessages {
/** 消息列表 */ /** 消息列表 */
list: Item.MessageProps[], list: Item.MessageProps[];
/** 页码信息 */ /** 页码信息 */
pager: Item.PagerProps pager: Item.PagerProps;
} }
interface UserGetUserPosts { interface UserGetUserPosts {
/** 帖子列表 */ /** 帖子列表 */
list: Item.PostProps[], list: Item.PostProps[];
/** 页码信息 */ /** 页码信息 */
pager: Item.PagerProps pager: Item.PagerProps;
} }
interface UserGetStars { interface UserGetStars {
/** 帖子列表 */ /** 帖子列表 */
list: Item.PostProps[], list: Item.PostProps[];
/** 页码信息 */ /** 页码信息 */
pager: Item.PagerProps pager: Item.PagerProps;
} }
type UserGetUserProfile = Item.UserInfo type UserGetUserProfile = Item.UserInfo;
interface UserGetBills { interface UserGetBills {
list: Item.BillProps[], list: Item.BillProps[];
/** 页码信息 */ /** 页码信息 */
pager: Item.PagerProps pager: Item.PagerProps;
} }
interface UserReqRecharge { interface UserReqRecharge {
id: number, id: number;
pay: string pay: string;
} }
interface UserGetRecharge { interface UserGetRecharge {
status: string status: string;
} }
interface UserBindUserPhone { interface UserBindUserPhone {}
}
interface UserGetCaptcha { interface UserGetCaptcha {
id: string, id: string;
/** 头像图片 base64 */ /** 头像图片 base64 */
b64s: string b64s: string;
}
interface UserChangeNickname {
} }
interface UserChangePassword { interface UserChangeNickname {}
} interface UserChangePassword {}
type PostGetPost = Item.PostProps type PostGetPost = Item.PostProps;
interface PostGetPosts { interface PostGetPosts {
/** 帖子列表 */ /** 帖子列表 */
list: Item.PostProps[], list: Item.PostProps[];
/** 页码信息 */ /** 页码信息 */
pager: Item.PagerProps pager: Item.PagerProps;
} }
interface PostLockPost { interface PostLockPost {
/** 锁定状态0为未锁定1为锁定 */ /** 锁定状态0为未锁定1为锁定 */
lock_status: 0 | 1 lock_status: 0 | 1;
} }
interface PostStickPost { interface PostStickPost {
/** 置顶状态0为未置顶1为置顶 */ /** 置顶状态0为未置顶1为置顶 */
top_status: 0 | 1 top_status: 0 | 1;
} }
interface PostGetPostStar { interface PostGetPostStar {
status: boolean status: boolean;
} }
interface PostPostStar { interface PostPostStar {
status: boolean status: boolean;
} }
interface PostGetPostCollection { interface PostGetPostCollection {
status: boolean status: boolean;
} }
interface PostPostCollection { interface PostPostCollection {
status: boolean status: boolean;
} }
type PostGetTags = Item.TagProps[] type PostGetTags = Item.TagProps[];
interface PostGetPostComments { interface PostGetPostComments {
/** 评论列表 */ /** 评论列表 */
list: Item.CommentProps[], list: Item.CommentProps[];
/** 页码信息 */ /** 页码信息 */
pager: Item.PagerProps pager: Item.PagerProps;
}
type PostCreatePost = Item.PostProps
interface PostDeletePost {
} }
type PostCreateComment = Item.CommentProps type PostCreatePost = Item.PostProps;
interface PostDeleteComment {
} interface PostDeletePost {}
type PostCreateCommentReply = Item.ReplyProps type PostCreateComment = Item.CommentProps;
interface PostDeleteCommentReply{ interface PostDeleteComment {}
} type PostCreateCommentReply = Item.ReplyProps;
interface PostDeleteCommentReply {}
} }

@ -1,290 +1,288 @@
declare module Item { declare namespace Item {
interface UserInfo { interface UserInfo {
/** 用户UID */ /** 用户UID */
id: number, id: number;
/** 用户名 */ /** 用户名 */
username: string, username: string;
/** 用户昵称 */ /** 用户昵称 */
nickname: string, nickname: string;
/** 用户头像 */ /** 用户头像 */
avatar: string, avatar: string;
/** 用户手机号 */ /** 用户手机号 */
phone?: string, phone?: string;
/** 是否为管理员 */ /** 是否为管理员 */
is_admin: boolean, is_admin: boolean;
/** 用户余额(分) */ /** 用户余额(分) */
balance?: number, balance?: number;
/** 用户状态 */ /** 用户状态 */
status?: 0 | 1 status?: 0 | 1;
} }
/** 评论内容 */ /** 评论内容 */
interface CommentItemProps { interface CommentItemProps {
/** 内容ID */ /** 内容ID */
id: number, id: number;
/** 评论ID */ /** 评论ID */
comment_id: number, comment_id: number;
/** 评论者UID */ /** 评论者UID */
user_id: number, user_id: number;
/** 类别1为标题2为文字段落3为图片地址4为视频地址5为语音地址6为链接地址 */ /** 类别1为标题2为文字段落3为图片地址4为视频地址5为语音地址6为链接地址 */
type: number, type: number;
/** 内容 */ /** 内容 */
content: string, content: string;
/** 排序,越小越靠前 */ /** 排序,越小越靠前 */
sort: number, sort: number;
/** 创建时间 */ /** 创建时间 */
created_on: number, created_on: number;
/** 修改时间 */ /** 修改时间 */
modified_on?: number, modified_on?: number;
/** 删除时间 */ /** 删除时间 */
deleted_on?: number, deleted_on?: number;
/** 是否删除0为未删除1为已删除 */ /** 是否删除0为未删除1为已删除 */
is_del?: 0 | 1 is_del?: 0 | 1;
} }
/** 评论数据 */ /** 评论数据 */
interface CommentProps { interface CommentProps {
id: number, id: number;
post_id: number, post_id: number;
/** 评论者UID */ /** 评论者UID */
user_id: number, user_id: number;
/** 评论者用户信息 */ /** 评论者用户信息 */
user: UserInfo, user: UserInfo;
/** 评论内容 */ /** 评论内容 */
contents: CommentItemProps[], contents: CommentItemProps[];
/** 回复列表 */ /** 回复列表 */
replies: ReplyProps[], replies: ReplyProps[];
/** 评论者IP地址 */ /** 评论者IP地址 */
ip?: string, ip?: string;
/** 评论者城市地址 */ /** 评论者城市地址 */
ip_loc: string, ip_loc: string;
/** 创建时间 */ /** 创建时间 */
created_on: number, created_on: number;
/** 修改时间 */ /** 修改时间 */
modified_on?: number, modified_on?: number;
/** 删除时间 */ /** 删除时间 */
deleted_on?: number, deleted_on?: number;
/** 是否删除0为未删除1为已删除 */ /** 是否删除0为未删除1为已删除 */
is_del?: 0 | 1 is_del?: 0 | 1;
} }
interface CommentComponentProps extends CommentProps { interface CommentComponentProps extends CommentProps {
/** 文字评论列表 */ /** 文字评论列表 */
texts: CommentItemProps[], texts: CommentItemProps[];
/** 图片评论列表 */ /** 图片评论列表 */
imgs: CommentItemProps[] imgs: CommentItemProps[];
} }
/** 回复内容 */ /** 回复内容 */
interface ReplyProps { interface ReplyProps {
/** 内容ID */ /** 内容ID */
id: number, id: number;
/** 评论ID */ /** 评论ID */
comment_id: number, comment_id: number;
/** 回复人ID */ /** 回复人ID */
user_id: number, user_id: number;
/** 回复人用户数据 */ /** 回复人用户数据 */
user: UserInfo, user: UserInfo;
/** 艾特人ID */ /** 艾特人ID */
at_user_id: number, at_user_id: number;
/** 艾特人用户数据 */ /** 艾特人用户数据 */
at_user: UserInfo, at_user: UserInfo;
/** 内容 */ /** 内容 */
content: string, content: string;
/** 回复人IP地址 */ /** 回复人IP地址 */
ip?: string, ip?: string;
/** 回复人城市地址 */ /** 回复人城市地址 */
ip_loc: string, ip_loc: string;
/** 创建时间 */ /** 创建时间 */
created_on: number, created_on: number;
/** 修改时间 */ /** 修改时间 */
modified_on?: number, modified_on?: number;
/** 删除时间 */ /** 删除时间 */
deleted_on?: number, deleted_on?: number;
/** 是否删除0为未删除1为已删除 */ /** 是否删除0为未删除1为已删除 */
is_del?: 0 | 1 is_del?: 0 | 1;
} }
/** 帖子内容 */ /** 帖子内容 */
interface PostItemProps { interface PostItemProps {
/** 内容ID */ /** 内容ID */
id: number, id: number;
/** 类型1为标题2为文字段落3为图片地址4为视频地址5为语音地址6为链接地址7为附件资源8为收费资源 */ /** 类型1为标题2为文字段落3为图片地址4为视频地址5为语音地址6为链接地址7为附件资源8为收费资源 */
type: number, type: number;
/** POST ID */ /** POST ID */
post_id: number, post_id: number;
/** 内容 */ /** 内容 */
content: string, content: string;
/** 排序,越小越靠前 */ /** 排序,越小越靠前 */
sort: number, sort: number;
/** 用户UID */ /** 用户UID */
user_id?: number, user_id?: number;
/** 创建时间 */ /** 创建时间 */
created_on: number, created_on: number;
/** 修改时间 */ /** 修改时间 */
modified_on?: number, modified_on?: number;
/** 删除时间 */ /** 删除时间 */
deleted_on?: number, deleted_on?: number;
/** 是否删除0为未删除1为已删除 */ /** 是否删除0为未删除1为已删除 */
is_del?: 0 | 1, is_del?: 0 | 1;
} }
/** 帖子 */ /** 帖子 */
interface PostProps { interface PostProps {
id: number, id: number;
/** 发帖人UID */ /** 发帖人UID */
user_id: number, user_id: number;
/** 发帖人用户数据 */ /** 发帖人用户数据 */
user: UserInfo, user: UserInfo;
/** 附件价格(分) */ /** 附件价格(分) */
attachment_price: number, attachment_price: number;
/** 发帖时IP地址 */ /** 发帖时IP地址 */
ip?: string, ip?: string;
/** 发帖时城市地址 */ /** 发帖时城市地址 */
ip_loc: string, ip_loc: string;
/** 最新回复时间 */ /** 最新回复时间 */
latest_replied_on: number, latest_replied_on: number;
/** 创建时间 */ /** 创建时间 */
created_on: number, created_on: number;
/** 修改时间 */ /** 修改时间 */
modified_on?: number, modified_on?: number;
/** 删除时间 */ /** 删除时间 */
deleted_on?: number, deleted_on?: number;
/** 点赞数 */ /** 点赞数 */
upvote_count: number, upvote_count: number;
/** 评论数 */ /** 评论数 */
comment_count: number, comment_count: number;
/** 收藏数 */ /** 收藏数 */
collection_count: number, collection_count: number;
/** 内容列表 */ /** 内容列表 */
contents: PostItemProps[], contents: PostItemProps[];
/** 标签列表 */ /** 标签列表 */
tags: {[key: string]: number} | string, tags: { [key: string]: number } | string;
/** 是否锁定 */ /** 是否锁定 */
is_lock: number, is_lock: number;
/** 是否置顶 */ /** 是否置顶 */
is_top: number, is_top: number;
/** 是否精华 */ /** 是否精华 */
is_essence: number, is_essence: number;
/** 是否删除0为未删除1为已删除 */ /** 是否删除0为未删除1为已删除 */
is_del?: 0 | 1 is_del?: 0 | 1;
} }
/** 组件用帖子 */ /** 组件用帖子 */
interface PostComponentProps extends PostProps { interface PostComponentProps extends PostProps {
/** 文字段落列表 */ /** 文字段落列表 */
texts: PostItemProps[], texts: PostItemProps[];
/** 图片列表 */ /** 图片列表 */
imgs: PostItemProps[], imgs: PostItemProps[];
/** 视频列表 */ /** 视频列表 */
videos: PostItemProps[], videos: PostItemProps[];
/** 链接列表 */ /** 链接列表 */
links: PostItemProps[], links: PostItemProps[];
/** 附件列表 */ /** 附件列表 */
attachments: PostItemProps[], attachments: PostItemProps[];
/** 收费附件列表 */ /** 收费附件列表 */
charge_attachments: PostItemProps[] charge_attachments: PostItemProps[];
} }
interface MessageProps { interface MessageProps {
id: number, id: number;
/** 类型1为动态2为评论3为回复4为私信99为系统通知 */ /** 类型1为动态2为评论3为回复4为私信99为系统通知 */
type: 1 | 2 | 3 | 4 | 99, type: 1 | 2 | 3 | 4 | 99;
/** 摘要说明 */ /** 摘要说明 */
breif: string, breif: string;
/** 详细内容 */ /** 详细内容 */
content: string, content: string;
/** 是否已读0为未读1为已读 */ /** 是否已读0为未读1为已读 */
is_read: 0 | 1, is_read: 0 | 1;
/** 发送人UID */ /** 发送人UID */
sender_user_id: number, sender_user_id: number;
/** 发送人用户数据 */ /** 发送人用户数据 */
sender_user: UserInfo, sender_user: UserInfo;
/** 接收方UID */ /** 接收方UID */
receiver_user_id: number, receiver_user_id: number;
/** 帖子ID */ /** 帖子ID */
post_id: number, post_id: number;
/** 帖子内容 */ /** 帖子内容 */
post: PostProps, post: PostProps;
/** 评论ID */ /** 评论ID */
comment_id: number, comment_id: number;
/** 评论内容 */ /** 评论内容 */
comment: CommentProps, comment: CommentProps;
/** 回复ID */ /** 回复ID */
reply_id: number, reply_id: number;
/** 回复内容 */ /** 回复内容 */
replay: ReplyProps, replay: ReplyProps;
/** 创建时间 */ /** 创建时间 */
created_on: number, created_on: number;
/** 修改时间 */ /** 修改时间 */
modified_on?: number, modified_on?: number;
/** 删除时间 */ /** 删除时间 */
deleted_on?: number, deleted_on?: number;
/** 是否删除0为未删除1为已删除 */ /** 是否删除0为未删除1为已删除 */
is_del?: 0 | 1 is_del?: 0 | 1;
} }
interface AttachmentProps { interface AttachmentProps {
id: number, id: number;
/** 类别1为图片2为视频3为其他附件 */ /** 类别1为图片2为视频3为其他附件 */
type: 1 | 2 | 3, type: 1 | 2 | 3;
/** 发布者用户UID */ /** 发布者用户UID */
user_id: number, user_id: number;
/** 发布者用户数据 */ /** 发布者用户数据 */
user: UserInfo, user: UserInfo;
/** 文件大小 */ /** 文件大小 */
file_size: number, file_size: number;
/** 图片宽度 */ /** 图片宽度 */
img_width?: number, img_width?: number;
/** 图片高度 */ /** 图片高度 */
img_height?: number, img_height?: number;
/** 内容 */ /** 内容 */
content: string, content: string;
/** 创建时间 */ /** 创建时间 */
created_on: number, created_on: number;
/** 修改时间 */ /** 修改时间 */
modified_on?: number, modified_on?: number;
/** 删除时间 */ /** 删除时间 */
deleted_on?: number, deleted_on?: number;
/** 是否删除0为未删除1为已删除 */ /** 是否删除0为未删除1为已删除 */
is_del?: 0 | 1 is_del?: 0 | 1;
} }
interface TagProps { interface TagProps {
id: number, id: number;
/** 创建者UID */ /** 创建者UID */
user_id: number, user_id: number;
/** 创建者用户数据 */ /** 创建者用户数据 */
user: UserInfo, user: UserInfo;
/** 标签名 */ /** 标签名 */
tag: string, tag: string;
/** 引用数 */ /** 引用数 */
quote_num: number, quote_num: number;
/** 创建时间 */ /** 创建时间 */
created_on: number, created_on: number;
/** 修改时间 */ /** 修改时间 */
modified_on?: number, modified_on?: number;
/** 删除时间 */ /** 删除时间 */
deleted_on?: number, deleted_on?: number;
/** 是否删除0为未删除1为已删除 */ /** 是否删除0为未删除1为已删除 */
is_del?: 0 | 1 is_del?: 0 | 1;
} }
interface PagerProps { interface PagerProps {
/** 当前页码 */ /** 当前页码 */
page: number, page: number;
/** 每页条数 */ /** 每页条数 */
page_size: number, page_size: number;
/** 总条数 */ /** 总条数 */
total_rows: number total_rows: number;
} }
interface BillProps { interface BillProps {
id: number, id: number;
reason: string, reason: string;
change_amount: number, change_amount: number;
created_on: number created_on: number;
} }
} }

@ -2,8 +2,8 @@
export const parsePostTag = (content: string) => { export const parsePostTag = (content: string) => {
const tags: string[] = [] const tags: string[] = []
const users: string[] = [] const users: string[] = []
var tagExp = /(#|)([^#@])+?\s+?/g // 这⾥中⽂#和英⽂#都会识别 const tagExp = /(#|)([^#@])+?\s+?/g // 这⾥中⽂#和英⽂#都会识别
var atExp = /@([a-zA-Z0-9])+?\s+?/g // 这⾥中⽂#和英⽂#都会识别 const atExp = /@([a-zA-Z0-9])+?\s+?/g // 这⾥中⽂#和英⽂#都会识别
content = content content = content
.replace(/<[^>]*?>/gi, '') .replace(/<[^>]*?>/gi, '')
.replace(/(.*?)<\/[^>]*?>/gi, '') .replace(/(.*?)<\/[^>]*?>/gi, '')

@ -1,8 +1,8 @@
// 滚动到顶部 // 滚动到顶部
export const scrollToTop = (scrollDuration: number) => { export const scrollToTop = (scrollDuration: number) => {
var cosParameter = window.scrollY / 2; const cosParameter = window.scrollY / 2;
var scrollCount = 0; let scrollCount = 0;
var oldTimestamp = performance.now(); let oldTimestamp = performance.now();
function step(newTimestamp: number) { function step(newTimestamp: number) {
scrollCount += scrollCount +=
Math.PI / (scrollDuration / (newTimestamp - oldTimestamp)); Math.PI / (scrollDuration / (newTimestamp - oldTimestamp));

@ -4,12 +4,12 @@
<n-list class="main-content-wrap" bordered> <n-list class="main-content-wrap" bordered>
<template #footer> <template #footer>
<div class="pagination-wrap" v-if="totalPage > 0"> <div v-if="totalPage > 0" class="pagination-wrap">
<n-pagination <n-pagination
:page="page" :page="page"
@update:page="updatePage"
:page-slot="!store.state.collapsedRight ? 8 : 5" :page-slot="!store.state.collapsedRight ? 8 : 5"
:page-count="totalPage" :page-count="totalPage"
@update:page="updatePage"
/> />
</div> </div>
</template> </template>
@ -18,7 +18,7 @@
<post-skeleton :num="pageSize" /> <post-skeleton :num="pageSize" />
</div> </div>
<div v-else> <div v-else>
<div class="empty-wrap" v-if="list.length === 0"> <div v-if="list.length === 0" class="empty-wrap">
<n-empty size="large" description="暂无数据" /> <n-empty size="large" description="暂无数据" />
</div> </div>

@ -4,12 +4,12 @@
<n-list class="main-content-wrap" bordered> <n-list class="main-content-wrap" bordered>
<template #footer> <template #footer>
<div class="pagination-wrap" v-if="totalPage > 0"> <div v-if="totalPage > 0" class="pagination-wrap">
<n-pagination <n-pagination
:page="page" :page="page"
@update:page="updatePage"
:page-slot="!store.state.collapsedRight ? 8 : 5" :page-slot="!store.state.collapsedRight ? 8 : 5"
:page-count="totalPage" :page-count="totalPage"
@update:page="updatePage"
/> />
</div> </div>
</template> </template>
@ -22,7 +22,7 @@
<post-skeleton :num="pageSize" /> <post-skeleton :num="pageSize" />
</div> </div>
<div v-else> <div v-else>
<div class="empty-wrap" v-if="list.length === 0"> <div v-if="list.length === 0" class="empty-wrap">
<n-empty size="large" description="暂无数据" /> <n-empty size="large" description="暂无数据" />
</div> </div>
@ -126,7 +126,7 @@ watch(
loadPosts(); loadPosts();
}, 0); }, 0);
} }
} },
); );
</script> </script>

@ -8,7 +8,7 @@
</div> </div>
<div v-else> <div v-else>
<div class="empty-wrap" v-if="list.length === 0"> <div v-if="list.length === 0" class="empty-wrap">
<n-empty size="large" description="暂无数据" /> <n-empty size="large" description="暂无数据" />
</div> </div>
@ -18,12 +18,12 @@
</div> </div>
<template #footer> <template #footer>
<div class="pagination-wrap" v-if="totalPage > 0"> <div v-if="totalPage > 0" class="pagination-wrap">
<n-pagination <n-pagination
:page="page" :page="page"
@update:page="updatePage"
:page-slot="!store.state.collapsedRight ? 8 : 5" :page-slot="!store.state.collapsedRight ? 8 : 5"
:page-count="totalPage" :page-count="totalPage"
@update:page="updatePage"
/> />
</div> </div>
</template> </template>

@ -5,10 +5,10 @@
<n-list class="main-content-wrap" bordered> <n-list class="main-content-wrap" bordered>
<n-list-item> <n-list-item>
<n-spin :show="loading"> <n-spin :show="loading">
<div class="detail-wrap" v-if="post.id > 0"> <div v-if="post.id > 0" class="detail-wrap">
<post-detail :post="post" @reload="loadPost" /> <post-detail :post="post" @reload="loadPost" />
</div> </div>
<div class="empty-wrap" v-else> <div v-else class="empty-wrap">
<n-empty size="large" description="暂无数据" /> <n-empty size="large" description="暂无数据" />
</div> </div>
</n-spin> </n-spin>
@ -26,18 +26,12 @@
<post-skeleton :num="5" /> <post-skeleton :num="5" />
</div> </div>
<div v-else> <div v-else>
<div class="empty-wrap" v-if="comments.length === 0"> <div v-if="comments.length === 0" class="empty-wrap">
<n-empty <n-empty size="large" description="暂无评论,快来抢沙发" />
size="large"
description="暂无评论,快来抢沙发"
/>
</div> </div>
<n-list-item v-for="comment in comments" :key="comment.id"> <n-list-item v-for="comment in comments" :key="comment.id">
<comment-item <comment-item :comment="comment" @reload="loadComments" />
:comment="comment"
@reload="loadComments"
/>
</n-list-item> </n-list-item>
</div> </div>
</div> </div>
@ -76,7 +70,7 @@ const loadPost = () => {
loading.value = false; loading.value = false;
}); });
}; };
const loadComments = (scrollToBottom: boolean = false) => { const loadComments = (scrollToBottom = false) => {
if (comments.value.length === 0) { if (comments.value.length === 0) {
commentLoading.value = true; commentLoading.value = true;
} }

@ -3,9 +3,9 @@
<main-nav title="主页" /> <main-nav title="主页" />
<n-list <n-list
v-if="store.state.userInfo.id > 0"
class="main-content-wrap profile-wrap" class="main-content-wrap profile-wrap"
bordered bordered
v-if="store.state.userInfo.id > 0"
> >
<!-- --> <!-- -->
<div class="profile-baseinfo"> <div class="profile-baseinfo">
@ -21,12 +21,12 @@
</div> </div>
</div> </div>
<template #footer> <template #footer>
<div class="pagination-wrap" v-if="totalPage > 0"> <div v-if="totalPage > 0" class="pagination-wrap">
<n-pagination <n-pagination
:page="page" :page="page"
@update:page="updatePage"
:page-slot="!store.state.collapsedRight ? 8 : 5" :page-slot="!store.state.collapsedRight ? 8 : 5"
:page-count="totalPage" :page-count="totalPage"
@update:page="updatePage"
/> />
</div> </div>
</template> </template>
@ -38,7 +38,7 @@
<post-skeleton :num="pageSize" /> <post-skeleton :num="pageSize" />
</div> </div>
<div v-else> <div v-else>
<div class="empty-wrap" v-if="list.length === 0"> <div v-if="list.length === 0" class="empty-wrap">
<n-empty size="large" description="暂无数据" /> <n-empty size="large" description="暂无数据" />
</div> </div>

@ -29,22 +29,22 @@
{{ store.state.userInfo.nickname }} {{ store.state.userInfo.nickname }}
</div> </div>
<n-input <n-input
ref="inputInstRef"
v-show="showNicknameEdit" v-show="showNicknameEdit"
class="nickname-input" ref="inputInstRef"
v-model:value="store.state.userInfo.nickname" v-model:value="store.state.userInfo.nickname"
class="nickname-input"
type="text" type="text"
size="small" size="small"
placeholder="请输入昵称" placeholder="请输入昵称"
@blur="handleNicknameChange"
:maxlength="16" :maxlength="16"
@blur="handleNicknameChange"
/> />
<n-button <n-button
v-if="!showNicknameEdit"
quaternary quaternary
round round
type="success" type="success"
size="small" size="small"
v-if="!showNicknameEdit"
@click="handleNicknameShow" @click="handleNicknameShow"
> >
<template #icon> <template #icon>
@ -64,17 +64,16 @@
<n-card title="手机号" size="small" class="setting-card"> <n-card title="手机号" size="small" class="setting-card">
<div <div
v-if=" v-if="
store.state.userInfo.phone && store.state.userInfo.phone && store.state.userInfo.phone.length > 0
store.state.userInfo.phone.length > 0
" "
> >
{{ store.state.userInfo.phone }} {{ store.state.userInfo.phone }}
<n-button <n-button
v-if="!showPhoneBind"
quaternary quaternary
round round
type="success" type="success"
v-if="!showPhoneBind"
@click="showPhoneBind = true" @click="showPhoneBind = true"
> >
@ -84,26 +83,22 @@
<n-alert title="手机绑定提示" type="warning"> <n-alert title="手机绑定提示" type="warning">
~ ~
<a <a
v-if="!showPhoneBind"
class="hash-link" class="hash-link"
@click="showPhoneBind = true" @click="showPhoneBind = true"
v-if="!showPhoneBind"
> >
</a> </a>
</n-alert> </n-alert>
</div> </div>
<div class="phone-bind-wrap" v-if="showPhoneBind"> <div v-if="showPhoneBind" class="phone-bind-wrap">
<n-form <n-form ref="phoneFormRef" :model="modelData" :rules="bindRules">
ref="phoneFormRef"
:model="modelData"
:rules="bindRules"
>
<n-form-item path="phone" label="手机号"> <n-form-item path="phone" label="手机号">
<n-input <n-input
:value="modelData.phone" :value="modelData.phone"
@update:value="(v) => (modelData.phone = v.trim())"
placeholder="请输入中国大陆手机号" placeholder="请输入中国大陆手机号"
@update:value="(v) => (modelData.phone = v.trim())"
@keydown.enter.prevent @keydown.enter.prevent
/> />
</n-form-item> </n-form-item>
@ -146,11 +141,7 @@
<n-row :gutter="[0, 24]"> <n-row :gutter="[0, 24]">
<n-col :span="24"> <n-col :span="24">
<div class="form-submit-wrap"> <div class="form-submit-wrap">
<n-button <n-button quaternary round @click="showPhoneBind = false">
quaternary
round
@click="showPhoneBind = false"
>
</n-button> </n-button>
<n-button <n-button
@ -172,15 +163,15 @@
<n-card title="账户安全" size="small" class="setting-card"> <n-card title="账户安全" size="small" class="setting-card">
<n-button <n-button
v-if="!showPasswordSetting"
quaternary quaternary
round round
type="success" type="success"
v-if="!showPasswordSetting"
@click="showPasswordSetting = true" @click="showPasswordSetting = true"
> >
</n-button> </n-button>
<div class="phone-bind-wrap" v-if="showPasswordSetting"> <div v-if="showPasswordSetting" class="phone-bind-wrap">
<n-form ref="formRef" :model="modelData" :rules="passwordRules"> <n-form ref="formRef" :model="modelData" :rules="passwordRules">
<n-form-item path="old_password" label="旧密码"> <n-form-item path="old_password" label="旧密码">
<n-input <n-input
@ -216,11 +207,7 @@
<n-row :gutter="[0, 24]"> <n-row :gutter="[0, 24]">
<n-col :span="24"> <n-col :span="24">
<div class="form-submit-wrap"> <div class="form-submit-wrap">
<n-button <n-button quaternary round @click="showPasswordSetting = false">
quaternary
round
@click="showPasswordSetting = false"
>
</n-button> </n-button>
<n-button <n-button
@ -285,9 +272,9 @@ const modelData = reactive({
imgCaptcha: '', imgCaptcha: '',
phone: '', phone: '',
phone_captcha: '', phone_captcha: '',
password: "", password: '',
old_password: "", old_password: '',
reenteredPassword: "", reenteredPassword: '',
}); });
const beforeUpload = async (data: any) => { const beforeUpload = async (data: any) => {

@ -4,12 +4,12 @@
<n-list class="main-content-wrap" bordered> <n-list class="main-content-wrap" bordered>
<template #footer> <template #footer>
<div class="pagination-wrap" v-if="totalPage > 0"> <div v-if="totalPage > 0" class="pagination-wrap">
<n-pagination <n-pagination
:page="page" :page="page"
@update:page="updatePage"
:page-slot="!store.state.collapsedRight ? 8 : 5" :page-slot="!store.state.collapsedRight ? 8 : 5"
:page-count="totalPage" :page-count="totalPage"
@update:page="updatePage"
/> />
</div> </div>
</template> </template>
@ -18,7 +18,7 @@
<post-skeleton :num="pageSize" /> <post-skeleton :num="pageSize" />
</div> </div>
<div v-else> <div v-else>
<div class="empty-wrap" v-if="list.length === 0"> <div v-if="list.length === 0" class="empty-wrap">
<n-empty size="large" description="暂无数据" /> <n-empty size="large" description="暂无数据" />
</div> </div>

@ -10,11 +10,11 @@
<n-spin :show="loading"> <n-spin :show="loading">
<n-space> <n-space>
<n-tag <n-tag
v-for="tag in tags"
:key="tag.id"
class="tag-item" class="tag-item"
type="success" type="success"
round round
v-for="tag in tags"
:key="tag.id"
> >
<router-link <router-link
class="hash-link" class="hash-link"

@ -5,7 +5,7 @@
<n-list class="main-content-wrap profile-wrap" bordered> <n-list class="main-content-wrap profile-wrap" bordered>
<!-- --> <!-- -->
<n-spin :show="userLoading"> <n-spin :show="userLoading">
<div class="profile-baseinfo" v-if="user.id > 0"> <div v-if="user.id > 0" class="profile-baseinfo">
<div class="avatar"> <div class="avatar">
<n-avatar size="large" :src="user.avatar" /> <n-avatar size="large" :src="user.avatar" />
</div> </div>
@ -32,19 +32,15 @@
</div> </div>
<!-- --> <!-- -->
<whisper <whisper :show="showWhisper" :user="user" @success="whisperSuccess" />
:show="showWhisper"
:user="user"
@success="whisperSuccess"
/>
</n-spin> </n-spin>
<template #footer> <template #footer>
<div class="pagination-wrap" v-if="totalPage > 0"> <div v-if="totalPage > 0" class="pagination-wrap">
<n-pagination <n-pagination
:page="page" :page="page"
@update:page="updatePage"
:page-slot="!store.state.collapsedRight ? 8 : 5" :page-slot="!store.state.collapsedRight ? 8 : 5"
:page-count="totalPage" :page-count="totalPage"
@update:page="updatePage"
/> />
</div> </div>
</template> </template>
@ -56,7 +52,7 @@
<post-skeleton :num="pageSize" /> <post-skeleton :num="pageSize" />
</div> </div>
<div v-else> <div v-else>
<div class="empty-wrap" v-if="list.length === 0"> <div v-if="list.length === 0" class="empty-wrap">
<n-empty size="large" description="暂无数据" /> <n-empty size="large" description="暂无数据" />
</div> </div>
@ -151,7 +147,7 @@ watch(
username.value = route.query.username || ''; username.value = route.query.username || '';
loadUser(); loadUser();
} }
} },
); );
onMounted(() => { onMounted(() => {
loadUser(); loadUser();

@ -37,12 +37,12 @@
</div> </div>
<template #footer> <template #footer>
<div class="pagination-wrap" v-if="totalPage > 0"> <div v-if="totalPage > 0" class="pagination-wrap">
<n-pagination <n-pagination
:page="page" :page="page"
@update:page="updatePage"
:page-slot="!store.state.collapsedRight ? 8 : 5" :page-slot="!store.state.collapsedRight ? 8 : 5"
:page-count="totalPage" :page-count="totalPage"
@update:page="updatePage"
/> />
</div> </div>
</template> </template>
@ -51,7 +51,7 @@
<post-skeleton :num="pageSize" /> <post-skeleton :num="pageSize" />
</div> </div>
<div v-else> <div v-else>
<div class="empty-wrap" v-if="list.length === 0"> <div v-if="list.length === 0" class="empty-wrap">
<n-empty size="large" description="暂无数据" /> <n-empty size="large" description="暂无数据" />
</div> </div>
@ -85,18 +85,14 @@
aria-modal="true" aria-modal="true"
style="width: 100%; max-width: 330px" style="width: 100%; max-width: 330px"
> >
<div class="amount-options" v-if="rechargeQrcode.length === 0"> <div v-if="rechargeQrcode.length === 0" class="amount-options">
<n-space align="baseline"> <n-space align="baseline">
<n-button <n-button
v-for="amount in openAmounts" v-for="amount in openAmounts"
:key="amount" :key="amount"
size="small" size="small"
secondary secondary
:type=" :type="selectedRechargeAmount === amount ? 'info' : 'default'"
selectedRechargeAmount === amount
? 'info'
: 'default'
"
@click.stop="selectedRechargeAmount = amount" @click.stop="selectedRechargeAmount = amount"
> >
{{ amount / 100 }} {{ amount / 100 }}
@ -104,10 +100,7 @@
</n-space> </n-space>
</div> </div>
<div <div
v-if=" v-if="selectedRechargeAmount > 0 && rechargeQrcode.length === 0"
selectedRechargeAmount > 0 &&
rechargeQrcode.length === 0
"
style="margin-top: 10px" style="margin-top: 10px"
> >
<n-button <n-button
@ -124,7 +117,7 @@
</n-button> </n-button>
</div> </div>
<div class="qrcode-wrap" v-show="rechargeQrcode.length > 0"> <div v-show="rechargeQrcode.length > 0" class="qrcode-wrap">
<canvas id="qrcode-container"></canvas> <canvas id="qrcode-container"></canvas>
<div class="pay-tips"> <div class="pay-tips">
使{{ 使{{
@ -133,9 +126,7 @@
</div> </div>
<div class="pay-sub-tips"> <div class="pay-sub-tips">
<n-badge :value="100" type="info" dot processing /> <n-badge :value="100" type="info" dot processing />
<span style="margin-left: 6px"> <span style="margin-left: 6px"> ... </span>
...
</span>
</div> </div>
</div> </div>
</n-card> </n-card>
@ -222,14 +213,10 @@ const handleRecharge = (amount: any) => {
rechargeQrcode.value = res.pay; rechargeQrcode.value = res.pay;
// 生成二维码 // 生成二维码
QRCode.toCanvas( QRCode.toCanvas(document.querySelector('#qrcode-container'), res.pay, {
document.querySelector('#qrcode-container'),
res.pay,
{
width: 150, width: 150,
margin: 2, margin: 2,
} });
);
const s = setInterval(() => { const s = setInterval(() => {
getRecharge({ getRecharge({

Loading…
Cancel
Save