web source add biome to format/chec code

pull/628/head
alimy 1 year ago
parent cd686e4080
commit 8183c8ebdd

1
web/.gitignore vendored

@ -23,6 +23,7 @@ dist-ssr
*.sln *.sln
*.sw? *.sw?
bun.lock
yarn.lock yarn.lock
package-lock.json package-lock.json
components.d.ts components.d.ts

@ -0,0 +1,30 @@
{
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"organizeImports": {
"enabled": true
},
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"formatter": {
"indentStyle": "space"
},
"javascript": {
"formatter": {
"quoteStyle": "single"
}
},
"css": {
"parser": {
"cssModules": true
}
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
}
}

@ -6,6 +6,8 @@
"dev": "vite", "dev": "vite",
"build": "vite build", "build": "vite build",
"preview": "vite preview", "preview": "vite preview",
"check": "biome check --write",
"format": "biome format --write",
"tauri": "tauri" "tauri": "tauri"
}, },
"dependencies": { "dependencies": {
@ -32,6 +34,7 @@
"vuex": "^4.1.0" "vuex": "^4.1.0"
}, },
"devDependencies": { "devDependencies": {
"@biomejs/biome": "^1.9.4",
"@tauri-apps/cli": "^1.5.10", "@tauri-apps/cli": "^1.5.10",
"@types/node": "^22.14.1", "@types/node": "^22.14.1",
"@types/qrcode": "^1.5.5", "@types/qrcode": "^1.5.5",

@ -1,10 +1,9 @@
self.addEventListener("install", (event) => { self.addEventListener('install', (event) => {
event.waitUntil((async () => {})()); event.waitUntil((async () => {})());
}); });
self.addEventListener("activate", (event) => { self.addEventListener('activate', (event) => {
event.waitUntil((async () => {})()); event.waitUntil((async () => {})());
}); });
self.addEventListener("fetch", (event) => {}); self.addEventListener('fetch', (event) => {});

@ -53,10 +53,12 @@ const theme = computed(() => (store.state.theme === 'dark' ? darkTheme : null));
function loadSiteProfile() { function loadSiteProfile() {
store.commit('loadDefaultSiteProfile'); store.commit('loadDefaultSiteProfile');
if (import.meta.env.VITE_USE_WEB_PROFILE.toLowerCase() === "true") { if (import.meta.env.VITE_USE_WEB_PROFILE.toLowerCase() === 'true') {
getSiteProfile().then((res) => { getSiteProfile()
.then((res) => {
store.commit('updateSiteProfile', res); store.commit('updateSiteProfile', res);
}).catch((err) => { })
.catch((err) => {
console.log(err); console.log(err);
}); });
} }

@ -1,7 +1,9 @@
import { request } from '@/utils/request'; import { request } from '@/utils/request';
/** 用户登录 */ /** 用户登录 */
export const userLogin = (params: NetParams.AuthUserLogin): Promise<NetReq.AuthUserLogin> => { export const userLogin = (
params: NetParams.AuthUserLogin,
): Promise<NetReq.AuthUserLogin> => {
return request({ return request({
method: 'post', method: 'post',
url: '/v1/auth/login', url: '/v1/auth/login',
@ -10,7 +12,9 @@ export const userLogin = (params: NetParams.AuthUserLogin): Promise<NetReq.AuthU
}; };
/** 注册用户 */ /** 注册用户 */
export const userRegister = (params: NetParams.AuthUserRegister): Promise<NetReq.AuthUserRegister> => { export const userRegister = (
params: NetParams.AuthUserRegister,
): Promise<NetReq.AuthUserRegister> => {
return request({ return request({
method: 'post', method: 'post',
url: '/v1/auth/register', url: '/v1/auth/register',
@ -19,7 +23,9 @@ export const userRegister = (params: NetParams.AuthUserRegister): Promise<NetReq
}; };
/** 用户信息 */ /** 用户信息 */
export const userInfo = (token: NetParams.AuthUserInfo = ""): Promise<NetReq.AuthUserInfo> => { export const userInfo = (
token: NetParams.AuthUserInfo = '',
): Promise<NetReq.AuthUserInfo> => {
return request({ return request({
method: 'get', method: 'get',
url: '/v1/user/info', url: '/v1/user/info',
@ -30,7 +36,9 @@ export const userInfo = (token: NetParams.AuthUserInfo = ""): Promise<NetReq.Aut
}; };
/** 修改用户密码,该接口暂时未使用 */ /** 修改用户密码,该接口暂时未使用 */
export const updateUserPassword = (data: NetParams.AuthUpdateUserPassword): Promise<NetReq.AuthUpdateUserPassword> => { export const updateUserPassword = (
data: NetParams.AuthUpdateUserPassword,
): Promise<NetReq.AuthUpdateUserPassword> => {
return request({ return request({
method: 'post', method: 'post',
url: '/v1/api/user/password', url: '/v1/api/user/password',

@ -1,320 +1,320 @@
import { request } from "@/utils/request"; import { request } from '@/utils/request';
/** 获取动态列表 */ /** 获取动态列表 */
export const getPosts = ( export const getPosts = (
params: NetParams.PostGetPosts params: NetParams.PostGetPosts,
): Promise<NetReq.PostGetPosts> => { ): Promise<NetReq.PostGetPosts> => {
return request({ return request({
method: "get", method: 'get',
url: "/v1/posts", url: '/v1/posts',
params, params,
}); });
}; };
/** 获取标签列表 */ /** 获取标签列表 */
export const getTags = ( export const getTags = (
params: NetParams.PostGetTags params: NetParams.PostGetTags,
): Promise<NetReq.PostGetTags> => { ): Promise<NetReq.PostGetTags> => {
return request({ return request({
method: "get", method: 'get',
url: "/v1/tags", url: '/v1/tags',
params, params,
}); });
}; };
/** 获取动态详情 */ /** 获取动态详情 */
export const getPost = ( export const getPost = (
params: NetParams.PostGetPost params: NetParams.PostGetPost,
): Promise<NetReq.PostGetPost> => { ): Promise<NetReq.PostGetPost> => {
return request({ return request({
method: "get", method: 'get',
url: "/v1/post", url: '/v1/post',
params, params,
}); });
}; };
/** 获取动态点赞状态 */ /** 获取动态点赞状态 */
export const getPostStar = ( export const getPostStar = (
params: NetParams.PostPostStar params: NetParams.PostPostStar,
): Promise<NetReq.PostGetPostStar> => { ): Promise<NetReq.PostGetPostStar> => {
return request({ return request({
method: "get", method: 'get',
url: "/v1/post/star", url: '/v1/post/star',
params, params,
}); });
}; };
/** 动态点赞 */ /** 动态点赞 */
export const postStar = ( export const postStar = (
data: NetParams.PostPostStar data: NetParams.PostPostStar,
): Promise<NetReq.PostPostStar> => { ): Promise<NetReq.PostPostStar> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/post/star", url: '/v1/post/star',
data, data,
}); });
}; };
/** 获取动态收藏状态 */ /** 获取动态收藏状态 */
export const getPostCollection = ( export const getPostCollection = (
params: NetParams.PostGetPostCollection params: NetParams.PostGetPostCollection,
): Promise<NetReq.PostGetPostCollection> => { ): Promise<NetReq.PostGetPostCollection> => {
return request({ return request({
method: "get", method: 'get',
url: "/v1/post/collection", url: '/v1/post/collection',
params, params,
}); });
}; };
/** 动态收藏 */ /** 动态收藏 */
export const postCollection = ( export const postCollection = (
data: NetParams.PostPostCollection data: NetParams.PostPostCollection,
): Promise<NetReq.PostPostCollection> => { ): Promise<NetReq.PostPostCollection> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/post/collection", url: '/v1/post/collection',
data, data,
}); });
}; };
/** 获取动态评论列表 */ /** 获取动态评论列表 */
export const getPostComments = ( export const getPostComments = (
params: NetParams.PostGetPostComments params: NetParams.PostGetPostComments,
): Promise<NetReq.PostGetPostComments> => { ): Promise<NetReq.PostGetPostComments> => {
return request({ return request({
method: "get", method: 'get',
url: "/v1/post/comments", url: '/v1/post/comments',
params, params,
}); });
}; };
/** 获取联系人列表 */ /** 获取联系人列表 */
export const getContacts = ( export const getContacts = (
params: NetParams.GetContacts params: NetParams.GetContacts,
): Promise<NetReq.GetContacts> => { ): Promise<NetReq.GetContacts> => {
return request({ return request({
method: "get", method: 'get',
url: "/v1/user/contacts", url: '/v1/user/contacts',
params, params,
}); });
}; };
/** 获取联系人列表 */ /** 获取联系人列表 */
export const getIndexTrends = ( export const getIndexTrends = (
params: NetParams.IndexTrendsReq params: NetParams.IndexTrendsReq,
): Promise<NetReq.IndexTrendsResp> => { ): Promise<NetReq.IndexTrendsResp> => {
return request({ return request({
method: "get", method: 'get',
url: "/v1/trends/index", url: '/v1/trends/index',
params, params,
}); });
}; };
/** 发布动态 */ /** 发布动态 */
export const createPost = ( export const createPost = (
data: NetParams.PostCreatePost data: NetParams.PostCreatePost,
): Promise<NetReq.PostCreatePost> => { ): Promise<NetReq.PostCreatePost> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/post", url: '/v1/post',
data, data,
}); });
}; };
/** 删除动态 */ /** 删除动态 */
export const deletePost = ( export const deletePost = (
data: NetParams.PostDeletePost data: NetParams.PostDeletePost,
): Promise<NetReq.PostDeletePost> => { ): Promise<NetReq.PostDeletePost> => {
return request({ return request({
method: "delete", method: 'delete',
url: "/v1/post", url: '/v1/post',
data, data,
}); });
}; };
/** 锁定/解锁动态 */ /** 锁定/解锁动态 */
export const lockPost = ( export const lockPost = (
data: NetParams.PostLockPost data: NetParams.PostLockPost,
): Promise<NetReq.PostLockPost> => { ): Promise<NetReq.PostLockPost> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/post/lock", url: '/v1/post/lock',
data, data,
}); });
}; };
/** 置顶/取消置顶动态 */ /** 置顶/取消置顶动态 */
export const stickPost = ( export const stickPost = (
data: NetParams.PostStickPost data: NetParams.PostStickPost,
): Promise<NetReq.PostStickPost> => { ): Promise<NetReq.PostStickPost> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/post/stick", url: '/v1/post/stick',
data, data,
}); });
}; };
/** 设为亮点/取消亮点动态 */ /** 设为亮点/取消亮点动态 */
export const highlightPost = ( export const highlightPost = (
data: NetParams.PostHighlightPost data: NetParams.PostHighlightPost,
): Promise<NetReq.PostHighlightPost> => { ): Promise<NetReq.PostHighlightPost> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/post/highlight", url: '/v1/post/highlight',
data, data,
}); });
}; };
/** 置顶/取消置顶动态 */ /** 置顶/取消置顶动态 */
export const visibilityPost = ( export const visibilityPost = (
data: NetParams.PostVisibilityPost data: NetParams.PostVisibilityPost,
): Promise<NetReq.PostVisibilityPost> => { ): Promise<NetReq.PostVisibilityPost> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/post/visibility", url: '/v1/post/visibility',
data, data,
}); });
}; };
/** 点赞评论 */ /** 点赞评论 */
export const thumbsUpTweetComment = ( export const thumbsUpTweetComment = (
data: NetParams.PostTweetCommentThumbs data: NetParams.PostTweetCommentThumbs,
): Promise<NetReq.PostTweetCommentThumbs> => { ): Promise<NetReq.PostTweetCommentThumbs> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/tweet/comment/thumbsup", url: '/v1/tweet/comment/thumbsup',
data, data,
}); });
}; };
/** 点踩评论 */ /** 点踩评论 */
export const thumbsDownTweetComment = ( export const thumbsDownTweetComment = (
data: NetParams.PostTweetCommentThumbs data: NetParams.PostTweetCommentThumbs,
): Promise<NetReq.PostTweetCommentThumbs> => { ): Promise<NetReq.PostTweetCommentThumbs> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/tweet/comment/thumbsdown", url: '/v1/tweet/comment/thumbsdown',
data, data,
}); });
}; };
/** 点赞评论回复 */ /** 点赞评论回复 */
export const thumbsUpTweetReply = ( export const thumbsUpTweetReply = (
data: NetParams.PostTweetReplyThumbs data: NetParams.PostTweetReplyThumbs,
): Promise<NetReq.PostTweetReplyThumbs> => { ): Promise<NetReq.PostTweetReplyThumbs> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/tweet/reply/thumbsup", url: '/v1/tweet/reply/thumbsup',
data, data,
}); });
}; };
/** 点踩评论回复 */ /** 点踩评论回复 */
export const thumbsDownTweetReply = ( export const thumbsDownTweetReply = (
data: NetParams.PostTweetReplyThumbs data: NetParams.PostTweetReplyThumbs,
): Promise<NetReq.PostTweetReplyThumbs> => { ): Promise<NetReq.PostTweetReplyThumbs> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/tweet/reply/thumbsdown", url: '/v1/tweet/reply/thumbsdown',
data, data,
}); });
}; };
/** 发布动态评论 */ /** 发布动态评论 */
export const createComment = ( export const createComment = (
data: NetParams.PostCreateComment data: NetParams.PostCreateComment,
): Promise<NetReq.PostCreateComment> => { ): Promise<NetReq.PostCreateComment> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/post/comment", url: '/v1/post/comment',
data, data,
}); });
}; };
/** 删除评论 */ /** 删除评论 */
export const deleteComment = ( export const deleteComment = (
data: NetParams.PostDeleteComment data: NetParams.PostDeleteComment,
): Promise<NetReq.PostDeleteComment> => { ): Promise<NetReq.PostDeleteComment> => {
return request({ return request({
method: "delete", method: 'delete',
url: "/v1/post/comment", url: '/v1/post/comment',
data, data,
}); });
}; };
/** 精选评论 */ /** 精选评论 */
export const highlightComment = ( export const highlightComment = (
data: NetParams.PostHighlightComment data: NetParams.PostHighlightComment,
): Promise<NetReq.PostHighlightComment> => { ): Promise<NetReq.PostHighlightComment> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/post/comment/highlight", url: '/v1/post/comment/highlight',
data, data,
}); });
}; };
/** 发布评论回复 */ /** 发布评论回复 */
export const createCommentReply = ( export const createCommentReply = (
data: NetParams.PostCreateCommentReply data: NetParams.PostCreateCommentReply,
): Promise<NetReq.PostCreateCommentReply> => { ): Promise<NetReq.PostCreateCommentReply> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/post/comment/reply", url: '/v1/post/comment/reply',
data, data,
}); });
}; };
/** 删除评论回复 */ /** 删除评论回复 */
export const deleteCommentReply = ( export const deleteCommentReply = (
data: NetParams.PostDeleteCommentReply data: NetParams.PostDeleteCommentReply,
): Promise<NetReq.PostDeleteCommentReply> => { ): Promise<NetReq.PostDeleteCommentReply> => {
return request({ return request({
method: "delete", method: 'delete',
url: "/v1/post/comment/reply", url: '/v1/post/comment/reply',
data, data,
}); });
}; };
/** 置顶/取消置顶话题 */ /** 置顶/取消置顶话题 */
export const stickTopic = ( export const stickTopic = (
data: NetParams.PostStickTopic data: NetParams.PostStickTopic,
): Promise<NetReq.PostStickTopic> => { ): Promise<NetReq.PostStickTopic> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/topic/stick", url: '/v1/topic/stick',
data, data,
}); });
}; };
/** 置顶/取消置顶话题 */ /** 置顶/取消置顶话题 */
export const pinTopic = ( export const pinTopic = (
data: NetParams.PostPinTopic data: NetParams.PostPinTopic,
): Promise<NetReq.PostPinTopic> => { ): Promise<NetReq.PostPinTopic> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/topic/pin", url: '/v1/topic/pin',
data, data,
}); });
}; };
/** 关注话题 */ /** 关注话题 */
export const followTopic = ( export const followTopic = (
data: NetParams.PostFollowTopic data: NetParams.PostFollowTopic,
): Promise<NetReq.PostFollowTopic> => { ): Promise<NetReq.PostFollowTopic> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/topic/follow", url: '/v1/topic/follow',
data, data,
}); });
}; };
/** 取消关注话题 */ /** 取消关注话题 */
export const unfollowTopic = ( export const unfollowTopic = (
data: NetParams.PostUnfollowTopic data: NetParams.PostUnfollowTopic,
): Promise<NetReq.PostUnfollowTopic> => { ): Promise<NetReq.PostUnfollowTopic> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/topic/unfollow", url: '/v1/topic/unfollow',
data, data,
}); });
}; };

@ -1,9 +1,9 @@
import { request } from "@/utils/request"; import { request } from '@/utils/request';
/** 获取站点概要信息 */ /** 获取站点概要信息 */
export const getSiteProfile = (): Promise<NetReq.SiteProfile> => { export const getSiteProfile = (): Promise<NetReq.SiteProfile> => {
return request({ return request({
method: "get", method: 'get',
url: "/v1/site/profile", url: '/v1/site/profile',
}); });
}; };

@ -1,12 +1,12 @@
import { request } from "@/utils/request"; import { request } from '@/utils/request';
/** 获取验证码 */ /** 获取验证码 */
export const getCaptcha = ( export const getCaptcha = (
params: NetParams.UserGetCaptcha = {} params: NetParams.UserGetCaptcha = {},
): Promise<NetReq.UserGetCaptcha> => { ): Promise<NetReq.UserGetCaptcha> => {
return request({ return request({
method: "get", method: 'get',
url: "/v1/captcha", url: '/v1/captcha',
params, params,
}); });
}; };
@ -18,8 +18,8 @@ export const getCaptcha = (
*/ */
export const sendCaptcha = (data: any) => { export const sendCaptcha = (data: any) => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/captcha", url: '/v1/captcha',
data, data,
}); });
}; };
@ -30,11 +30,11 @@ export const sendCaptcha = (data: any) => {
* @returns Promise * @returns Promise
*/ */
export const sendUserWhisper = ( export const sendUserWhisper = (
data: NetParams.UserWhisper data: NetParams.UserWhisper,
): Promise<NetParams.UserWhisper> => { ): Promise<NetParams.UserWhisper> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/user/whisper", url: '/v1/user/whisper',
data, data,
}); });
}; };
@ -45,11 +45,11 @@ export const sendUserWhisper = (
* @returns Promise * @returns Promise
*/ */
export const requestingFriend = ( export const requestingFriend = (
data: NetParams.RequestingFriend data: NetParams.RequestingFriend,
): Promise<NetReq.RequestingFriend> => { ): Promise<NetReq.RequestingFriend> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/friend/requesting", url: '/v1/friend/requesting',
data, data,
}); });
}; };
@ -60,33 +60,33 @@ export const requestingFriend = (
* @returns Promise * @returns Promise
*/ */
export const addFriend = ( export const addFriend = (
data: NetParams.AddFriend data: NetParams.AddFriend,
): Promise<NetReq.AddFriend> => { ): Promise<NetReq.AddFriend> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/friend/add", url: '/v1/friend/add',
data, data,
}); });
}; };
// 关注 用户 // 关注 用户
export const followUser = ( export const followUser = (
data: NetParams.FollowUserReq data: NetParams.FollowUserReq,
): Promise<NetReq.FollowUserResp> => { ): Promise<NetReq.FollowUserResp> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/user/follow", url: '/v1/user/follow',
data, data,
}); });
}; };
// 取消关注 用户 // 取消关注 用户
export const unfollowUser = ( export const unfollowUser = (
data: NetParams.UnfollowUserReq data: NetParams.UnfollowUserReq,
): Promise<NetReq.UnfollowUserResp> => { ): Promise<NetReq.UnfollowUserResp> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/user/unfollow", url: '/v1/user/unfollow',
data, data,
}); });
}; };
@ -97,11 +97,11 @@ export const unfollowUser = (
* @returns Promise * @returns Promise
*/ */
export const getUserFollows = ( export const getUserFollows = (
params: NetParams.GetUserFollows params: NetParams.GetUserFollows,
): Promise<NetReq.GetContacts> => { ): Promise<NetReq.GetContacts> => {
return request({ return request({
method: "get", method: 'get',
url: "/v1/user/follows", url: '/v1/user/follows',
params, params,
}); });
}; };
@ -112,11 +112,11 @@ export const getUserFollows = (
* @returns Promise * @returns Promise
*/ */
export const getUserFollowings = ( export const getUserFollowings = (
params: NetParams.GetUserFollowings params: NetParams.GetUserFollowings,
): Promise<NetReq.GetContacts> => { ): Promise<NetReq.GetContacts> => {
return request({ return request({
method: "get", method: 'get',
url: "/v1/user/followings", url: '/v1/user/followings',
params, params,
}); });
}; };
@ -127,11 +127,11 @@ export const getUserFollowings = (
* @returns Promise * @returns Promise
*/ */
export const rejectFriend = ( export const rejectFriend = (
data: NetParams.RejectFriend data: NetParams.RejectFriend,
): Promise<NetReq.RejectFriend> => { ): Promise<NetReq.RejectFriend> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/friend/reject", url: '/v1/friend/reject',
data, data,
}); });
}; };
@ -142,11 +142,11 @@ export const rejectFriend = (
* @returns Promise * @returns Promise
*/ */
export const deleteFriend = ( export const deleteFriend = (
data: NetParams.DeleteFriend data: NetParams.DeleteFriend,
): Promise<NetReq.DeleteFriend> => { ): Promise<NetReq.DeleteFriend> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/friend/delete", url: '/v1/friend/delete',
data, data,
}); });
}; };
@ -157,11 +157,11 @@ export const deleteFriend = (
* @returns Promise * @returns Promise
*/ */
export const getContacts = ( export const getContacts = (
data: NetParams.GetContacts data: NetParams.GetContacts,
): Promise<NetReq.GetContacts> => { ): Promise<NetReq.GetContacts> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/user/contacts", url: '/v1/user/contacts',
data, data,
}); });
}; };
@ -172,11 +172,11 @@ export const getContacts = (
* @returns Promise * @returns Promise
*/ */
export const bindUserPhone = ( export const bindUserPhone = (
data: NetParams.UserBindUserPhone data: NetParams.UserBindUserPhone,
): Promise<NetParams.UserBindUserPhone> => { ): Promise<NetParams.UserBindUserPhone> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/user/phone", url: '/v1/user/phone',
data, data,
}); });
}; };
@ -187,33 +187,33 @@ export const bindUserPhone = (
* @returns Promise * @returns Promise
*/ */
export const activateUser = ( export const activateUser = (
data: NetParams.UserActivation data: NetParams.UserActivation,
): Promise<NetParams.UserActivation> => { ): Promise<NetParams.UserActivation> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/user/activate", url: '/v1/user/activate',
data, data,
}); });
}; };
/** 更改密码 */ /** 更改密码 */
export const changePassword = ( export const changePassword = (
data: NetParams.UserChangePassword data: NetParams.UserChangePassword,
): Promise<NetReq.UserChangePassword> => { ): Promise<NetReq.UserChangePassword> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/user/password", url: '/v1/user/password',
data, data,
}); });
}; };
/** 更改昵称 */ /** 更改昵称 */
export const changeNickname = ( export const changeNickname = (
data: NetParams.UserChangeNickname data: NetParams.UserChangeNickname,
): Promise<NetReq.UserChangeNickname> => { ): Promise<NetReq.UserChangeNickname> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/user/nickname", url: '/v1/user/nickname',
data, data,
}); });
}; };
@ -225,30 +225,30 @@ export const changeNickname = (
*/ */
export const changeAvatar = (data: any) => { export const changeAvatar = (data: any) => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/user/avatar", url: '/v1/user/avatar',
data, data,
}); });
}; };
/** 获取未读消息数 */ /** 获取未读消息数 */
export const getUnreadMsgCount = ( export const getUnreadMsgCount = (
params: NetParams.UserGetUnreadMsgCount = {} params: NetParams.UserGetUnreadMsgCount = {},
): Promise<NetReq.UserGetUnreadMsgCount> => { ): Promise<NetReq.UserGetUnreadMsgCount> => {
return request({ return request({
method: "get", method: 'get',
url: "/v1/user/msgcount/unread", url: '/v1/user/msgcount/unread',
params, params,
}); });
}; };
/** 获取消息列表 */ /** 获取消息列表 */
export const getMessages = ( export const getMessages = (
params: NetParams.UserGetMessages params: NetParams.UserGetMessages,
): Promise<NetReq.UserGetMessages> => { ): Promise<NetReq.UserGetMessages> => {
return request({ return request({
method: "get", method: 'get',
url: "/v1/user/messages", url: '/v1/user/messages',
params, params,
}); });
}; };
@ -259,11 +259,11 @@ export const getMessages = (
* @returns Promise * @returns Promise
*/ */
export const readMessage = ( export const readMessage = (
data: NetParams.ReadMessageReq data: NetParams.ReadMessageReq,
): Promise<NetReq.ReadMessageResp> => { ): Promise<NetReq.ReadMessageResp> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/user/message/read", url: '/v1/user/message/read',
data, data,
}); });
}; };
@ -274,51 +274,51 @@ export const readMessage = (
*/ */
export const readAllMessage = (): Promise<NetReq.ReadAllMessageResp> => { export const readAllMessage = (): Promise<NetReq.ReadAllMessageResp> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/user/message/readall", url: '/v1/user/message/readall',
}); });
}; };
/** 获取收藏列表 */ /** 获取收藏列表 */
export const getCollections = ( export const getCollections = (
params: NetParams.UserGetCollections params: NetParams.UserGetCollections,
): Promise<NetReq.UserGetCollections> => { ): Promise<NetReq.UserGetCollections> => {
return request({ return request({
method: "get", method: 'get',
url: "/v1/user/collections", url: '/v1/user/collections',
params, params,
}); });
}; };
/** 获取用户基础信息 */ /** 获取用户基础信息 */
export const getUserProfile = ( export const getUserProfile = (
params: NetParams.UserGetUserProfile params: NetParams.UserGetUserProfile,
): Promise<NetReq.UserGetUserProfile> => { ): Promise<NetReq.UserGetUserProfile> => {
return request({ return request({
method: "get", method: 'get',
url: "/v1/user/profile", url: '/v1/user/profile',
params, params,
}); });
}; };
/** 获取用户帖子列表 */ /** 获取用户帖子列表 */
export const getUserPosts = ( export const getUserPosts = (
params: NetParams.UserGetUserPosts params: NetParams.UserGetUserPosts,
): Promise<NetReq.UserGetUserPosts> => { ): Promise<NetReq.UserGetUserPosts> => {
return request({ return request({
method: "get", method: 'get',
url: "/v1/user/posts", url: '/v1/user/posts',
params, params,
}); });
}; };
/** 获取账单列表 */ /** 获取账单列表 */
export const getBills = ( export const getBills = (
params: NetParams.UserGetBills params: NetParams.UserGetBills,
): Promise<NetReq.UserGetBills> => { ): Promise<NetReq.UserGetBills> => {
return request({ return request({
method: "get", method: 'get',
url: "/v1/user/wallet/bills", url: '/v1/user/wallet/bills',
params, params,
}); });
}; };
@ -329,11 +329,11 @@ export const getBills = (
* @returns Promise * @returns Promise
*/ */
export const reqRecharge = ( export const reqRecharge = (
data: NetParams.UserReqRecharge data: NetParams.UserReqRecharge,
): Promise<NetReq.UserReqRecharge> => { ): Promise<NetReq.UserReqRecharge> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/user/recharge", url: '/v1/user/recharge',
data, data,
}); });
}; };
@ -344,11 +344,11 @@ export const reqRecharge = (
* @returns Promise * @returns Promise
*/ */
export const getRecharge = ( export const getRecharge = (
params: NetParams.UserGetRecharge params: NetParams.UserGetRecharge,
): Promise<NetReq.UserGetRecharge> => { ): Promise<NetReq.UserGetRecharge> => {
return request({ return request({
method: "get", method: 'get',
url: "/v1/user/recharge", url: '/v1/user/recharge',
params, params,
}); });
}; };
@ -362,8 +362,8 @@ export const getSuggestUsers = (params: {
k: string; k: string;
}): Promise<NetReq.UserGetSuggestUsers> => { }): Promise<NetReq.UserGetSuggestUsers> => {
return request({ return request({
method: "get", method: 'get',
url: "/v1/suggest/users", url: '/v1/suggest/users',
params, params,
}); });
}; };
@ -377,8 +377,8 @@ export const getSuggestTags = (params: {
k: string; k: string;
}): Promise<NetReq.UserGetSuggestTags> => { }): Promise<NetReq.UserGetSuggestTags> => {
return request({ return request({
method: "get", method: 'get',
url: "/v1/suggest/tags", url: '/v1/suggest/tags',
params, params,
}); });
}; };
@ -389,11 +389,11 @@ export const getSuggestTags = (params: {
* @returns Promise * @returns Promise
*/ */
export const precheckAttachment = ( export const precheckAttachment = (
params: NetParams.UserPrecheckAttachment params: NetParams.UserPrecheckAttachment,
): Promise<NetReq.UserPrecheckAttachment> => { ): Promise<NetReq.UserPrecheckAttachment> => {
return request({ return request({
method: "get", method: 'get',
url: "/v1/attachment/precheck", url: '/v1/attachment/precheck',
params, params,
}); });
}; };
@ -404,11 +404,11 @@ export const precheckAttachment = (
* @returns Promise * @returns Promise
*/ */
export const getAttachment = ( export const getAttachment = (
params: NetParams.UserGetAttachment params: NetParams.UserGetAttachment,
): Promise<NetReq.UserGetAttachment> => { ): Promise<NetReq.UserGetAttachment> => {
return request({ return request({
method: "get", method: 'get',
url: "/v1/attachment", url: '/v1/attachment',
params, params,
}); });
}; };
@ -419,11 +419,11 @@ export const getAttachment = (
* @returns Promise * @returns Promise
*/ */
export const changeUserStatus = ( export const changeUserStatus = (
data: NetParams.UserStatusReq data: NetParams.UserStatusReq,
): Promise<NetReq.UserChangeStatus> => { ): Promise<NetReq.UserChangeStatus> => {
return request({ return request({
method: "post", method: 'post',
url: "/v1/admin/user/status", url: '/v1/admin/user/status',
data, data,
}); });
}; };
@ -434,7 +434,7 @@ export const changeUserStatus = (
*/ */
export const getSiteInfo = (): Promise<NetReq.SiteInfoResp> => { export const getSiteInfo = (): Promise<NetReq.SiteInfoResp> => {
return request({ return request({
method: "get", method: 'get',
url: "/v1/admin/site/status", url: '/v1/admin/site/status',
}); });
}; };

@ -225,7 +225,7 @@ const handleLogin = (e: Event) => {
store.commit('updateUserinfo', res); store.commit('updateUserinfo', res);
store.commit('triggerAuth', false); store.commit('triggerAuth', false);
store.commit('refresh') store.commit('refresh');
loginForm.username = ''; loginForm.username = '';
loginForm.password = ''; loginForm.password = '';
}) })

@ -142,12 +142,15 @@ 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<{
postUserId: number comment: Item.CommentProps;
}>(), {}) postUserId: number;
}>(),
{},
);
const comment = computed(() => { const comment = computed(() => {
let comment: Item.CommentComponentProps = Object.assign( let comment: Item.CommentComponentProps = Object.assign(
@ -155,7 +158,7 @@ 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) {
@ -220,7 +223,7 @@ const execHightlightAction = () => {
}) })
.then((res) => { .then((res) => {
comment.value.is_essence = res.highlight_status; comment.value.is_essence = res.highlight_status;
window.$message.success("操作成功"); window.$message.success('操作成功');
setTimeout(() => { setTimeout(() => {
reload(); reload();
}, 50); }, 50);

@ -170,9 +170,7 @@
import { onMounted, computed, ref } from 'vue'; import { onMounted, computed, ref } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { debounce } from 'lodash'; import { debounce } from 'lodash';
import { import { ImageOutline } from '@vicons/ionicons5';
ImageOutline,
} from '@vicons/ionicons5';
import { createComment } from '@/api/post'; import { createComment } from '@/api/post';
import { getSuggestUsers } from '@/api/user'; import { getSuggestUsers } from '@/api/user';
import { parsePostTag } from '@/utils/content'; import { parsePostTag } from '@/utils/content';
@ -189,7 +187,7 @@ const props = withDefaults(
{ {
lock: 0, lock: 0,
postId: 0, postId: 0,
} },
); );
const store = useStore(); const store = useStore();
@ -203,8 +201,12 @@ const uploadRef = ref<UploadInst>();
const uploadType = ref('public/image'); const uploadType = ref('public/image');
const fileQueue = ref<UploadFileInfo[]>([]); const fileQueue = ref<UploadFileInfo[]>([]);
const imageContents = ref<Item.CommentItemProps[]>([]); const imageContents = ref<Item.CommentItemProps[]>([]);
const allowUserRegister = ref(import.meta.env.VITE_ALLOW_USER_REGISTER.toLowerCase() === 'true') const allowUserRegister = ref(
const defaultCommentMaxLength = Number(import.meta.env.VITE_DEFAULT_COMMENT_MAX_LENGTH) import.meta.env.VITE_ALLOW_USER_REGISTER.toLowerCase() === 'true',
);
const defaultCommentMaxLength = Number(
import.meta.env.VITE_DEFAULT_COMMENT_MAX_LENGTH,
);
const uploadGateway = import.meta.env.VITE_HOST + '/v1/attachment'; const uploadGateway = import.meta.env.VITE_HOST + '/v1/attachment';
const uploadToken = computed(() => { const uploadToken = computed(() => {
@ -255,7 +257,12 @@ const updateUpload = (list: UploadFileInfo[]) => {
var basename: string = name.split('.').slice(0, -1).join('.'); var basename: string = name.split('.').slice(0, -1).join('.');
var ext: string = name.split('.').pop()!; var ext: string = name.split('.').pop()!;
if (basename.length > 30) { if (basename.length > 30) {
list[i].name = basename.substring(0, 18) + "..." + basename.substring(basename.length-9) + "." + ext; list[i].name =
basename.substring(0, 18) +
'...' +
basename.substring(basename.length - 9) +
'.' +
ext;
} }
} }
fileQueue.value = list; fileQueue.value = list;
@ -265,7 +272,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 as any).file?.type (data.file as any).file?.type,
) )
) { ) {
window.$message.warning('图片仅允许 png/jpg/gif 格式'); window.$message.warning('图片仅允许 png/jpg/gif 格式');

@ -57,7 +57,11 @@
import { ref } from 'vue'; import { ref } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { formatPrettyTime } from '@/utils/formatTime'; import { formatPrettyTime } from '@/utils/formatTime';
import { createCommentReply, thumbsUpTweetComment, thumbsDownTweetComment } from '@/api/post'; import {
createCommentReply,
thumbsUpTweetComment,
thumbsDownTweetComment,
} from '@/api/post';
import { InputInst } from 'naive-ui'; import { InputInst } from 'naive-ui';
import { import {
ThumbUpTwotone, ThumbUpTwotone,
@ -67,28 +71,33 @@ import {
} from '@vicons/material'; } from '@vicons/material';
import { YesNoEnum } from '@/utils/IEnum'; import { YesNoEnum } from '@/utils/IEnum';
const props = withDefaults(defineProps<{ const props = withDefaults(
comment: Item.CommentProps, defineProps<{
atUserid: number, comment: Item.CommentProps;
atUsername: string, atUserid: number;
}>(), { atUsername: string;
}>(),
{
atUserid: 0, atUserid: 0,
atUsername: '' atUsername: '',
}); },
);
const store = useStore(); const store = useStore();
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);
const replyContent = ref(''); const replyContent = ref('');
const submitting = ref(false); const submitting = ref(false);
const defaultReplyMaxLength = Number(import.meta.env.VITE_DEFAULT_REPLY_MAX_LENGTH) const defaultReplyMaxLength = Number(
const hasThumbsUp = ref(props.comment.is_thumbs_up == YesNoEnum.YES) import.meta.env.VITE_DEFAULT_REPLY_MAX_LENGTH,
const hasThumbsDown = ref(props.comment.is_thumbs_down == YesNoEnum.YES) );
const thumbsUpCount = ref(props.comment.thumbs_up_count) const hasThumbsUp = ref(props.comment.is_thumbs_up == YesNoEnum.YES);
const hasThumbsDown = ref(props.comment.is_thumbs_down == YesNoEnum.YES);
const thumbsUpCount = ref(props.comment.thumbs_up_count);
const handleThumbsUp = () => { const handleThumbsUp = () => {
thumbsUpTweetComment({ thumbsUpTweetComment({
@ -96,12 +105,12 @@ const handleThumbsUp = () => {
comment_id: props.comment.id, comment_id: props.comment.id,
}) })
.then((_res) => { .then((_res) => {
hasThumbsUp.value = !hasThumbsUp.value hasThumbsUp.value = !hasThumbsUp.value;
if (hasThumbsUp.value) { if (hasThumbsUp.value) {
thumbsUpCount.value++ thumbsUpCount.value++;
hasThumbsDown.value = false hasThumbsDown.value = false;
} else { } else {
thumbsUpCount.value-- thumbsUpCount.value--;
} }
}) })
.catch((err) => { .catch((err) => {
@ -114,11 +123,11 @@ const handleThumbsDown = () => {
comment_id: props.comment.id, comment_id: props.comment.id,
}) })
.then((_res) => { .then((_res) => {
hasThumbsDown.value = !hasThumbsDown.value hasThumbsDown.value = !hasThumbsDown.value;
if (hasThumbsDown.value) { if (hasThumbsDown.value) {
if (hasThumbsUp.value) { if (hasThumbsUp.value) {
thumbsUpCount.value-- thumbsUpCount.value--;
hasThumbsUp.value = false hasThumbsUp.value = false;
} }
} }
}) })

@ -315,9 +315,11 @@ const imageContents = ref<Item.CommentItemProps[]>([]);
const videoContents = ref<Item.CommentItemProps[]>([]); const videoContents = ref<Item.CommentItemProps[]>([]);
const attachmentContents = ref<Item.AttachmentProps[]>([]); const attachmentContents = ref<Item.AttachmentProps[]>([]);
const visitType = ref<VisibilityEnum>(VisibilityEnum.PUBLIC); const visitType = ref<VisibilityEnum>(VisibilityEnum.PUBLIC);
const defaultVisitType = ref<VisibilityEnum>(VisibilityEnum.PUBLIC) const defaultVisitType = ref<VisibilityEnum>(VisibilityEnum.PUBLIC);
const allowTweetVisibility = ref(import.meta.env.VITE_ALLOW_TWEET_VISIBILITY.toLowerCase() === 'true') const allowTweetVisibility = ref(
import.meta.env.VITE_ALLOW_TWEET_VISIBILITY.toLowerCase() === 'true',
);
const uploadGateway = import.meta.env.VITE_HOST + '/v1/attachment'; const uploadGateway = import.meta.env.VITE_HOST + '/v1/attachment';
const uploadToken = computed(() => { const uploadToken = computed(() => {
@ -326,12 +328,12 @@ const uploadToken = computed(() => {
const visibilities = computed(() => { const visibilities = computed(() => {
let res = [ let res = [
{value: VisibilityEnum.PUBLIC, label: "公开"}, { value: VisibilityEnum.PUBLIC, label: '公开' },
{value: VisibilityEnum.PRIVATE, label: "私密"}, { value: VisibilityEnum.PRIVATE, label: '私密' },
{value: VisibilityEnum.Following, label: "关注可见"}, { value: VisibilityEnum.Following, label: '关注可见' },
]; ];
if (store.state.profile.useFriendship) { if (store.state.profile.useFriendship) {
res.push({value: VisibilityEnum.FRIEND, label: "好友可见"}); res.push({ value: VisibilityEnum.FRIEND, label: '好友可见' });
} }
return res; return res;
}); });
@ -339,14 +341,14 @@ const visibilities = computed(()=> {
const switchLink = () => { const switchLink = () => {
showLinkSet.value = !showLinkSet.value; showLinkSet.value = !showLinkSet.value;
if (showLinkSet.value && showEyeSet.value) { if (showLinkSet.value && showEyeSet.value) {
showEyeSet.value = false showEyeSet.value = false;
} }
}; };
const switchEye = () => { const switchEye = () => {
showEyeSet.value = !showEyeSet.value; showEyeSet.value = !showEyeSet.value;
if (showEyeSet.value && showLinkSet.value) { if (showEyeSet.value && showLinkSet.value) {
showLinkSet.value = false showLinkSet.value = false;
} }
}; };
@ -420,7 +422,12 @@ const updateUpload = (list: UploadFileInfo[]) => {
var basename: string = name.split('.').slice(0, -1).join('.'); var basename: string = name.split('.').slice(0, -1).join('.');
var ext: string = name.split('.').pop()!; var ext: string = name.split('.').pop()!;
if (basename.length > 30) { if (basename.length > 30) {
list[i].name = basename.substring(0, 18) + "..." + basename.substring(basename.length-9) + "." + ext; list[i].name =
basename.substring(0, 18) +
'...' +
basename.substring(basename.length - 9) +
'.' +
ext;
} }
} }
fileQueue.value = list; fileQueue.value = list;
@ -429,9 +436,13 @@ const beforeUpload = async (data: any) => {
// 图片类型校验 // 图片类型校验
if ( if (
uploadType.value === 'public/image' && uploadType.value === 'public/image' &&
!['image/webp', 'image/png', 'image/jpg', 'image/jpeg', 'image/gif'].includes( ![
data.file.file?.type 'image/webp',
) 'image/png',
'image/jpg',
'image/jpeg',
'image/gif',
].includes(data.file.file?.type)
) { ) {
window.$message.warning('图片仅允许 webp/png/jpg/gif 格式'); window.$message.warning('图片仅允许 webp/png/jpg/gif 格式');
return false; return false;
@ -451,17 +462,12 @@ 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;
} }
// 附件类型校验 // 附件类型校验
if ( if (uploadType.value === 'attachment' && !(await isZipFile(data.file.file))) {
uploadType.value === 'attachment' && !(await isZipFile(data.file.file))
) {
window.$message.warning('附件仅允许 zip 格式'); window.$message.warning('附件仅允许 zip 格式');
return false; return false;
} }
@ -593,7 +599,7 @@ const submitPost = () => {
tags: Array.from(new Set(tags)), tags: Array.from(new Set(tags)),
users: Array.from(new Set(users)), users: Array.from(new Set(users)),
attachment_price: +attachmentPrice.value * 100, attachment_price: +attachmentPrice.value * 100,
visibility: visitType.value visibility: visitType.value,
}) })
.then((res) => { .then((res) => {
window.$message.success('发布成功'); window.$message.success('发布成功');
@ -621,15 +627,15 @@ const triggerAuth = (key: string) => {
store.commit('triggerAuthKey', key); store.commit('triggerAuthKey', key);
}; };
onMounted(() => { onMounted(() => {
const defaultVisibility = store.state.profile.defaultTweetVisibility const defaultVisibility = store.state.profile.defaultTweetVisibility;
if (store.state.profile.useFriendship && defaultVisibility === 'friend') { if (store.state.profile.useFriendship && defaultVisibility === 'friend') {
defaultVisitType.value = VisibilityEnum.FRIEND defaultVisitType.value = VisibilityEnum.FRIEND;
} else if (defaultVisibility === 'following') { } else if (defaultVisibility === 'following') {
defaultVisitType.value = VisibilityEnum.Following defaultVisitType.value = VisibilityEnum.Following;
} else if (defaultVisibility === 'public') { } else if (defaultVisibility === 'public') {
defaultVisitType.value = VisibilityEnum.PUBLIC defaultVisitType.value = VisibilityEnum.PUBLIC;
} else { } else {
defaultVisitType.value = VisibilityEnum.PRIVATE defaultVisitType.value = VisibilityEnum.PRIVATE;
} }
visitType.value = defaultVisitType.value; visitType.value = defaultVisitType.value;
}); });

@ -57,14 +57,12 @@
<script setup lang="ts"> <script setup lang="ts">
import { h, computed } from 'vue'; import { h, computed } from 'vue';
import { NIcon } from 'naive-ui' import { NIcon } from 'naive-ui';
import type { Component } from 'vue' import type { Component } from 'vue';
import { DropdownOption } from 'naive-ui'; import { DropdownOption } from 'naive-ui';
import { formatDate } from '@/utils/formatTime'; import { formatDate } from '@/utils/formatTime';
import { MoreHorizFilled } from '@vicons/material'; import { MoreHorizFilled } from '@vicons/material';
import { import { PaperPlaneOutline } from '@vicons/ionicons5';
PaperPlaneOutline,
} from '@vicons/ionicons5';
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'send-whisper', user: Item.UserInfo): void; (e: 'send-whisper', user: Item.UserInfo): void;
@ -73,29 +71,30 @@ const emit = defineEmits<{
const renderIcon = (icon: Component) => { const renderIcon = (icon: Component) => {
return () => { return () => {
return h(NIcon, null, { return h(NIcon, null, {
default: () => h(icon) default: () => h(icon),
}) });
} };
}; };
const props = withDefaults(defineProps<{ const props = withDefaults(
contact: Item.ContactItemProps defineProps<{
}>(), {}) contact: Item.ContactItemProps;
}>(),
{},
);
const actionOpts = computed(() => { const actionOpts = computed(() => {
let options: DropdownOption[] = [ let options: DropdownOption[] = [
{ {
label: '私信 @' + props.contact.username, label: '私信 @' + props.contact.username,
key: 'whisper', key: 'whisper',
icon: renderIcon(PaperPlaneOutline) icon: renderIcon(PaperPlaneOutline),
}, },
]; ];
return options; return options;
}); });
const handleAction = ( const handleAction = (item: 'whisper') => {
item: 'whisper'
) => {
switch (item) { switch (item) {
case 'whisper': case 'whisper':
const user: Item.UserInfo = { const user: Item.UserInfo = {
@ -110,7 +109,7 @@ const handleAction = (
follows: 0, follows: 0,
followings: 0, followings: 0,
status: 1, status: 1,
} };
emit('send-whisper', user); emit('send-whisper', user);
break; break;
default: default:

@ -57,17 +57,13 @@
<script setup lang="ts"> <script setup lang="ts">
import { h, computed } from 'vue'; import { h, computed } from 'vue';
import { NIcon } from 'naive-ui' import { NIcon } from 'naive-ui';
import type { Component } from 'vue' import type { Component } from 'vue';
import { useDialog, DropdownOption } from 'naive-ui'; import { useDialog, DropdownOption } from 'naive-ui';
import { followUser, unfollowUser } from '@/api/user'; import { followUser, unfollowUser } from '@/api/user';
import { formatDate } from '@/utils/formatTime'; import { formatDate } from '@/utils/formatTime';
import { MoreHorizFilled } from '@vicons/material'; import { MoreHorizFilled } from '@vicons/material';
import { import { PaperPlaneOutline, BodyOutline, WalkOutline } from '@vicons/ionicons5';
PaperPlaneOutline,
BodyOutline,
WalkOutline
} from '@vicons/ionicons5';
const dialog = useDialog(); const dialog = useDialog();
@ -78,23 +74,27 @@ const emit = defineEmits<{
const renderIcon = (icon: Component) => { const renderIcon = (icon: Component) => {
return () => { return () => {
return h(NIcon, null, { return h(NIcon, null, {
default: () => h(icon) default: () => h(icon),
}) });
} };
}; };
const handleFollowUser = () => { const handleFollowUser = () => {
dialog.success({ dialog.success({
title: '提示', title: '提示',
content: content:
'确定' + (props.contact.is_following ? '取消关注 @' : '关注 @') + props.contact.username +' 吗?', '确定' +
(props.contact.is_following ? '取消关注 @' : '关注 @') +
props.contact.username +
' 吗?',
positiveText: '确定', positiveText: '确定',
negativeText: '取消', negativeText: '取消',
onPositiveClick: () => { onPositiveClick: () => {
if (props.contact.is_following) { if (props.contact.is_following) {
unfollowUser({ unfollowUser({
user_id: props.contact.user_id, user_id: props.contact.user_id,
}).then((_res) => { })
.then((_res) => {
window.$message.success('取消关注成功'); window.$message.success('取消关注成功');
props.contact.is_following = false; props.contact.is_following = false;
}) })
@ -104,7 +104,8 @@ const handleFollowUser = () => {
} else { } else {
followUser({ followUser({
user_id: props.contact.user_id, user_id: props.contact.user_id,
}).then((_res) => { })
.then((_res) => {
window.$message.success('关注成功'); window.$message.success('关注成功');
props.contact.is_following = true; props.contact.is_following = true;
}) })
@ -116,37 +117,38 @@ const handleFollowUser = () => {
}); });
}; };
const props = withDefaults(defineProps<{ const props = withDefaults(
contact: Item.ContactItemProps defineProps<{
}>(), {}) contact: Item.ContactItemProps;
}>(),
{},
);
const actionOpts = computed(() => { const actionOpts = computed(() => {
let options: DropdownOption[] = [ let options: DropdownOption[] = [
{ {
label: '私信 @' + props.contact.username, label: '私信 @' + props.contact.username,
key: 'whisper', key: 'whisper',
icon: renderIcon(PaperPlaneOutline) icon: renderIcon(PaperPlaneOutline),
}, },
]; ];
if (props.contact.is_following) { if (props.contact.is_following) {
options.push({ options.push({
label: '取消关注 @' + props.contact.username, label: '取消关注 @' + props.contact.username,
key: 'unfollow', key: 'unfollow',
icon: renderIcon(WalkOutline) icon: renderIcon(WalkOutline),
}) });
} else { } else {
options.push({ options.push({
label: '关注 @' + props.contact.username, label: '关注 @' + props.contact.username,
key: 'follow', key: 'follow',
icon: renderIcon(BodyOutline) icon: renderIcon(BodyOutline),
}) });
} }
return options; return options;
}); });
const handleAction = ( const handleAction = (item: 'follow' | 'unfollow' | 'whisper') => {
item: 'follow' | 'unfollow' | 'whisper'
) => {
switch (item) { switch (item) {
case 'follow': case 'follow':
case 'unfollow': case 'unfollow':
@ -165,7 +167,7 @@ const handleAction = (
follows: 0, follows: 0,
followings: 0, followings: 0,
status: 1, status: 1,
} };
emit('send-whisper', user); emit('send-whisper', user);
break; break;
default: default:

@ -65,12 +65,17 @@ import { onMounted, ref } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { useMessage, useOsTheme, DrawerPlacement } from 'naive-ui'; import { useMessage, useOsTheme, DrawerPlacement } from 'naive-ui';
import { LightModeOutlined, DarkModeOutlined, ChevronLeftRound, DehazeRound } from '@vicons/material'; import {
LightModeOutlined,
DarkModeOutlined,
ChevronLeftRound,
DehazeRound,
} from '@vicons/material';
const store = useStore(); const store = useStore();
const router = useRouter(); const router = useRouter();
const activeDrawerRef = ref(false) const activeDrawerRef = ref(false);
const placementRef = ref<DrawerPlacement>('left') const placementRef = ref<DrawerPlacement>('left');
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
@ -82,7 +87,7 @@ const props = withDefaults(
title: '', title: '',
back: false, back: false,
theme: true, theme: true,
} },
); );
const switchTheme = (theme: boolean) => { const switchTheme = (theme: boolean) => {
if (theme) { if (theme) {
@ -103,7 +108,7 @@ const goBack = () => {
} }
}; };
const activeDrawer = () => { const activeDrawer = () => {
activeDrawerRef.value = true activeDrawerRef.value = true;
}; };
onMounted(() => { onMounted(() => {

@ -138,13 +138,24 @@
<script setup lang="ts"> <script setup lang="ts">
import { h, computed } from 'vue'; import { h, computed } from 'vue';
import type { Component } from 'vue' import type { Component } from 'vue';
import { NIcon, useDialog } from 'naive-ui' import { NIcon, useDialog } from 'naive-ui';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { DropdownOption } from 'naive-ui'; import { DropdownOption } from 'naive-ui';
import { ShareOutline, CheckmarkOutline, CloseOutline, CheckmarkDoneOutline } from '@vicons/ionicons5'; import {
import { readMessage, addFriend, rejectFriend, followUser, unfollowUser } from '@/api/user'; ShareOutline,
CheckmarkOutline,
CloseOutline,
CheckmarkDoneOutline,
} from '@vicons/ionicons5';
import {
readMessage,
addFriend,
rejectFriend,
followUser,
unfollowUser,
} from '@/api/user';
import { formatRelativeTime } from '@/utils/formatTime'; import { formatRelativeTime } from '@/utils/formatTime';
import { MoreHorizFilled } from '@vicons/material'; import { MoreHorizFilled } from '@vicons/material';
import { import {
@ -152,9 +163,10 @@ import {
CheckmarkCircle, CheckmarkCircle,
BodyOutline, BodyOutline,
WalkOutline, WalkOutline,
} from '@vicons/ionicons5' } from '@vicons/ionicons5';
const defaultavatar = 'https://assets.paopao.info/public/avatar/default/admin.png'; const defaultavatar =
'https://assets.paopao.info/public/avatar/default/admin.png';
const router = useRouter(); const router = useRouter();
const store = useStore(); const store = useStore();
@ -163,66 +175,73 @@ const props = withDefaults(
defineProps<{ defineProps<{
message: Item.MessageProps; message: Item.MessageProps;
}>(), }>(),
{} {},
); );
const renderIcon = (icon: Component) => { const renderIcon = (icon: Component) => {
return () => { return () => {
return h(NIcon, null, { return h(NIcon, null, {
default: () => h(icon) default: () => h(icon),
}) });
} };
}; };
const actionOpts = computed(() => { const actionOpts = computed(() => {
let user = props.message.type == 4 && props.message.sender_user_id == store.state.userInfo.id let user =
props.message.type == 4 &&
props.message.sender_user_id == store.state.userInfo.id
? props.message.receiver_user ? props.message.receiver_user
: props.message.sender_user; : props.message.sender_user;
let options: DropdownOption[] = [ let options: DropdownOption[] = [
{ {
label: '私信 @' + user.username, label: '私信 @' + user.username,
key: 'whisper', key: 'whisper',
icon: renderIcon(PaperPlaneOutline) icon: renderIcon(PaperPlaneOutline),
}, },
] ];
if (store.state.userInfo.id != user.id) { if (store.state.userInfo.id != user.id) {
if (user.is_following) { if (user.is_following) {
options.push({ options.push({
label: '取消关注 @' + user.username, label: '取消关注 @' + user.username,
key: 'unfollow', key: 'unfollow',
icon: renderIcon(WalkOutline) icon: renderIcon(WalkOutline),
}) });
} else { } else {
options.push({ options.push({
label: '关注 @' + user.username, label: '关注 @' + user.username,
key: 'follow', key: 'follow',
icon: renderIcon(BodyOutline) icon: renderIcon(BodyOutline),
}) });
} }
} }
return options; return options;
}); });
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'send-whisper', user: Item.UserInfo): void (e: 'send-whisper', user: Item.UserInfo): void;
(e: 'reload'): void (e: 'reload'): void;
}>(); }>();
const onHandleFollowAction = (message: Item.MessageProps) => { const onHandleFollowAction = (message: Item.MessageProps) => {
let user = message.type == 4 && message.sender_user_id == store.state.userInfo.id let user =
message.type == 4 && message.sender_user_id == store.state.userInfo.id
? message.receiver_user ? message.receiver_user
: message.sender_user; : message.sender_user;
dialog.success({ dialog.success({
title: '提示', title: '提示',
content: content:
'确定' + (user.is_following ? '取消关注 @' : '关注 @') + user.username + ' 吗?', '确定' +
(user.is_following ? '取消关注 @' : '关注 @') +
user.username +
' 吗?',
positiveText: '确定', positiveText: '确定',
negativeText: '取消', negativeText: '取消',
onPositiveClick: () => { onPositiveClick: () => {
if (user.is_following) { if (user.is_following) {
unfollowUser({ unfollowUser({
user_id: user.id, user_id: user.id,
}).then((_res) => { })
.then((_res) => {
window.$message.success('操作成功'); window.$message.success('操作成功');
user.is_following = false; user.is_following = false;
// TODO: 这里暴力处理,简单重新加载,更好的做法是遍历所有message,如果是对应user就更新到新状态 // TODO: 这里暴力处理,简单重新加载,更好的做法是遍历所有message,如果是对应user就更新到新状态
@ -234,7 +253,8 @@ const onHandleFollowAction = (message: Item.MessageProps) => {
} else { } else {
followUser({ followUser({
user_id: user.id, user_id: user.id,
}).then((_res) => { })
.then((_res) => {
window.$message.success('关注成功'); window.$message.success('关注成功');
user.is_following = true; user.is_following = true;
// TODO: 这里暴力处理,简单重新加载,更好的做法是遍历所有message,如果是对应user就更新到新状态 // TODO: 这里暴力处理,简单重新加载,更好的做法是遍历所有message,如果是对应user就更新到新状态
@ -248,14 +268,13 @@ const onHandleFollowAction = (message: Item.MessageProps) => {
}); });
}; };
const handleAction = ( const handleAction = (item: 'whisper' | 'follow' | 'unfollow') => {
item: 'whisper' | 'follow' | 'unfollow'
) => {
switch (item) { switch (item) {
case 'whisper': case 'whisper':
const message = props.message const message = props.message;
if (message.type != 99) { if (message.type != 99) {
let user = message.type == 4 && message.sender_user_id == store.state.userInfo.id let user =
message.type == 4 && message.sender_user_id == store.state.userInfo.id
? message.receiver_user ? message.receiver_user
: message.sender_user; : message.sender_user;
emit('send-whisper', user); emit('send-whisper', user);
@ -271,15 +290,24 @@ const handleAction = (
}; };
const isNotWhisperSender = computed(() => { const isNotWhisperSender = computed(() => {
return props.message.type !== 4 || props.message.sender_user_id !== store.state.userInfo.id return (
props.message.type !== 4 ||
props.message.sender_user_id !== store.state.userInfo.id
);
}); });
const isWhisperReceiver = computed(() => { const isWhisperReceiver = computed(() => {
return props.message.type == 4 && props.message.receiver_user_id == store.state.userInfo.id return (
props.message.type == 4 &&
props.message.receiver_user_id == store.state.userInfo.id
);
}); });
const isWhisperSender = computed(() => { const isWhisperSender = computed(() => {
return props.message.type == 4 && props.message.sender_user_id == store.state.userInfo.id return (
props.message.type == 4 &&
props.message.sender_user_id == store.state.userInfo.id
);
}); });
const viewDetail = (message: Item.MessageProps) => { const viewDetail = (message: Item.MessageProps) => {
@ -310,7 +338,7 @@ const agreeAddFriend = (message: Item.MessageProps) => {
.catch((err) => { .catch((err) => {
console.log(err); console.log(err);
}); });
} };
const rejectAddFriend = (message: Item.MessageProps) => { const rejectAddFriend = (message: Item.MessageProps) => {
handleReadMessage(message); handleReadMessage(message);
@ -324,16 +352,17 @@ const rejectAddFriend = (message: Item.MessageProps) => {
.catch((err) => { .catch((err) => {
console.log(err); console.log(err);
}); });
} };
const handleReadMessage = (message: Item.MessageProps) => { const handleReadMessage = (message: Item.MessageProps) => {
if (props.message.receiver_user_id != store.state.userInfo.id) { if (props.message.receiver_user_id != store.state.userInfo.id) {
return return;
} }
if (message.is_read === 0) { if (message.is_read === 0) {
readMessage({ readMessage({
id: message.id, id: message.id,
}).then((_res) => { })
.then((_res) => {
message.is_read = 1; message.is_read = 1;
}) })
.catch((err) => { .catch((err) => {

@ -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>

@ -128,17 +128,14 @@
<script setup lang="ts"> <script setup lang="ts">
import { h, ref, computed } from 'vue'; import { h, ref, computed } from 'vue';
import type { Component } from 'vue' import type { Component } from 'vue';
import { NIcon } from 'naive-ui' import { NIcon } from 'naive-ui';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import type { DropdownOption } from 'naive-ui'; import type { DropdownOption } from 'naive-ui';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { formatPrettyDate } from '@/utils/formatTime'; import { formatPrettyDate } from '@/utils/formatTime';
import { preparePost } from '@/utils/content'; import { preparePost } from '@/utils/content';
import { import { postStar, postCollection } from '@/api/post';
postStar,
postCollection,
} from '@/api/post';
import { import {
PaperPlaneOutline, PaperPlaneOutline,
HeartOutline, HeartOutline,
@ -151,30 +148,33 @@ import {
WalkOutline, WalkOutline,
} from '@vicons/ionicons5'; } from '@vicons/ionicons5';
import { MoreHorizFilled } from '@vicons/material'; import { MoreHorizFilled } from '@vicons/material';
import copy from "copy-to-clipboard"; import copy from 'copy-to-clipboard';
const router = useRouter(); const router = useRouter();
const store = useStore(); const store = useStore();
const inFoldStyle = ref<boolean>(true) const inFoldStyle = ref<boolean>(true);
const props = withDefaults(defineProps<{ const props = withDefaults(
post: Item.PostProps, defineProps<{
isOwner: boolean, post: Item.PostProps;
addFriendAction: boolean, isOwner: boolean;
addFollowAction: boolean, addFriendAction: boolean;
}>(), {}); addFollowAction: boolean;
}>(),
{},
);
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'send-whisper', user: Item.UserInfo): void (e: 'send-whisper', user: Item.UserInfo): void;
(e: 'handle-follow-action', user: Item.PostProps): void (e: 'handle-follow-action', user: Item.PostProps): void;
(e: 'handle-friend-action', user: Item.PostProps): void (e: 'handle-friend-action', user: Item.PostProps): void;
}>(); }>();
const renderIcon = (icon: Component) => { const renderIcon = (icon: Component) => {
return () => { return () => {
return h(NIcon, null, { return h(NIcon, null, {
default: () => h(icon) default: () => h(icon),
}) });
} };
}; };
const tweetOptions = computed(() => { const tweetOptions = computed(() => {
@ -183,7 +183,7 @@ const tweetOptions = computed(() => {
options.push({ options.push({
label: '私信 @' + props.post.user.username, label: '私信 @' + props.post.user.username,
key: 'whisper', key: 'whisper',
icon: renderIcon(PaperPlaneOutline) icon: renderIcon(PaperPlaneOutline),
}); });
} }
if (!props.isOwner && props.addFollowAction) { if (!props.isOwner && props.addFollowAction) {
@ -191,14 +191,14 @@ const tweetOptions = computed(() => {
options.push({ options.push({
label: '取消关注 @' + props.post.user.username, label: '取消关注 @' + props.post.user.username,
key: 'unfollow', key: 'unfollow',
icon: renderIcon(WalkOutline) icon: renderIcon(WalkOutline),
}) });
} else { } else {
options.push({ options.push({
label: '关注 @' + props.post.user.username, label: '关注 @' + props.post.user.username,
key: 'follow', key: 'follow',
icon: renderIcon(BodyOutline) icon: renderIcon(BodyOutline),
}) });
} }
} }
if (!props.isOwner && props.addFriendAction) { if (!props.isOwner && props.addFriendAction) {
@ -206,13 +206,13 @@ const tweetOptions = computed(() => {
options.push({ options.push({
label: '删除好友 @' + props.post.user.username, label: '删除好友 @' + props.post.user.username,
key: 'delete', key: 'delete',
icon: renderIcon(PersonRemoveOutline) icon: renderIcon(PersonRemoveOutline),
}); });
} else { } else {
options.push({ options.push({
label: '添加朋友 @' + props.post.user.username, label: '添加朋友 @' + props.post.user.username,
key: 'requesting', key: 'requesting',
icon: renderIcon(PersonAddOutline) icon: renderIcon(PersonAddOutline),
}); });
} }
} }
@ -225,11 +225,19 @@ const tweetOptions = computed(() => {
}); });
const handleTweetAction = async ( const handleTweetAction = async (
item: 'copyTweetLink' | 'whisper' | 'follow' | 'unfollow' | 'delete' | 'requesting' item:
| 'copyTweetLink'
| 'whisper'
| 'follow'
| 'unfollow'
| 'delete'
| 'requesting',
) => { ) => {
switch (item) { switch (item) {
case 'copyTweetLink': case 'copyTweetLink':
copy(`${window.location.origin}/#/post?id=${post.value.id}&share=copy_link&t=${new Date().getTime()}`); copy(
`${window.location.origin}/#/post?id=${post.value.id}&share=copy_link&t=${new Date().getTime()}`,
);
window.$message.success('链接已复制到剪贴板'); window.$message.success('链接已复制到剪贴板');
break; break;
case 'whisper': case 'whisper':
@ -259,7 +267,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) {
@ -302,7 +310,8 @@ const handlePostStar = () => {
} else { } else {
post.value = { post.value = {
...post.value, ...post.value,
upvote_count: post.value.upvote_count > 0 ? post.value.upvote_count - 1 : 0, upvote_count:
post.value.upvote_count > 0 ? post.value.upvote_count - 1 : 0,
}; };
} }
}) })
@ -324,7 +333,10 @@ const handlePostCollection = () => {
} else { } else {
post.value = { post.value = {
...post.value, ...post.value,
collection_count: post.value.collection_count > 0 ? post.value.collection_count - 1 : 0, collection_count:
post.value.collection_count > 0
? post.value.collection_count - 1
: 0,
}; };
} }
}) })
@ -342,7 +354,7 @@ const goPostDetail = (id: number) => {
}); });
}; };
const doClickText = (e: MouseEvent, id: number) => { const doClickText = (e: MouseEvent, id: number) => {
const detail = (e.target as any).dataset.detail const detail = (e.target as any).dataset.detail;
if (detail && detail !== 'post') { if (detail && detail !== 'post') {
const d = detail.split(':'); const d = detail.split(':');
if (d.length === 2) { if (d.length === 2) {
@ -365,7 +377,7 @@ const doClickText = (e: MouseEvent, id: number) => {
} }
} }
} else if (detail && detail === 'post') { } else if (detail && detail === 'post') {
inFoldStyle.value = !inFoldStyle.value inFoldStyle.value = !inFoldStyle.value;
} else { } else {
goPostDetail(id); goPostDetail(id);
} }

@ -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',
{},
'此次下载您已支付或无需付费,请确认下载'
),
]); ]);
} }
}) })

@ -216,8 +216,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { h, ref, onMounted, computed } from 'vue'; import { h, ref, onMounted, computed } from 'vue';
import type { Component } from 'vue' import type { Component } from 'vue';
import { NIcon, useDialog } from 'naive-ui' import { NIcon, useDialog } from 'naive-ui';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { formatPrettyTime } from '@/utils/formatTime'; import { formatPrettyTime } from '@/utils/formatTime';
@ -251,14 +251,15 @@ import {
lockPost, lockPost,
stickPost, stickPost,
highlightPost, highlightPost,
visibilityPost visibilityPost,
} from '@/api/post'; } from '@/api/post';
import { followUser, unfollowUser } from '@/api/user'; import { followUser, unfollowUser } from '@/api/user';
import type { DropdownOption } from 'naive-ui'; import type { DropdownOption } from 'naive-ui';
import { VisibilityEnum } from '@/utils/IEnum'; import { VisibilityEnum } from '@/utils/IEnum';
import copy from "copy-to-clipboard"; import copy from 'copy-to-clipboard';
const useFriendship = (import.meta.env.VITE_USE_FRIENDSHIP.toLowerCase() === 'true') const useFriendship =
import.meta.env.VITE_USE_FRIENDSHIP.toLowerCase() === 'true';
const store = useStore(); const store = useStore();
const router = useRouter(); const router = useRouter();
@ -269,7 +270,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);
@ -317,7 +318,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) {
@ -352,50 +353,53 @@ const post = computed({
const renderIcon = (icon: Component) => { const renderIcon = (icon: Component) => {
return () => { return () => {
return h(NIcon, null, { return h(NIcon, null, {
default: () => h(icon) default: () => h(icon),
}) });
} };
}; };
const adminOptions = computed(() => { const adminOptions = computed(() => {
let options: DropdownOption[] = []; let options: DropdownOption[] = [];
if (!store.state.userInfo.is_admin && store.state.userInfo.id != props.post.user.id) { if (
!store.state.userInfo.is_admin &&
store.state.userInfo.id != props.post.user.id
) {
options.push({ options.push({
label: '私信 @' + props.post.user.username, label: '私信 @' + props.post.user.username,
key: 'whisper', key: 'whisper',
icon: renderIcon(PaperPlaneOutline) icon: renderIcon(PaperPlaneOutline),
}); });
if (props.post.user.is_following) { if (props.post.user.is_following) {
options.push({ options.push({
label: '取消关注 @' + props.post.user.username, label: '取消关注 @' + props.post.user.username,
key: 'unfollow', key: 'unfollow',
icon: renderIcon(WalkOutline) icon: renderIcon(WalkOutline),
}) });
} else { } else {
options.push({ options.push({
label: '关注 @' + props.post.user.username, label: '关注 @' + props.post.user.username,
key: 'follow', key: 'follow',
icon: renderIcon(BodyOutline) icon: renderIcon(BodyOutline),
}) });
} }
return options; return options;
} }
options.push({ options.push({
label: '删除', label: '删除',
key: 'delete', key: 'delete',
icon: renderIcon(TrashOutline) icon: renderIcon(TrashOutline),
}) });
if (post.value.is_lock === 0) { if (post.value.is_lock === 0) {
options.push({ options.push({
label: '锁定', label: '锁定',
key: 'lock', key: 'lock',
icon: renderIcon(LockClosedOutline) icon: renderIcon(LockClosedOutline),
}); });
} else { } else {
options.push({ options.push({
label: '解锁', label: '解锁',
key: 'unlock', key: 'unlock',
icon: renderIcon(LockOpenOutline) icon: renderIcon(LockOpenOutline),
}); });
} }
if (store.state.userInfo.is_admin) { if (store.state.userInfo.is_admin) {
@ -403,13 +407,13 @@ const adminOptions = computed(() => {
options.push({ options.push({
label: '置顶', label: '置顶',
key: 'stick', key: 'stick',
icon: renderIcon(PushOutline) icon: renderIcon(PushOutline),
}); });
} else { } else {
options.push({ options.push({
label: '取消置顶', label: '取消置顶',
key: 'unstick', key: 'unstick',
icon: renderIcon(PushOutline) icon: renderIcon(PushOutline),
}); });
} }
} }
@ -417,16 +421,16 @@ const adminOptions = computed(() => {
options.push({ options.push({
label: '设为亮点', label: '设为亮点',
key: 'highlight', key: 'highlight',
icon: renderIcon(FlameOutline) icon: renderIcon(FlameOutline),
}); });
} else { } else {
options.push({ options.push({
label: '取消亮点', label: '取消亮点',
key: 'unhighlight', key: 'unhighlight',
icon: renderIcon(FlameOutline) icon: renderIcon(FlameOutline),
}); });
} }
let visitMenu: DropdownOption let visitMenu: DropdownOption;
if (post.value.visibility === VisibilityEnum.PUBLIC) { if (post.value.visibility === VisibilityEnum.PUBLIC) {
visitMenu = { visitMenu = {
label: '公开', label: '公开',
@ -434,8 +438,8 @@ const adminOptions = computed(() => {
icon: renderIcon(EyeOutline), icon: renderIcon(EyeOutline),
children: [ children: [
{ label: '私密', key: 'vprivate', icon: renderIcon(EyeOffOutline) }, { label: '私密', key: 'vprivate', icon: renderIcon(EyeOffOutline) },
{ label: '关注可见', key: 'vfollowing', icon: renderIcon(BodyOutline) } { label: '关注可见', key: 'vfollowing', icon: renderIcon(BodyOutline) },
] ],
}; };
} else if (post.value.visibility === VisibilityEnum.PRIVATE) { } else if (post.value.visibility === VisibilityEnum.PRIVATE) {
visitMenu = { visitMenu = {
@ -444,8 +448,8 @@ const adminOptions = computed(() => {
icon: renderIcon(EyeOffOutline), icon: renderIcon(EyeOffOutline),
children: [ children: [
{ label: '公开', key: 'vpublic', icon: renderIcon(EyeOutline) }, { label: '公开', key: 'vpublic', icon: renderIcon(EyeOutline) },
{ label: '关注可见', key: 'vfollowing', icon: renderIcon(BodyOutline) } { label: '关注可见', key: 'vfollowing', icon: renderIcon(BodyOutline) },
] ],
}; };
} else if (useFriendship && post.value.visibility === VisibilityEnum.FRIEND) { } else if (useFriendship && post.value.visibility === VisibilityEnum.FRIEND) {
visitMenu = { visitMenu = {
@ -455,8 +459,8 @@ const adminOptions = computed(() => {
children: [ children: [
{ label: '公开', key: 'vpublic', icon: renderIcon(EyeOutline) }, { label: '公开', key: 'vpublic', icon: renderIcon(EyeOutline) },
{ label: '私密', key: 'vprivate', icon: renderIcon(EyeOffOutline) }, { label: '私密', key: 'vprivate', icon: renderIcon(EyeOffOutline) },
{ label: '关注可见', key: 'vfollowing', icon: renderIcon(BodyOutline) } { label: '关注可见', key: 'vfollowing', icon: renderIcon(BodyOutline) },
] ],
}; };
} else { } else {
visitMenu = { visitMenu = {
@ -465,12 +469,16 @@ const adminOptions = computed(() => {
icon: renderIcon(BodyOutline), icon: renderIcon(BodyOutline),
children: [ children: [
{ label: '公开', key: 'vpublic', icon: renderIcon(EyeOutline) }, { label: '公开', key: 'vpublic', icon: renderIcon(EyeOutline) },
{ label: '私密', key: 'vprivate', icon: renderIcon(EyeOffOutline) } { label: '私密', key: 'vprivate', icon: renderIcon(EyeOffOutline) },
] ],
}; };
} }
if (useFriendship && post.value.visibility !== VisibilityEnum.FRIEND) { if (useFriendship && post.value.visibility !== VisibilityEnum.FRIEND) {
visitMenu.children?.push({ label: '好友可见', key: 'vfriend', icon: renderIcon(PersonOutline) }) visitMenu.children?.push({
label: '好友可见',
key: 'vfriend',
icon: renderIcon(PersonOutline),
});
} }
options.push(visitMenu); options.push(visitMenu);
return options; return options;
@ -480,14 +488,18 @@ const onHandleFollowAction = (post: Item.PostProps) => {
dialog.success({ dialog.success({
title: '提示', title: '提示',
content: content:
'确定' + (post.user.is_following ? '取消关注 @' : '关注 @') + props.post.user.username + ' 吗?', '确定' +
(post.user.is_following ? '取消关注 @' : '关注 @') +
props.post.user.username +
' 吗?',
positiveText: '确定', positiveText: '确定',
negativeText: '取消', negativeText: '取消',
onPositiveClick: () => { onPositiveClick: () => {
if (post.user.is_following) { if (post.user.is_following) {
unfollowUser({ unfollowUser({
user_id: post.user.id, user_id: post.user.id,
}).then((_res) => { })
.then((_res) => {
window.$message.success('操作成功'); window.$message.success('操作成功');
post.user.is_following = false; post.user.is_following = false;
}) })
@ -495,7 +507,8 @@ const onHandleFollowAction = (post: Item.PostProps) => {
} else { } else {
followUser({ followUser({
user_id: post.user.id, user_id: post.user.id,
}).then((_res) => { })
.then((_res) => {
window.$message.success('操作成功'); window.$message.success('操作成功');
post.user.is_following = true; post.user.is_following = true;
}) })
@ -540,7 +553,21 @@ const doClickText = (e: MouseEvent, id: number) => {
goPostDetail(id); goPostDetail(id);
}; };
const handlePostAction = ( const handlePostAction = (
item: 'whisper' | 'follow' | 'unfollow' | 'delete' | 'lock' | 'unlock' | 'stick' | 'unstick' | 'highlight' | 'unhighlight' | 'vpublic' | 'vprivate' | 'vfriend' | 'vfollowing' item:
| 'whisper'
| 'follow'
| 'unfollow'
| 'delete'
| 'lock'
| 'unlock'
| 'stick'
| 'unstick'
| 'highlight'
| 'unhighlight'
| 'vpublic'
| 'vprivate'
| 'vfriend'
| 'vfollowing',
) => { ) => {
switch (item) { switch (item) {
case 'whisper': case 'whisper':
@ -655,7 +682,7 @@ const execHighlightAction = () => {
const execVisibilityAction = () => { const execVisibilityAction = () => {
visibilityPost({ visibilityPost({
id: post.value.id, id: post.value.id,
visibility: tempVisibility.value visibility: tempVisibility.value,
}) })
.then((_res) => { .then((_res) => {
emit('reload', post.value.id); emit('reload', post.value.id);
@ -710,7 +737,9 @@ const handlePostCollection = () => {
}); });
}; };
const handlePostShare = () => { const handlePostShare = () => {
copy(`${window.location.origin}/#/post?id=${post.value.id}&share=copy_link&t=${new Date().getTime()}`); copy(
`${window.location.origin}/#/post?id=${post.value.id}&share=copy_link&t=${new Date().getTime()}`,
);
window.$message.success('链接已复制到剪贴板'); window.$message.success('链接已复制到剪贴板');
}; };

@ -227,11 +227,14 @@ import { ref, onMounted } from 'vue';
const defaultImg = import.meta.env.VITE_DEFAULT_TWEET_IMAGE_404; const defaultImg = import.meta.env.VITE_DEFAULT_TWEET_IMAGE_404;
const thumbnail = import.meta.env.VITE_TWEET_IMAGE_THUMBNAIL; const thumbnail = import.meta.env.VITE_TWEET_IMAGE_THUMBNAIL;
const props = withDefaults(defineProps<{ const props = withDefaults(
imgs: Item.PostItemProps[], defineProps<{
}>(), { imgs: Item.PostItemProps[];
imgs: () => [] }>(),
}); {
imgs: () => [],
},
);
</script> </script>
<style lang="less"> <style lang="less">

@ -128,15 +128,12 @@
import { h, ref, computed } from 'vue'; import { h, ref, computed } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { NIcon } from 'naive-ui' import { NIcon } from 'naive-ui';
import type { Component } from 'vue' import type { Component } from 'vue';
import type { DropdownOption } from 'naive-ui'; import type { DropdownOption } from 'naive-ui';
import { formatPrettyDate } from '@/utils/formatTime'; import { formatPrettyDate } from '@/utils/formatTime';
import { preparePost } from '@/utils/content'; import { preparePost } from '@/utils/content';
import { import { postStar, postCollection } from '@/api/post';
postStar,
postCollection,
} from '@/api/post';
import { import {
PaperPlaneOutline, PaperPlaneOutline,
HeartOutline, HeartOutline,
@ -149,30 +146,33 @@ import {
WalkOutline, WalkOutline,
} from '@vicons/ionicons5'; } from '@vicons/ionicons5';
import { MoreHorizFilled } from '@vicons/material'; import { MoreHorizFilled } from '@vicons/material';
import copy from "copy-to-clipboard"; import copy from 'copy-to-clipboard';
const router = useRouter(); const router = useRouter();
const store = useStore(); const store = useStore();
const inFoldStyle = ref<boolean>(true) const inFoldStyle = ref<boolean>(true);
const props = withDefaults(defineProps<{ const props = withDefaults(
post: Item.PostProps, defineProps<{
isOwner: boolean, post: Item.PostProps;
addFriendAction: boolean, isOwner: boolean;
addFollowAction: boolean, addFriendAction: boolean;
}>(), {}); addFollowAction: boolean;
}>(),
{},
);
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'send-whisper', user: Item.UserInfo): void (e: 'send-whisper', user: Item.UserInfo): void;
(e: 'handle-follow-action', user: Item.PostProps): void (e: 'handle-follow-action', user: Item.PostProps): void;
(e: 'handle-friend-action', user: Item.PostProps): void (e: 'handle-friend-action', user: Item.PostProps): void;
}>(); }>();
const renderIcon = (icon: Component) => { const renderIcon = (icon: Component) => {
return () => { return () => {
return h(NIcon, null, { return h(NIcon, null, {
default: () => h(icon) default: () => h(icon),
}) });
} };
}; };
const tweetOptions = computed(() => { const tweetOptions = computed(() => {
@ -181,7 +181,7 @@ const tweetOptions = computed(() => {
options.push({ options.push({
label: '私信 @' + props.post.user.username, label: '私信 @' + props.post.user.username,
key: 'whisper', key: 'whisper',
icon: renderIcon(PaperPlaneOutline) icon: renderIcon(PaperPlaneOutline),
}); });
} }
if (!props.isOwner && props.addFollowAction) { if (!props.isOwner && props.addFollowAction) {
@ -189,14 +189,14 @@ const tweetOptions = computed(() => {
options.push({ options.push({
label: '取消关注 @' + props.post.user.username, label: '取消关注 @' + props.post.user.username,
key: 'unfollow', key: 'unfollow',
icon: renderIcon(WalkOutline) icon: renderIcon(WalkOutline),
}) });
} else { } else {
options.push({ options.push({
label: '关注 @' + props.post.user.username, label: '关注 @' + props.post.user.username,
key: 'follow', key: 'follow',
icon: renderIcon(BodyOutline) icon: renderIcon(BodyOutline),
}) });
} }
} }
if (!props.isOwner && props.addFriendAction) { if (!props.isOwner && props.addFriendAction) {
@ -204,13 +204,13 @@ const tweetOptions = computed(() => {
options.push({ options.push({
label: '删除好友 @' + props.post.user.username, label: '删除好友 @' + props.post.user.username,
key: 'delete', key: 'delete',
icon: renderIcon(PersonRemoveOutline) icon: renderIcon(PersonRemoveOutline),
}); });
} else { } else {
options.push({ options.push({
label: '添加朋友 @' + props.post.user.username, label: '添加朋友 @' + props.post.user.username,
key: 'requesting', key: 'requesting',
icon: renderIcon(PersonAddOutline) icon: renderIcon(PersonAddOutline),
}); });
} }
} }
@ -223,11 +223,19 @@ const tweetOptions = computed(() => {
}); });
const handleTweetAction = async ( const handleTweetAction = async (
item: 'copyTweetLink' | 'whisper' | 'follow' | 'unfollow' | 'delete' | 'requesting' item:
| 'copyTweetLink'
| 'whisper'
| 'follow'
| 'unfollow'
| 'delete'
| 'requesting',
) => { ) => {
switch (item) { switch (item) {
case 'copyTweetLink': case 'copyTweetLink':
copy(`${window.location.origin}/#/post?id=${post.value.id}&share=copy_link&t=${new Date().getTime()}`); copy(
`${window.location.origin}/#/post?id=${post.value.id}&share=copy_link&t=${new Date().getTime()}`,
);
window.$message.success('链接已复制到剪贴板'); window.$message.success('链接已复制到剪贴板');
break; break;
case 'whisper': case 'whisper':
@ -257,7 +265,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) {
@ -299,7 +307,8 @@ const handlePostStar = () => {
} else { } else {
post.value = { post.value = {
...post.value, ...post.value,
upvote_count: post.value.upvote_count > 0 ? post.value.upvote_count - 1 : 0, upvote_count:
post.value.upvote_count > 0 ? post.value.upvote_count - 1 : 0,
}; };
} }
}) })
@ -320,7 +329,10 @@ const handlePostCollection = () => {
} else { } else {
post.value = { post.value = {
...post.value, ...post.value,
collection_count: post.value.collection_count > 0 ? post.value.collection_count - 1 : 0, collection_count:
post.value.collection_count > 0
? post.value.collection_count - 1
: 0,
}; };
} }
}) })
@ -337,7 +349,7 @@ const goPostDetail = (id: number) => {
}); });
}; };
const doClickText = (e: MouseEvent, id: number) => { const doClickText = (e: MouseEvent, id: number) => {
const detail = (e.target as any).dataset.detail const detail = (e.target as any).dataset.detail;
if (detail && detail !== 'post') { if (detail && detail !== 'post') {
const d = detail.split(':'); const d = detail.split(':');
if (d.length === 2) { if (d.length === 2) {
@ -360,7 +372,7 @@ const doClickText = (e: MouseEvent, id: number) => {
} }
} }
} else if (detail && detail === 'post') { } else if (detail && detail === 'post') {
inFoldStyle.value = !inFoldStyle.value inFoldStyle.value = !inFoldStyle.value;
} else { } else {
goPostDetail(id); goPostDetail(id);
} }

@ -13,11 +13,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>

@ -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>

@ -20,6 +20,6 @@ const props = withDefaults(
{ {
videos: () => [], videos: () => [],
full: false, full: false,
} },
); );
</script> </script>

@ -87,7 +87,11 @@ import { ref } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { Trash } from '@vicons/tabler'; import { Trash } from '@vicons/tabler';
import { formatPrettyTime } from '@/utils/formatTime'; import { formatPrettyTime } from '@/utils/formatTime';
import { deleteCommentReply, thumbsUpTweetReply, thumbsDownTweetReply } from '@/api/post'; import {
deleteCommentReply,
thumbsUpTweetReply,
thumbsDownTweetReply,
} from '@/api/post';
import { import {
ThumbUpTwotone, ThumbUpTwotone,
ThumbUpOutlined, ThumbUpOutlined,
@ -96,19 +100,22 @@ import {
} from '@vicons/material'; } from '@vicons/material';
import { YesNoEnum } from '@/utils/IEnum'; import { YesNoEnum } from '@/utils/IEnum';
const props = withDefaults(defineProps<{ const props = withDefaults(
tweetId: number, defineProps<{
reply: Item.ReplyProps, tweetId: number;
}>(), {}); 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 hasThumbsUp = ref(props.reply.is_thumbs_up == YesNoEnum.YES) const hasThumbsUp = ref(props.reply.is_thumbs_up == YesNoEnum.YES);
const hasThumbsDown = ref(props.reply.is_thumbs_down == YesNoEnum.YES) const hasThumbsDown = ref(props.reply.is_thumbs_down == YesNoEnum.YES);
const thumbsUpCount = ref(props.reply.thumbs_up_count) const thumbsUpCount = ref(props.reply.thumbs_up_count);
const handleThumbsUp = () => { const handleThumbsUp = () => {
thumbsUpTweetReply({ thumbsUpTweetReply({
@ -117,12 +124,12 @@ const handleThumbsUp = () => {
reply_id: props.reply.id, reply_id: props.reply.id,
}) })
.then((_res) => { .then((_res) => {
hasThumbsUp.value = !hasThumbsUp.value hasThumbsUp.value = !hasThumbsUp.value;
if (hasThumbsUp.value) { if (hasThumbsUp.value) {
thumbsUpCount.value++ thumbsUpCount.value++;
hasThumbsDown.value = false hasThumbsDown.value = false;
} else { } else {
thumbsUpCount.value-- thumbsUpCount.value--;
} }
}) })
.catch((err) => { .catch((err) => {
@ -136,11 +143,11 @@ const handleThumbsDown = () => {
reply_id: props.reply.id, reply_id: props.reply.id,
}) })
.then((_res) => { .then((_res) => {
hasThumbsDown.value = !hasThumbsDown.value hasThumbsDown.value = !hasThumbsDown.value;
if (hasThumbsDown.value) { if (hasThumbsDown.value) {
if (hasThumbsUp.value) { if (hasThumbsUp.value) {
thumbsUpCount.value-- thumbsUpCount.value--;
hasThumbsUp.value = false hasThumbsUp.value = false;
} }
} }
}) })

@ -99,13 +99,17 @@ const loading = ref(false);
const keyword = ref(''); const keyword = ref('');
const store = useStore(); const store = useStore();
const router = useRouter(); const router = useRouter();
const registerUserCount = ref(0) const registerUserCount = ref(0);
const onlineUserCount = ref(0) const onlineUserCount = ref(0);
const historyMaxOnline = ref(0) const historyMaxOnline = ref(0);
const serverUpTime = ref(0) const serverUpTime = ref(0);
const userInfoElement = ref<HTMLElement | null>(null); const userInfoElement = ref<HTMLElement | null>(null);
const rightFollowTopicMaxSize = Number(import.meta.env.VITE_RIGHT_FOLLOW_TOPIC_MAX_SIZE) const rightFollowTopicMaxSize = Number(
const rightHotTopicMaxSize = Number(import.meta.env.VITE_RIGHT_HOT_TOPIC_MAX_SIZE) import.meta.env.VITE_RIGHT_FOLLOW_TOPIC_MAX_SIZE,
);
const rightHotTopicMaxSize = Number(
import.meta.env.VITE_RIGHT_HOT_TOPIC_MAX_SIZE,
);
const loadSiteInfo = () => { const loadSiteInfo = () => {
getSiteInfo() getSiteInfo()
@ -118,7 +122,7 @@ const loadSiteInfo = () => {
.catch((_err) => { .catch((_err) => {
// do nothing // do nothing
}); });
observer.disconnect() observer.disconnect();
}; };
const loadHotTags = () => { const loadHotTags = () => {
loading.value = true; loading.value = true;
@ -130,7 +134,7 @@ const loadHotTags = () => {
.then((res) => { .then((res) => {
hotTags.value = res.topics; hotTags.value = res.topics;
followTags.value = res.extral_topics ?? []; followTags.value = res.extral_topics ?? [];
showFollowTopics.value = true showFollowTopics.value = true;
loading.value = false; loading.value = false;
}) })
.catch((_err) => { .catch((_err) => {
@ -162,7 +166,7 @@ const showFollowTopics = computed({
watch( watch(
() => ({ () => ({
refreshTopicFollow: store.state.refreshTopicFollow, refreshTopicFollow: store.state.refreshTopicFollow,
userLogined: store.state.userLogined userLogined: store.state.userLogined,
}), }),
(to, from) => { (to, from) => {
if (to.refreshTopicFollow !== from.refreshTopicFollow || to.userLogined) { if (to.refreshTopicFollow !== from.refreshTopicFollow || to.userLogined) {
@ -171,19 +175,22 @@ watch(
if (store.state.userInfo.is_admin) { if (store.state.userInfo.is_admin) {
loadSiteInfo(); loadSiteInfo();
} }
} },
); );
const observer = new IntersectionObserver((entries: IntersectionObserverEntry[]) => { const observer = new IntersectionObserver(
entries.forEach(entry => { (entries: IntersectionObserverEntry[]) => {
entries.forEach((entry) => {
if (entry.isIntersecting) { if (entry.isIntersecting) {
loadSiteInfo(); loadSiteInfo();
} }
}); });
}, { },
{
root: null, root: null,
rootMargin: '0px', rootMargin: '0px',
threshold: 1 threshold: 1,
}); },
);
onMounted(() => { onMounted(() => {
// 不知道为什么 store.state.userInfo.is_admin 在这里就是不起作用f*k,所以才用这么一种蹩脚的法子来凑合 // 不知道为什么 store.state.userInfo.is_admin 在这里就是不起作用f*k,所以才用这么一种蹩脚的法子来凑合
if (userInfoElement.value) { if (userInfoElement.value) {

@ -80,7 +80,8 @@ const hasUnreadMsg = ref(false);
const selectedPath = ref<any>(route.name || ''); const selectedPath = ref<any>(route.name || '');
const msgLoop = ref(); const msgLoop = ref();
const enableAnnoucement = (import.meta.env.VITE_ENABLE_ANOUNCEMENT.toLowerCase() === 'true'); const enableAnnoucement =
import.meta.env.VITE_ENABLE_ANOUNCEMENT.toLowerCase() === 'true';
watch(route, () => { watch(route, () => {
selectedPath.value = route.name; selectedPath.value = route.name;
@ -92,7 +93,7 @@ watch(store.state, () => {
getUnreadMsgCount() getUnreadMsgCount()
.then((res) => { .then((res) => {
hasUnreadMsg.value = res.count > 0; hasUnreadMsg.value = res.count > 0;
store.commit("updateUnreadMsgCount", res.count) store.commit('updateUnreadMsgCount', res.count);
}) })
.catch((err) => { .catch((err) => {
console.log(err); console.log(err);
@ -102,7 +103,7 @@ watch(store.state, () => {
getUnreadMsgCount() getUnreadMsgCount()
.then((res) => { .then((res) => {
hasUnreadMsg.value = res.count > 0; hasUnreadMsg.value = res.count > 0;
store.commit("updateUnreadMsgCount", res.count) store.commit('updateUnreadMsgCount', res.count);
}) })
.catch((err) => { .catch((err) => {
console.log(err); console.log(err);
@ -155,7 +156,7 @@ const menuOptions = computed(() => {
key: 'messages', key: 'messages',
icon: () => h(ChatbubblesOutline), icon: () => h(ChatbubblesOutline),
href: '/messages', href: '/messages',
}) });
options.push({ options.push({
label: '收藏', label: '收藏',
key: 'collection', key: 'collection',
@ -228,9 +229,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 });
@ -239,9 +240,10 @@ const renderMenuIcon = (option: AnyObject) => {
const goRouter = (name: string, item: any = {}) => { const goRouter = (name: string, item: any = {}) => {
selectedPath.value = name; selectedPath.value = name;
router.push({ router.push({
name, query: { name,
t: (new Date().getTime()) query: {
} t: new Date().getTime(),
},
}); });
}; };
const goHome = () => { const goHome = () => {
@ -256,8 +258,8 @@ const triggerAuth = (key: string) => {
}; };
const handleLogout = () => { const handleLogout = () => {
store.commit('userLogout'); store.commit('userLogout');
store.commit('refresh') store.commit('refresh');
goHome() goHome();
}; };
window.$store = store; window.$store = store;
window.$message = useMessage(); window.$message = useMessage();

@ -67,18 +67,17 @@ const props = withDefaults(
checkFollowing: boolean; checkFollowing: boolean;
checkPin: boolean; checkPin: boolean;
}>(), }>(),
{} {},
); );
const tagUserAvatar = computed(() => { const tagUserAvatar = computed(() => {
if (props.tag.user) { if (props.tag.user) {
return props.tag.user.avatar return props.tag.user.avatar;
} else { } else {
return defaultUserAvatar return defaultUserAvatar;
} }
}); });
const tagOptions = computed(() => { const tagOptions = computed(() => {
let options: DropdownOption[] = []; let options: DropdownOption[] = [];
if (props.tag.is_following === 0) { if (props.tag.is_following === 0) {
@ -118,15 +117,15 @@ const tagOptions = computed(() => {
}); });
const handleTagAction = ( const handleTagAction = (
item: 'follow' | 'unfollow' | 'pin' | 'unpin' | 'stick' | 'unstick' item: 'follow' | 'unfollow' | 'pin' | 'unpin' | 'stick' | 'unstick',
) => { ) => {
switch (item) { switch (item) {
case 'follow': case 'follow':
followTopic({ followTopic({
topic_id: props.tag.id topic_id: props.tag.id,
}) })
.then((_res) => { .then((_res) => {
props.tag.is_following = 1 props.tag.is_following = 1;
window.$message.success(`关注成功`); window.$message.success(`关注成功`);
}) })
.catch((err) => { .catch((err) => {
@ -135,10 +134,10 @@ const handleTagAction = (
break; break;
case 'unfollow': case 'unfollow':
unfollowTopic({ unfollowTopic({
topic_id: props.tag.id topic_id: props.tag.id,
}) })
.then((_res) => { .then((_res) => {
props.tag.is_following = 0 props.tag.is_following = 0;
window.$message.success(`取消关注`); window.$message.success(`取消关注`);
}) })
.catch((err) => { .catch((err) => {
@ -147,7 +146,7 @@ const handleTagAction = (
break; break;
case 'pin': case 'pin':
pinTopic({ pinTopic({
topic_id: props.tag.id topic_id: props.tag.id,
}) })
.then((_res) => { .then((_res) => {
props.tag.is_pin = 1; props.tag.is_pin = 1;
@ -159,7 +158,7 @@ const handleTagAction = (
break; break;
case 'unpin': case 'unpin':
pinTopic({ pinTopic({
topic_id: props.tag.id topic_id: props.tag.id,
}) })
.then((_res) => { .then((_res) => {
props.tag.is_pin = 0; props.tag.is_pin = 0;
@ -171,10 +170,10 @@ const handleTagAction = (
break; break;
case 'stick': case 'stick':
stickTopic({ stickTopic({
topic_id: props.tag.id topic_id: props.tag.id,
}) })
.then((res) => { .then((res) => {
props.tag.is_top = res.top_status props.tag.is_top = res.top_status;
window.$message.success(`置顶成功`); window.$message.success(`置顶成功`);
}) })
.catch((err) => { .catch((err) => {
@ -183,10 +182,10 @@ const handleTagAction = (
break; break;
case 'unstick': case 'unstick':
stickTopic({ stickTopic({
topic_id: props.tag.id topic_id: props.tag.id,
}) })
.then((res) => { .then((res) => {
props.tag.is_top = res.top_status props.tag.is_top = res.top_status;
window.$message.success(`取消置顶`); window.$message.success(`取消置顶`);
}) })
.catch((err) => { .catch((err) => {
@ -199,7 +198,7 @@ const handleTagAction = (
}; };
onMounted(() => { onMounted(() => {
hasFollowing.value = false hasFollowing.value = false;
}); });
</script> </script>

@ -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);

@ -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,20 +1,20 @@
import { createApp } from 'vue' import { createApp } from 'vue';
import router from './router' import router from './router';
import store from './store' import store from './store';
import App from './App.vue' import App from './App.vue';
import type { MessageApiInjection } from 'naive-ui/lib/message/src/MessageProvider' import type { MessageApiInjection } from 'naive-ui/lib/message/src/MessageProvider';
// 通用字体 // 通用字体
import 'vfonts/Lato.css' import 'vfonts/Lato.css';
// 等宽字体 // 等宽字体
import 'vfonts/FiraCode.css' import 'vfonts/FiraCode.css';
createApp(App).use(router).use(store).mount('#app') createApp(App).use(router).use(store).mount('#app');
declare global { declare global {
interface Window { interface Window {
$message: MessageApiInjection, $message: MessageApiInjection;
$store: any $store: any;
} }
} }

@ -1,114 +1,114 @@
import { createRouter, createWebHashHistory } from "vue-router"; import { createRouter, createWebHashHistory } from 'vue-router';
const routes = [ const routes = [
{ {
path: "/", path: '/',
name: "home", name: 'home',
meta: { meta: {
title: "广场", title: '广场',
keepAlive: true, keepAlive: true,
}, },
component: () => import("@/views/Home.vue"), component: () => import('@/views/Home.vue'),
}, },
{ {
path: "/post", path: '/post',
name: "post", name: 'post',
meta: { meta: {
title: "泡泡详情", title: '泡泡详情',
}, },
component: () => import("@/views/Post.vue"), component: () => import('@/views/Post.vue'),
}, },
{ {
path: "/topic", path: '/topic',
name: "topic", name: 'topic',
meta: { meta: {
title: "话题", title: '话题',
}, },
component: () => import("@/views/Topic.vue"), component: () => import('@/views/Topic.vue'),
}, },
{ {
path: "/anouncement", path: '/anouncement',
name: "anouncement", name: 'anouncement',
meta: { meta: {
title: "公告", title: '公告',
}, },
component: () => import("@/views/Anouncement.vue"), component: () => import('@/views/Anouncement.vue'),
}, },
{ {
path: "/profile", path: '/profile',
name: "profile", name: 'profile',
meta: { meta: {
title: "主页", title: '主页',
}, },
component: () => import("@/views/Profile.vue"), component: () => import('@/views/Profile.vue'),
}, },
{ {
path: "/u", path: '/u',
name: "user", name: 'user',
meta: { meta: {
title: "用户详情", title: '用户详情',
}, },
component: () => import("@/views/User.vue"), component: () => import('@/views/User.vue'),
}, },
{ {
path: "/messages", path: '/messages',
name: "messages", name: 'messages',
meta: { meta: {
title: "消息", title: '消息',
}, },
component: () => import("@/views/Messages.vue"), component: () => import('@/views/Messages.vue'),
}, },
{ {
path: "/collection", path: '/collection',
name: "collection", name: 'collection',
meta: { meta: {
title: "收藏", title: '收藏',
}, },
component: () => import("@/views/Collection.vue"), component: () => import('@/views/Collection.vue'),
}, },
{ {
path: "/contacts", path: '/contacts',
name: "contacts", name: 'contacts',
meta: { meta: {
title: "好友", title: '好友',
}, },
component: () => import("@/views/Contacts.vue"), component: () => import('@/views/Contacts.vue'),
}, },
{ {
path: "/following", path: '/following',
name: "following", name: 'following',
meta: { meta: {
title: "关注", title: '关注',
}, },
component: () => import("@/views/Following.vue"), component: () => import('@/views/Following.vue'),
}, },
{ {
path: "/wallet", path: '/wallet',
name: "wallet", name: 'wallet',
meta: { meta: {
title: "钱包", title: '钱包',
}, },
component: () => import("@/views/Wallet.vue"), component: () => import('@/views/Wallet.vue'),
}, },
{ {
path: "/setting", path: '/setting',
name: "setting", name: 'setting',
meta: { meta: {
title: "设置", title: '设置',
}, },
component: () => import("@/views/Setting.vue"), component: () => import('@/views/Setting.vue'),
}, },
{ {
path: "/404", path: '/404',
name: "404", name: '404',
meta: { meta: {
title: "404", title: '404',
}, },
component: () => import("@/views/404.vue"), component: () => import('@/views/404.vue'),
}, },
{ {
path: "/:pathMatch(.*)", path: '/:pathMatch(.*)',
redirect: "/404", redirect: '/404',
}, },
]; ];

@ -1,19 +1,19 @@
declare module '*.vue' { declare module '*.vue' {
import type { DefineComponent } from 'vue' import type { DefineComponent } from 'vue';
const component: DefineComponent<{}, {}, any> const component: DefineComponent<{}, {}, any>;
export default component export default component;
} }
declare module '*.svg' declare module '*.svg';
declare module '*.png' declare module '*.png';
declare module '*.jpg' declare module '*.jpg';
declare module '*.jpeg' declare module '*.jpeg';
declare module '*.gif' declare module '*.gif';
declare module '*.bmp' declare module '*.bmp';
declare module '*.tiff' declare module '*.tiff';
declare module '*.json' declare module '*.json';
declare module 'paopao-video-player' declare module 'paopao-video-player';
interface AnyObject { interface AnyObject {
[key: string]: any [key: string]: any;
} }

@ -1,22 +1,22 @@
import { createStore } from "vuex"; import { createStore } from 'vuex';
export default createStore({ export default createStore({
state: { state: {
refresh: Date.now(), refresh: Date.now(),
refreshTopicFollow: Date.now(), refreshTopicFollow: Date.now(),
theme: localStorage.getItem("PAOPAO_THEME"), theme: localStorage.getItem('PAOPAO_THEME'),
collapsedLeft: document.body.clientWidth <= 821, collapsedLeft: document.body.clientWidth <= 821,
collapsedRight: document.body.clientWidth <= 821, collapsedRight: document.body.clientWidth <= 821,
drawerModelShow: document.body.clientWidth <= 821, drawerModelShow: document.body.clientWidth <= 821,
desktopModelShow: document.body.clientWidth > 821, desktopModelShow: document.body.clientWidth > 821,
authModalShow: false, authModalShow: false,
authModelTab: "signin", authModelTab: 'signin',
unreadMsgCount: 0, unreadMsgCount: 0,
userLogined: false, userLogined: false,
userInfo: { userInfo: {
id: 0, id: 0,
username: "", username: '',
nickname: "", nickname: '',
created_on: 0, created_on: 0,
follows: 0, follows: 0,
followings: 0, followings: 0,
@ -35,13 +35,13 @@ export default createStore({
defaultTweetMaxLength: 2000, defaultTweetMaxLength: 2000,
tweetWebEllipsisSize: 400, tweetWebEllipsisSize: 400,
tweetMobileEllipsisSize: 300, tweetMobileEllipsisSize: 300,
defaultTweetVisibility: "friend", defaultTweetVisibility: 'friend',
defaultMsgLoopInterval: 5000, defaultMsgLoopInterval: 5000,
copyrightTop: "2023 paopao.info", copyrightTop: '2023 paopao.info',
copyrightLeft: "Roc's Me", copyrightLeft: "Roc's Me",
copyrightLeftLink: "", copyrightLeftLink: '',
copyrightRight: "泡泡(PaoPao)开源社区", copyrightRight: '泡泡(PaoPao)开源社区',
copyrightRightLink: "https://www.paopao.info", copyrightRightLink: 'https://www.paopao.info',
}, },
}, },
mutations: { mutations: {
@ -79,47 +79,47 @@ export default createStore({
}, },
loadDefaultSiteProfile(state) { loadDefaultSiteProfile(state) {
state.profile.useFriendship = state.profile.useFriendship =
import.meta.env.VITE_USE_FRIENDSHIP.toLowerCase() === "true"; import.meta.env.VITE_USE_FRIENDSHIP.toLowerCase() === 'true';
state.profile.enableTrendsBar = state.profile.enableTrendsBar =
import.meta.env.VITE_ENABLE_TRENDS_BAR.toLowerCase() === "true"; import.meta.env.VITE_ENABLE_TRENDS_BAR.toLowerCase() === 'true';
state.profile.enableWallet = state.profile.enableWallet =
import.meta.env.VITE_ENABLE_WALLET.toLocaleLowerCase() === "true"; import.meta.env.VITE_ENABLE_WALLET.toLocaleLowerCase() === 'true';
state.profile.allowTweetAttachment = state.profile.allowTweetAttachment =
import.meta.env.VITE_ALLOW_TWEET_ATTACHMENT.toLowerCase() === "true"; import.meta.env.VITE_ALLOW_TWEET_ATTACHMENT.toLowerCase() === 'true';
state.profile.allowTweetAttachmentPrice = state.profile.allowTweetAttachmentPrice =
import.meta.env.VITE_ALLOW_TWEET_ATTACHMENT_PRICE.toLowerCase() === import.meta.env.VITE_ALLOW_TWEET_ATTACHMENT_PRICE.toLowerCase() ===
"true"; 'true';
state.profile.allowTweetVideo = state.profile.allowTweetVideo =
import.meta.env.VITE_ALLOW_TWEET_VIDEO.toLowerCase() === "true"; import.meta.env.VITE_ALLOW_TWEET_VIDEO.toLowerCase() === 'true';
state.profile.allowUserRegister = state.profile.allowUserRegister =
import.meta.env.VITE_ALLOW_USER_REGISTER.toLowerCase() === "true"; import.meta.env.VITE_ALLOW_USER_REGISTER.toLowerCase() === 'true';
state.profile.allowPhoneBind = state.profile.allowPhoneBind =
import.meta.env.VITE_ALLOW_PHONE_BIND.toLowerCase() === "true"; import.meta.env.VITE_ALLOW_PHONE_BIND.toLowerCase() === 'true';
state.profile.defaultTweetMaxLength = Number( state.profile.defaultTweetMaxLength = Number(
import.meta.env.VITE_DEFAULT_TWEET_MAX_LENGTH import.meta.env.VITE_DEFAULT_TWEET_MAX_LENGTH,
); );
state.profile.tweetWebEllipsisSize = Number( state.profile.tweetWebEllipsisSize = Number(
import.meta.env.VITE_TWEET_WEB_ELLIPSIS_SIZE import.meta.env.VITE_TWEET_WEB_ELLIPSIS_SIZE,
); );
state.profile.tweetMobileEllipsisSize = Number( state.profile.tweetMobileEllipsisSize = Number(
import.meta.env.VITE_TWEET_MOBILE_ELLIPSIS_SIZE import.meta.env.VITE_TWEET_MOBILE_ELLIPSIS_SIZE,
); );
state.profile.defaultTweetVisibility = state.profile.defaultTweetVisibility =
import.meta.env.VITE_DEFAULT_TWEET_VISIBILITY.toLowerCase(); import.meta.env.VITE_DEFAULT_TWEET_VISIBILITY.toLowerCase();
state.profile.defaultMsgLoopInterval = Number( state.profile.defaultMsgLoopInterval = Number(
import.meta.env.VITE_DEFAULT_MSG_LOOP_INTERVAL import.meta.env.VITE_DEFAULT_MSG_LOOP_INTERVAL,
); );
state.profile.copyrightTop = import.meta.env.VITE_COPYRIGHT_TOP; state.profile.copyrightTop = import.meta.env.VITE_COPYRIGHT_TOP;
@ -182,11 +182,11 @@ export default createStore({
data.copyright_right_link ?? p.copyrightRightLink; data.copyright_right_link ?? p.copyrightRightLink;
}, },
userLogout(state) { userLogout(state) {
localStorage.removeItem("PAOPAO_TOKEN"); localStorage.removeItem('PAOPAO_TOKEN');
state.userInfo = { state.userInfo = {
id: 0, id: 0,
nickname: "", nickname: '',
username: "", username: '',
created_on: 0, created_on: 0,
follows: 0, follows: 0,
followings: 0, followings: 0,

@ -41,7 +41,7 @@ declare module Item {
/** 评论者UID */ /** 评论者UID */
user_id: number; user_id: number;
/** 类别:1为标题,2为文字段落,3为图片地址,4为视频地址,5为语音地址,6为链接地址 */ /** 类别:1为标题,2为文字段落,3为图片地址,4为视频地址,5为语音地址,6为链接地址 */
type: import("@/utils/IEnum").CommentItemTypeEnum; type: import('@/utils/IEnum').CommentItemTypeEnum;
/** 内容 */ /** 内容 */
content: string; content: string;
/** 排序,越小越靠前 */ /** 排序,越小越靠前 */
@ -73,13 +73,13 @@ declare module Item {
/** 评论者城市地址 */ /** 评论者城市地址 */
ip_loc: string; ip_loc: string;
/** 是否精选 */ /** 是否精选 */
is_essence: import("@/utils/IEnum").YesNoEnum; is_essence: import('@/utils/IEnum').YesNoEnum;
/** 点赞数 */ /** 点赞数 */
thumbs_up_count: number; thumbs_up_count: number;
/** 是否点赞,0为未点赞,1为已点赞 */ /** 是否点赞,0为未点赞,1为已点赞 */
is_thumbs_up: import("@/utils/IEnum").YesNoEnum; is_thumbs_up: import('@/utils/IEnum').YesNoEnum;
/** 是否反对,0为未反对,1为已反对 */ /** 是否反对,0为未反对,1为已反对 */
is_thumbs_down: import("@/utils/IEnum").YesNoEnum; is_thumbs_down: import('@/utils/IEnum').YesNoEnum;
/** 创建时间 */ /** 创建时间 */
created_on: number; created_on: number;
/** 修改时间 */ /** 修改时间 */
@ -120,9 +120,9 @@ declare module Item {
/** 点赞数 */ /** 点赞数 */
thumbs_up_count: number; thumbs_up_count: number;
/** 是否点赞,0为未点赞,1为已点赞 */ /** 是否点赞,0为未点赞,1为已点赞 */
is_thumbs_up: import("@/utils/IEnum").YesNoEnum; is_thumbs_up: import('@/utils/IEnum').YesNoEnum;
/** 是否反对,0为未反对,1为已反对 */ /** 是否反对,0为未反对,1为已反对 */
is_thumbs_down: import("@/utils/IEnum").YesNoEnum; is_thumbs_down: import('@/utils/IEnum').YesNoEnum;
/** 创建时间 */ /** 创建时间 */
created_on: number; created_on: number;
/** 修改时间 */ /** 修改时间 */
@ -165,7 +165,7 @@ declare module Item {
/** 内容ID */ /** 内容ID */
id: number; id: number;
/** 类型:1为标题,2为文字段落,3为图片地址,4为视频地址,5为语音地址,6为链接地址,7为附件资源,8为收费资源 */ /** 类型:1为标题,2为文字段落,3为图片地址,4为视频地址,5为语音地址,6为链接地址,7为附件资源,8为收费资源 */
type: import("@/utils/IEnum").PostItemTypeEnum; type: import('@/utils/IEnum').PostItemTypeEnum;
/** POST ID */ /** POST ID */
post_id: number; post_id: number;
/** 内容 */ /** 内容 */
@ -218,7 +218,7 @@ declare module Item {
/** 标签列表 */ /** 标签列表 */
tags: { [key: string]: number } | string; tags: { [key: string]: number } | string;
/** 可见性:0为公开,1为私密,2为好友可见 */ /** 可见性:0为公开,1为私密,2为好友可见 */
visibility: import("@/utils/IEnum").VisibilityEnum; visibility: import('@/utils/IEnum').VisibilityEnum;
/** 是否锁定 */ /** 是否锁定 */
is_lock: number; is_lock: number;
/** 是否置顶 */ /** 是否置顶 */
@ -248,7 +248,7 @@ declare module Item {
interface MessageProps { interface MessageProps {
id: number; id: number;
/** 类型:1为动态,2为评论,3为回复,4为私信,5为好友申请, 99为系统通知 */ /** 类型:1为动态,2为评论,3为回复,4为私信,5为好友申请, 99为系统通知 */
type: import("@/utils/IEnum").MessageTypeEnum; type: import('@/utils/IEnum').MessageTypeEnum;
/** 摘要说明 */ /** 摘要说明 */
brief: string; brief: string;
/** 详细内容 */ /** 详细内容 */
@ -302,7 +302,7 @@ declare module Item {
interface AttachmentProps { interface AttachmentProps {
id: number; id: number;
/** 类别:1为图片,2为视频,3为其他附件 */ /** 类别:1为图片,2为视频,3为其他附件 */
type: import("@/utils/IEnum").AttachmentTypeEnum; type: import('@/utils/IEnum').AttachmentTypeEnum;
/** 发布者用户UID */ /** 发布者用户UID */
user_id: number; user_id: number;
/** 发布者用户数据 */ /** 发布者用户数据 */

@ -42,7 +42,7 @@ declare module NetParams {
} }
interface UserGetMessages { interface UserGetMessages {
style: "all" | "system" | "whisper" | "requesting" | "unread"; style: 'all' | 'system' | 'whisper' | 'requesting' | 'unread';
page: number; page: number;
page_size: number; page_size: number;
} }
@ -162,7 +162,7 @@ declare module NetParams {
interface PostGetPosts { interface PostGetPosts {
query: string | null; query: string | null;
type: string; type: string;
style: "newest" | "hots" | "following" | "search"; style: 'newest' | 'hots' | 'following' | 'search';
page: number; page: number;
page_size: number; page_size: number;
} }
@ -182,7 +182,7 @@ declare module NetParams {
interface PostVisibilityPost { interface PostVisibilityPost {
id: number; id: number;
/** 可见性:0为公开,1为私密,2为好友可见 */ /** 可见性:0为公开,1为私密,2为好友可见 */
visibility: import("@/utils/IEnum").VisibilityEnum; visibility: import('@/utils/IEnum').VisibilityEnum;
} }
interface PostGetPostStar { interface PostGetPostStar {
@ -202,14 +202,14 @@ declare module NetParams {
} }
interface PostGetTags { interface PostGetTags {
type: "hot" | "new" | "follow" | "pin" | "hot_extral"; type: 'hot' | 'new' | 'follow' | 'pin' | 'hot_extral';
num: number; num: number;
extral_num?: number; extral_num?: number;
} }
interface PostGetPostComments { interface PostGetPostComments {
id: number; id: number;
style: "default" | "hots" | "newest"; style: 'default' | 'hots' | 'newest';
page?: number; page?: number;
page_size?: number; page_size?: number;
} }
@ -226,7 +226,7 @@ declare module NetParams {
/** 附件价格 */ /** 附件价格 */
attachment_price: number; attachment_price: number;
/** 可见性:0为公开,1为私密,2为好友可见 */ /** 可见性:0为公开,1为私密,2为好友可见 */
visibility: import("@/utils/IEnum").VisibilityEnum; visibility: import('@/utils/IEnum').VisibilityEnum;
} }
interface PostDeletePost { interface PostDeletePost {

@ -135,7 +135,7 @@ declare module NetReq {
interface PostVisibilityPost { interface PostVisibilityPost {
/** 可见性:0为公开,1为私密,2为好友可见 */ /** 可见性:0为公开,1为私密,2为好友可见 */
visibility_status: import("@/utils/IEnum").VisibilityEnum; visibility_status: import('@/utils/IEnum').VisibilityEnum;
} }
interface PostGetPostStar { interface PostGetPostStar {
@ -179,7 +179,7 @@ declare module NetReq {
interface PostDeleteComment {} interface PostDeleteComment {}
interface PostHighlightComment { interface PostHighlightComment {
highlight_status: import("@/utils/IEnum").YesNoEnum; highlight_status: import('@/utils/IEnum').YesNoEnum;
} }
type PostCreateCommentReply = Item.ReplyProps; type PostCreateCommentReply = Item.ReplyProps;

@ -4,8 +4,8 @@ export const parsePostTag = (content: string) => {
var tagExp = /(#|#)([^#@\s])+?\s+?/g; // 这⾥中⽂#和英⽂#都会识别 var tagExp = /(#|#)([^#@\s])+?\s+?/g; // 这⾥中⽂#和英⽂#都会识别
var atExp = /@([a-zA-Z0-9])+?\s+?/g; // 这⾥中⽂#和英⽂#都会识别 var atExp = /@([a-zA-Z0-9])+?\s+?/g; // 这⾥中⽂#和英⽂#都会识别
content = content content = content
.replace(/<[^>]*?>/gi, "") .replace(/<[^>]*?>/gi, '')
.replace(/(.*?)<\/[^>]*?>/gi, "") .replace(/(.*?)<\/[^>]*?>/gi, '')
.replace(tagExp, (item) => { .replace(tagExp, (item) => {
tags.push(item.substr(1).trim()); tags.push(item.substr(1).trim());
return ( return (
@ -13,7 +13,7 @@ export const parsePostTag = (content: string) => {
encodeURIComponent(item.substr(1).trim()) + encodeURIComponent(item.substr(1).trim()) +
'">' + '">' +
item.trim() + item.trim() +
"</a> " '</a> '
); );
}) })
.replace(atExp, (item) => { .replace(atExp, (item) => {
@ -23,7 +23,7 @@ export const parsePostTag = (content: string) => {
encodeURIComponent(item.substr(1).trim()) + encodeURIComponent(item.substr(1).trim()) +
'">' + '">' +
item.trim() + item.trim() +
"</a> " '</a> '
); );
}); });
return { content, tags, users }; return { content, tags, users };
@ -34,28 +34,28 @@ export const preparePost = (
foldHint: string, foldHint: string,
unfoldHint: string, unfoldHint: string,
maxSize: number, maxSize: number,
isFold: boolean = true isFold: boolean = true,
) => { ) => {
const isEllipsis = content.length > maxSize; const isEllipsis = content.length > maxSize;
if (isFold && isEllipsis) { if (isFold && isEllipsis) {
content = content.substring(0, maxSize); content = content.substring(0, maxSize);
let latestChar = content.charAt(maxSize - 1); let latestChar = content.charAt(maxSize - 1);
if (latestChar == "#" || latestChar == "#" || latestChar == "@") { if (latestChar == '#' || latestChar == '#' || latestChar == '@') {
content = content.substring(0, maxSize - 1); content = content.substring(0, maxSize - 1);
} }
} }
const tagExp = /(#|#)([^#@\s])+?\s+?/g; // 这⾥中⽂#和英⽂#都会识别 const tagExp = /(#|#)([^#@\s])+?\s+?/g; // 这⾥中⽂#和英⽂#都会识别
const 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, '')
.replace(tagExp, (item) => { .replace(tagExp, (item) => {
return ( return (
'<a class="hash-link" data-detail="tag:' + '<a class="hash-link" data-detail="tag:' +
encodeURIComponent(item.substring(1).trim()) + encodeURIComponent(item.substring(1).trim()) +
'">' + '">' +
item.trim() + item.trim() +
"</a> " '</a> '
); );
}) })
.replace(atExp, (item) => { .replace(atExp, (item) => {
@ -64,16 +64,16 @@ export const preparePost = (
encodeURIComponent(item.substring(1).trim()) + encodeURIComponent(item.substring(1).trim()) +
'">' + '">' +
item.trim() + item.trim() +
"</a> " '</a> '
); );
}); });
if (isEllipsis) { if (isEllipsis) {
content = content =
content.trimEnd() + content.trimEnd() +
(isFold ? "...&nbsp;" : "&nbsp;") + (isFold ? '...&nbsp;' : '&nbsp;') +
'<a class="hash-link" data-detail="post">' + '<a class="hash-link" data-detail="post">' +
(isFold ? foldHint : unfoldHint) + (isFold ? foldHint : unfoldHint) +
"</a> "; '</a> ';
} }
return content; return content;
}; };

@ -1,8 +1,8 @@
export const prettyQuoteNum = (num: number) => { export const prettyQuoteNum = (num: number) => {
if (num >= 1000) { if (num >= 1000) {
return (num / 1000).toFixed(1) + "千"; return (num / 1000).toFixed(1) + '千';
} else if (num >= 10000) { } else if (num >= 10000) {
return (num / 10000).toFixed(1) + "万"; return (num / 10000).toFixed(1) + '万';
} }
return num; return num;
}; };

@ -2,12 +2,12 @@
* @file 格式化日期 * @file 格式化日期
*/ */
import moment from "moment"; import moment from 'moment';
import "moment/dist/locale/zh-cn"; import 'moment/dist/locale/zh-cn';
moment.locale("zh-cn"); moment.locale('zh-cn');
export const formatTime = (time: number) => { export const formatTime = (time: number) => {
return moment.unix(time).utc(true).format("YYYY-MM-DD HH:mm"); return moment.unix(time).utc(true).format('YYYY-MM-DD HH:mm');
}; };
export const formatHumanTime = (time: number) => { export const formatHumanTime = (time: number) => {
@ -22,9 +22,9 @@ export const formatPrettyTime = (time: number) => {
let mt = moment.unix(time); let mt = moment.unix(time);
let now = moment(); let now = moment();
if (mt.year() != now.year()) { if (mt.year() != now.year()) {
return mt.utc(true).format("YYYY-MM-DD HH:mm"); return mt.utc(true).format('YYYY-MM-DD HH:mm');
} else if (moment().diff(mt, "month") > 3) { } else if (moment().diff(mt, 'month') > 3) {
return mt.utc(true).format("MM-DD HH:mm"); return mt.utc(true).format('MM-DD HH:mm');
} }
return mt.fromNow(); return mt.fromNow();
}; };
@ -33,13 +33,13 @@ export const formatPrettyDate = (time: number) => {
let mt = moment.unix(time); let mt = moment.unix(time);
let now = moment(); let now = moment();
if (mt.year() != now.year()) { if (mt.year() != now.year()) {
return mt.utc(true).format("YYYY-MM-DD"); return mt.utc(true).format('YYYY-MM-DD');
} else if (moment().diff(mt, "month") > 3) { } else if (moment().diff(mt, 'month') > 3) {
return mt.utc(true).format("MM-DD"); return mt.utc(true).format('MM-DD');
} }
return mt.fromNow(); return mt.fromNow();
}; };
export const formatDate = (time: number) => { export const formatDate = (time: number) => {
return moment.unix(time).utc(true).format("YYYY年MM月"); return moment.unix(time).utc(true).format('YYYY年MM月');
}; };

@ -1,9 +1,13 @@
export const isZipFile = (file: File): Promise<unknown> => { export const isZipFile = (file: File): Promise<unknown> => {
const fileReader = new FileReader(); const fileReader = new FileReader();
const isValidZipFileType = (fileType: string): boolean => { const isValidZipFileType = (fileType: string): boolean => {
const zipFileTypes = ['application/zip', 'application/x-zip', 'application/octet-stream', 'application/x-zip-compressed']; const zipFileTypes = [
'application/zip',
'application/x-zip',
'application/octet-stream',
'application/x-zip-compressed',
];
return zipFileTypes.includes(fileType); return zipFileTypes.includes(fileType);
}; };
@ -44,4 +48,4 @@ export const isZipFile = (file: File): Promise<unknown> => {
fileReader.readAsArrayBuffer(file.slice(0, 4)); fileReader.readAsArrayBuffer(file.slice(0, 4));
}); });
} };

@ -6,21 +6,22 @@ const service = axios.create({
}); });
service.interceptors.request.use( service.interceptors.request.use(
config => { (config) => {
// 鉴权Header // 鉴权Header
if (localStorage.getItem('PAOPAO_TOKEN')) { if (localStorage.getItem('PAOPAO_TOKEN')) {
(config.headers as any)['Authorization'] = 'Bearer ' + localStorage.getItem('PAOPAO_TOKEN'); (config.headers as any)['Authorization'] =
'Bearer ' + localStorage.getItem('PAOPAO_TOKEN');
} }
return config; return config;
}, },
error => { (error) => {
return Promise.reject(error); return Promise.reject(error);
} },
); );
service.interceptors.response.use( service.interceptors.response.use(
response => { (response) => {
const { data = {}, code = 0 } = response?.data || {}; const { data = {}, code = 0 } = response?.data || {};
if (+code === 0) { if (+code === 0) {
return data || {}; return data || {};
@ -44,7 +45,7 @@ service.interceptors.response.use(
window.$message.error(response?.data?.msg || '请求失败'); window.$message.error(response?.data?.msg || '请求失败');
} }
return Promise.reject(response?.data || {}); return Promise.reject(response?.data || {});
} },
); );
export default service; export default service;

@ -4,13 +4,12 @@ export const scrollToTop = (scrollDuration: number) => {
var scrollCount = 0; var scrollCount = 0;
var oldTimestamp = performance.now(); var oldTimestamp = performance.now();
function step(newTimestamp: number) { function step(newTimestamp: number) {
scrollCount += scrollCount += Math.PI / (scrollDuration / (newTimestamp - oldTimestamp));
Math.PI / (scrollDuration / (newTimestamp - oldTimestamp));
if (scrollCount >= Math.PI) window.scrollTo(0, 0); if (scrollCount >= Math.PI) window.scrollTo(0, 0);
if (window.scrollY === 0) return; if (window.scrollY === 0) return;
window.scrollTo( window.scrollTo(
0, 0,
Math.round(cosParameter + cosParameter * Math.cos(scrollCount)) Math.round(cosParameter + cosParameter * Math.cos(scrollCount)),
); );
oldTimestamp = newTimestamp; oldTimestamp = newTimestamp;
window.requestAnimationFrame(step); window.requestAnimationFrame(step);

@ -51,7 +51,7 @@ import { ref, onMounted } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { useDialog } from 'naive-ui'; import { useDialog } from 'naive-ui';
import InfiniteLoading from "v3-infinite-loading"; import InfiniteLoading from 'v3-infinite-loading';
import { getCollections, followUser, unfollowUser } from '@/api/user'; import { getCollections, followUser, unfollowUser } from '@/api/user';
const store = useStore(); const store = useStore();
@ -99,7 +99,8 @@ const onHandleFollowAction = (post: Item.PostProps) => {
if (post.user.is_following) { if (post.user.is_following) {
unfollowUser({ unfollowUser({
user_id: post.user.id, user_id: post.user.id,
}).then((_res) => { })
.then((_res) => {
window.$message.success('操作成功'); window.$message.success('操作成功');
postFollowAction(post.user_id, false); postFollowAction(post.user_id, false);
}) })
@ -107,7 +108,8 @@ const onHandleFollowAction = (post: Item.PostProps) => {
} else { } else {
followUser({ followUser({
user_id: post.user.id, user_id: post.user.id,
}).then((_res) => { })
.then((_res) => {
window.$message.success('关注成功'); window.$message.success('关注成功');
postFollowAction(post.user_id, true); postFollowAction(post.user_id, true);
}) })
@ -130,10 +132,11 @@ const loadPosts = () => {
getCollections({ getCollections({
page: page.value, page: page.value,
page_size: pageSize.value, page_size: pageSize.value,
}).then((res) => { })
.then((res) => {
loading.value = false; loading.value = false;
if (res.list.length === 0) { if (res.list.length === 0) {
noMore.value = true noMore.value = true;
} }
if (page.value > 1) { if (page.value > 1) {
list.value = list.value.concat(res.list); list.value = list.value.concat(res.list);
@ -146,7 +149,7 @@ const loadPosts = () => {
.catch((_err) => { .catch((_err) => {
loading.value = false; loading.value = false;
if (page.value > 1) { if (page.value > 1) {
page.value-- page.value--;
} }
}); });
}; };

@ -34,7 +34,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted } from 'vue'; import { ref, onMounted } from 'vue';
import { getContacts } from '@/api/post'; import { getContacts } from '@/api/post';
import InfiniteLoading from "v3-infinite-loading"; import InfiniteLoading from 'v3-infinite-loading';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
const route = useRoute(); const route = useRoute();
@ -79,7 +79,7 @@ const nextPage = () => {
}; };
onMounted(() => { onMounted(() => {
loadContacts() loadContacts();
}); });
const loadContacts = (scrollToBottom: boolean = false) => { const loadContacts = (scrollToBottom: boolean = false) => {
@ -89,10 +89,11 @@ const loadContacts = (scrollToBottom: boolean = false) => {
getContacts({ getContacts({
page: page.value, page: page.value,
page_size: pageSize.value, page_size: pageSize.value,
}).then((res) => { })
.then((res) => {
loading.value = false; loading.value = false;
if (res.list.length === 0) { if (res.list.length === 0) {
noMore.value = true noMore.value = true;
} }
if (page.value > 1) { if (page.value > 1) {
list.value = list.value.concat(res.list); list.value = list.value.concat(res.list);
@ -112,7 +113,7 @@ const loadContacts = (scrollToBottom: boolean = false) => {
page.value--; page.value--;
} }
}); });
} };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

@ -38,16 +38,16 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, computed } from 'vue'; import { ref, onMounted, computed } from 'vue';
import { getUserFollows, getUserFollowings } from '@/api/user'; import { getUserFollows, getUserFollowings } from '@/api/user';
import InfiniteLoading from "v3-infinite-loading"; import InfiniteLoading from 'v3-infinite-loading';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
const route = useRoute(); const route = useRoute();
const loading = ref(false); const loading = ref(false);
const noMore = ref(false); const noMore = ref(false);
const list = ref<Item.ContactItemProps[]>([]); const list = ref<Item.ContactItemProps[]>([]);
const nickname= route.query.n as string || "粉丝详情"; const nickname = (route.query.n as string) || '粉丝详情';
const username = route.query.s as string || ""; const username = (route.query.s as string) || '';
const tabler = ref(route.query.t as string || "follows") const tabler = ref((route.query.t as string) || 'follows');
const page = ref(+(route.query.p as string) || 1); const page = ref(+(route.query.p as string) || 1);
const pageSize = ref(20); const pageSize = ref(20);
const totalPage = ref(0); const totalPage = ref(0);
@ -66,7 +66,7 @@ const whisperReceiver = ref<Item.UserInfo>({
status: 1, status: 1,
}); });
function resetPage(tab: "follows" | "followings") { function resetPage(tab: 'follows' | 'followings') {
list.value = []; list.value = [];
loading.value = false; loading.value = false;
noMore.value = false; noMore.value = false;
@ -76,10 +76,10 @@ function resetPage(tab: "follows" | "followings") {
} }
const completeStr = computed(() => { const completeStr = computed(() => {
if (tabler.value == "follows") { if (tabler.value == 'follows') {
return '没有更多关注了' return '没有更多关注了';
} else { } else {
return '没有更多粉丝了' return '没有更多粉丝了';
} }
}); });
@ -102,18 +102,18 @@ const nextPage = () => {
} }
}; };
const changeTab = (tab: "follows" | "followings") => { const changeTab = (tab: 'follows' | 'followings') => {
resetPage(tab); resetPage(tab);
loadPage(); loadPage();
}; };
const loadPage = () => { const loadPage = () => {
if (tabler.value === "follows") { if (tabler.value === 'follows') {
loadFollows(username); loadFollows(username);
} else if (tabler.value === "followings") { } else if (tabler.value === 'followings') {
loadFollowings(username); loadFollowings(username);
} }
} };
const loadFollows = (username: string, scrollToBottom: boolean = false) => { const loadFollows = (username: string, scrollToBottom: boolean = false) => {
if (list.value.length === 0) { if (list.value.length === 0) {
@ -123,10 +123,11 @@ const loadFollows = (username: string, scrollToBottom: boolean = false) => {
username: username, username: username,
page: page.value, page: page.value,
page_size: pageSize.value, page_size: pageSize.value,
}).then((res) => { })
.then((res) => {
loading.value = false; loading.value = false;
if (res.list.length === 0) { if (res.list.length === 0) {
noMore.value = true noMore.value = true;
} }
if (page.value > 1) { if (page.value > 1) {
list.value = list.value.concat(res.list); list.value = list.value.concat(res.list);
@ -156,10 +157,11 @@ const loadFollowings = (username: string, scrollToBottom: boolean = false) => {
username: username, username: username,
page: page.value, page: page.value,
page_size: pageSize.value, page_size: pageSize.value,
}).then((res) => { })
.then((res) => {
loading.value = false; loading.value = false;
if (res.list.length === 0) { if (res.list.length === 0) {
noMore.value = true noMore.value = true;
} }
if (page.value > 1) { if (page.value > 1) {
list.value = list.value.concat(res.list); list.value = list.value.concat(res.list);

@ -104,9 +104,14 @@ import { ref, onMounted, reactive, computed, watch } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { useRoute, useRouter } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
import { useDialog } from 'naive-ui'; import { useDialog } from 'naive-ui';
import InfiniteLoading from "v3-infinite-loading"; import InfiniteLoading from 'v3-infinite-loading';
import { getPosts, getIndexTrends } from '@/api/post'; import { getPosts, getIndexTrends } from '@/api/post';
import { getUserPosts, deleteFriend, followUser, unfollowUser } from '@/api/user'; import {
getUserPosts,
deleteFriend,
followUser,
unfollowUser,
} from '@/api/user';
import SlideBar from '@opentiny/vue-slide-bar'; import SlideBar from '@opentiny/vue-slide-bar';
import allTweets from '@/assets/img/fresh-tweets.png'; import allTweets from '@/assets/img/fresh-tweets.png';
import discoverTweets from '@/assets/img/discover-tweets.jpeg'; import discoverTweets from '@/assets/img/discover-tweets.jpeg';
@ -117,26 +122,38 @@ const route = useRoute();
const router = useRouter(); const router = useRouter();
const dialog = useDialog(); const dialog = useDialog();
const newestTweetsStyle = ref<'newest' | 'hots' | 'following'>('newest') const newestTweetsStyle = ref<'newest' | 'hots' | 'following'>('newest');
const onNewestTweets = () => { const onNewestTweets = () => {
newestTweetsStyle.value='newest' newestTweetsStyle.value = 'newest';
handleBarClick(slideBarList.value[0], 0) handleBarClick(slideBarList.value[0], 0);
}; };
const onHotTweets = () => { const onHotTweets = () => {
newestTweetsStyle.value='hots' newestTweetsStyle.value = 'hots';
handleBarClick(slideBarList.value[1], 1) handleBarClick(slideBarList.value[1], 1);
}; };
const onFollowingTweets = () => { const onFollowingTweets = () => {
newestTweetsStyle.value='following' newestTweetsStyle.value = 'following';
handleBarClick(slideBarList.value[2], 2) handleBarClick(slideBarList.value[2], 2);
}; };
const initBlocks = ref(9) const initBlocks = ref(9);
const wheelBlocks = ref(8) const wheelBlocks = ref(8);
const slideBarList = ref<Item.SlideBarItem[]>([ const slideBarList = ref<Item.SlideBarItem[]>([
{ title: '最新动态', style: 1, username: '', avatar: allTweets, show: true }, { title: '最新动态', style: 1, username: '', avatar: allTweets, show: true },
{ title: '热门推荐', style: 2, username: '', avatar: discoverTweets, show: false }, {
{ title: '正在关注', style: 3, username: '', avatar: followingTweets, show: false }, title: '热门推荐',
style: 2,
username: '',
avatar: discoverTweets,
show: false,
},
{
title: '正在关注',
style: 3,
username: '',
avatar: followingTweets,
show: false,
},
// TODO: 不知道SlideBar抽什么疯,如果没有填充下面这些伪数据的话,直接设置initBlocks为9而给的数据又不足,后面动态添加数据后,吖的竟然不能后划了, // TODO: 不知道SlideBar抽什么疯,如果没有填充下面这些伪数据的话,直接设置initBlocks为9而给的数据又不足,后面动态添加数据后,吖的竟然不能后划了,
// f*k,不知道哪姿势不对,总之先凑合着用吧,后期再优化。 // f*k,不知道哪姿势不对,总之先凑合着用吧,后期再优化。
{ title: '', style: 1, username: '', avatar: '', show: true }, { title: '', style: 1, username: '', avatar: '', show: true },
@ -147,7 +164,7 @@ const slideBarList = ref<Item.SlideBarItem[]>([
{ title: '', style: 1, username: '', avatar: '', show: true }, { title: '', style: 1, username: '', avatar: '', show: true },
{ title: '', style: 1, username: '', avatar: '', show: true }, { title: '', style: 1, username: '', avatar: '', show: true },
{ title: '', style: 1, username: '', avatar: '', show: true }, { title: '', style: 1, username: '', avatar: '', show: true },
{ title: '', style: 1, username: '', avatar: '', show: true } { title: '', style: 1, username: '', avatar: '', show: true },
]); ]);
const user = reactive<Item.UserInfo>({ const user = reactive<Item.UserInfo>({
id: 0, id: 0,
@ -162,13 +179,13 @@ const user = reactive<Item.UserInfo>({
followings: 0, followings: 0,
status: 1, status: 1,
}); });
const inActionPost = ref<Item.PostProps | null>(null) const inActionPost = ref<Item.PostProps | null>(null);
const title = ref<string>("泡泡广场") const title = ref<string>('泡泡广场');
const loading = ref(false); const loading = ref(false);
const noMore = ref(false); const noMore = ref(false);
const targetStyle = ref<number>(1) const targetStyle = ref<number>(1);
const targetUsername = ref<string>("") const targetUsername = ref<string>('');
const list = ref<any[]>([]); const list = ref<any[]>([]);
const page = ref(1); const page = ref(1);
const pageSize = ref(20); const pageSize = ref(20);
@ -205,13 +222,17 @@ const openAddFriendWhisper = () => {
const openDeleteFriend = (post: Item.PostProps) => { const openDeleteFriend = (post: Item.PostProps) => {
dialog.warning({ dialog.warning({
title: '删除好友', title: '删除好友',
content: '将好友 “' + post.user.nickname + '” 删除,将同时删除 点赞/收藏 列表中关于该朋友的 “好友可见” 推文', content:
'将好友 “' +
post.user.nickname +
'” 删除,将同时删除 点赞/收藏 列表中关于该朋友的 “好友可见” 推文',
positiveText: '确定', positiveText: '确定',
negativeText: '取消', negativeText: '取消',
onPositiveClick: () => { onPositiveClick: () => {
deleteFriend({ deleteFriend({
user_id: user.id, user_id: user.id,
}).then((res) => { })
.then((res) => {
window.$message.success('操作成功'); window.$message.success('操作成功');
post.user.is_friend = false; post.user.is_friend = false;
}) })
@ -241,14 +262,18 @@ const onHandleFollowAction = (post: Item.PostProps) => {
dialog.success({ dialog.success({
title: '提示', title: '提示',
content: content:
'确定' + (post.user.is_following ? '取消关注 @' : '关注 @') + post.user.username + ' 吗?', '确定' +
(post.user.is_following ? '取消关注 @' : '关注 @') +
post.user.username +
' 吗?',
positiveText: '确定', positiveText: '确定',
negativeText: '取消', negativeText: '取消',
onPositiveClick: () => { onPositiveClick: () => {
if (post.user.is_following) { if (post.user.is_following) {
unfollowUser({ unfollowUser({
user_id: post.user.id, user_id: post.user.id,
}).then((_res) => { })
.then((_res) => {
window.$message.success('操作成功'); window.$message.success('操作成功');
postFollowAction(post.user_id, false); postFollowAction(post.user_id, false);
}) })
@ -256,7 +281,8 @@ const onHandleFollowAction = (post: Item.PostProps) => {
} else { } else {
followUser({ followUser({
user_id: post.user.id, user_id: post.user.id,
}).then((_res) => { })
.then((_res) => {
window.$message.success('关注成功'); window.$message.success('关注成功');
postFollowAction(post.user_id, true); postFollowAction(post.user_id, true);
}) })
@ -286,10 +312,19 @@ const updateTitle = () => {
}; };
const showTrendsTag = computed(() => { const showTrendsTag = computed(() => {
return store.state.userInfo.id > 0 && !store.state.profile.enableTrendsBar && store.state.desktopModelShow return (
}) store.state.userInfo.id > 0 &&
!store.state.profile.enableTrendsBar &&
store.state.desktopModelShow
);
});
const showTrendsBar = computed(() => { const showTrendsBar = computed(() => {
return store.state.profile.useFriendship && store.state.profile.enableTrendsBar && store.state.desktopModelShow && store.state.userInfo.id > 0; return (
store.state.profile.useFriendship &&
store.state.profile.enableTrendsBar &&
store.state.desktopModelShow &&
store.state.userInfo.id > 0
);
}); });
const reset = () => { const reset = () => {
@ -298,25 +333,25 @@ const reset = () => {
list.value = []; list.value = [];
page.value = 1; page.value = 1;
totalPage.value = 0; totalPage.value = 0;
} };
const handleBarClick = (data: Item.SlideBarItem, index: number) => { const handleBarClick = (data: Item.SlideBarItem, index: number) => {
reset(); reset();
targetStyle.value = data.style targetStyle.value = data.style;
if (route.query.q) { if (route.query.q) {
route.query.q = null; route.query.q = null;
updateTitle(); updateTitle();
} }
switch (data.style) { switch (data.style) {
case 1: case 1:
loadPosts("newest"); loadPosts('newest');
break; break;
case 2: case 2:
loadPosts("hots"); loadPosts('hots');
break; break;
case 3: case 3:
route.query.q=null route.query.q = null;
loadPosts("following"); loadPosts('following');
break; break;
case 21: case 21:
targetUsername.value = data.username; targetUsername.value = data.username;
@ -329,17 +364,22 @@ const handleBarClick = (data: Item.SlideBarItem, index: number) => {
}; };
const loadContacts = () => { const loadContacts = () => {
slideBarList.value = slideBarList.value.slice(0, 3) slideBarList.value = slideBarList.value.slice(0, 3);
if (!store.state.profile.useFriendship || !store.state.profile.enableTrendsBar || store.state.userInfo.id === 0) { if (
return !store.state.profile.useFriendship ||
!store.state.profile.enableTrendsBar ||
store.state.userInfo.id === 0
) {
return;
} }
getIndexTrends({ getIndexTrends({
page: 1, page: 1,
page_size: 50, page_size: 50,
}).then((res) => { })
.then((res) => {
var i = 0; var i = 0;
const list = res.list || [] const list = res.list || [];
let barItems: Item.SlideBarItem[] = [] let barItems: Item.SlideBarItem[] = [];
for (; i < list.length; i++) { for (; i < list.length; i++) {
let item: Item.IndexTrendsItem = list[i]; let item: Item.IndexTrendsItem = list[i];
barItems.push({ barItems.push({
@ -359,7 +399,7 @@ const loadContacts = () => {
}); });
}; };
const loadPosts = (style : "newest" | "hots" | "following" | "search") => { const loadPosts = (style: 'newest' | 'hots' | 'following' | 'search') => {
loading.value = true; loading.value = true;
getPosts({ getPosts({
query: route.query.q ? decodeURIComponent(route.query.q as string) : null, query: route.query.q ? decodeURIComponent(route.query.q as string) : null,
@ -371,7 +411,7 @@ const loadPosts = (style : "newest" | "hots" | "following" | "search") => {
.then((rsp) => { .then((rsp) => {
loading.value = false; loading.value = false;
if (rsp.list.length === 0) { if (rsp.list.length === 0) {
noMore.value = true noMore.value = true;
} }
if (page.value > 1) { if (page.value > 1) {
@ -386,7 +426,7 @@ const loadPosts = (style : "newest" | "hots" | "following" | "search") => {
.catch((err) => { .catch((err) => {
loading.value = false; loading.value = false;
if (page.value > 1) { if (page.value > 1) {
page.value-- page.value--;
} }
}); });
}; };
@ -395,14 +435,14 @@ const loadUserPosts = () => {
loading.value = true; loading.value = true;
getUserPosts({ getUserPosts({
username: targetUsername.value, username: targetUsername.value,
style: "post", style: 'post',
page: page.value, page: page.value,
page_size: pageSize.value, page_size: pageSize.value,
}) })
.then((rsp) => { .then((rsp) => {
loading.value = false; loading.value = false;
if (rsp.list.length === 0) { if (rsp.list.length === 0) {
noMore.value = true noMore.value = true;
} }
if (page.value > 1) { if (page.value > 1) {
list.value = list.value.concat(rsp.list); list.value = list.value.concat(rsp.list);
@ -464,17 +504,17 @@ const onPostSuccess = (post: Item.PostProps) => {
const loadMorePosts = () => { const loadMorePosts = () => {
switch (targetStyle.value) { switch (targetStyle.value) {
case 1: case 1:
loadPosts("newest"); loadPosts('newest');
break; break;
case 2: case 2:
loadPosts("hots"); loadPosts('hots');
break; break;
case 3: case 3:
loadPosts("following"); loadPosts('following');
break; break;
case 21: case 21:
if (route.query.q) { if (route.query.q) {
loadPosts("search"); loadPosts('search');
} else { } else {
loadUserPosts(); loadUserPosts();
} }
@ -496,8 +536,8 @@ const nextPage = () => {
onMounted(() => { onMounted(() => {
reset(); reset();
loadContacts() loadContacts();
loadPosts("newest"); loadPosts('newest');
}); });
watch( watch(
@ -511,7 +551,7 @@ watch(
if (to.refresh !== from.refresh) { if (to.refresh !== from.refresh) {
reset(); reset();
setTimeout(() => { setTimeout(() => {
loadContacts() loadContacts();
loadMorePosts(); loadMorePosts();
}, 0); }, 0);
return; return;
@ -519,13 +559,12 @@ watch(
if (from.path !== '/post' && to.path === '/') { if (from.path !== '/post' && to.path === '/') {
reset(); reset();
setTimeout(() => { setTimeout(() => {
loadContacts() loadContacts();
loadMorePosts(); loadMorePosts();
}, 0); }, 0);
} }
} },
); );
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

@ -65,11 +65,11 @@
<script setup lang="ts"> <script setup lang="ts">
import { h, ref, onMounted, computed } from 'vue'; import { h, ref, onMounted, computed } from 'vue';
import type { Component } from 'vue' import type { Component } from 'vue';
import { NIcon, DropdownOption } from 'naive-ui' import { NIcon, DropdownOption } from 'naive-ui';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import InfiniteLoading from "v3-infinite-loading"; import InfiniteLoading from 'v3-infinite-loading';
import { getMessages, readAllMessage } from '@/api/user'; import { getMessages, readAllMessage } from '@/api/user';
import { import {
LayersOutline as AllIcon, LayersOutline as AllIcon,
@ -78,7 +78,7 @@ import {
PersonAddOutline as RequestingIcon, PersonAddOutline as RequestingIcon,
ChatbubbleEllipsesOutline as UnreadIcon, ChatbubbleEllipsesOutline as UnreadIcon,
OptionsOutline as OptionsIcon, OptionsOutline as OptionsIcon,
} from '@vicons/ionicons5' } from '@vicons/ionicons5';
const store = useStore(); const store = useStore();
const route = useRoute(); const route = useRoute();
@ -88,8 +88,12 @@ const page = ref(+(route.query.p as string) || 1);
const pageSize = ref(20); const pageSize = ref(20);
const totalPage = ref(0); const totalPage = ref(0);
const list = ref<Item.MessageProps[]>([]); const list = ref<Item.MessageProps[]>([]);
const messageStyle = ref<'所有消息' | '系统消息' | '我的私信' | '好友申请' | '未读消息'>('所有消息') const messageStyle = ref<
const messageStyleVal = ref<'all' | 'system' | 'whisper' | 'requesting' | 'unread'>('all') '所有消息' | '系统消息' | '我的私信' | '好友申请' | '未读消息'
>('所有消息');
const messageStyleVal = ref<
'all' | 'system' | 'whisper' | 'requesting' | 'unread'
>('all');
const showWhisper = ref(false); const showWhisper = ref(false);
const whisperReceiver = ref<Item.UserInfo>({ const whisperReceiver = ref<Item.UserInfo>({
id: 0, id: 0,
@ -110,15 +114,15 @@ const reset = () => {
page.value = 1; page.value = 1;
totalPage.value = 0; totalPage.value = 0;
list.value = []; list.value = [];
} };
const renderIcon = (icon: Component) => { const renderIcon = (icon: Component) => {
return () => { return () => {
return h(NIcon, null, { return h(NIcon, null, {
default: () => h(icon) default: () => h(icon),
}) });
} };
} };
const options = computed(() => { const options = computed(() => {
let opts: DropdownOption[]; let opts: DropdownOption[];
@ -128,120 +132,120 @@ const options = computed(() => {
{ {
label: '系统消息', label: '系统消息',
key: 'system', key: 'system',
icon: renderIcon(SystemIcon) icon: renderIcon(SystemIcon),
}, },
{ {
label: '我的私信', label: '我的私信',
key: 'whisper', key: 'whisper',
icon: renderIcon(WhisperIcon) icon: renderIcon(WhisperIcon),
}, },
{ {
label: '好友申请', label: '好友申请',
key: 'requesting', key: 'requesting',
icon: renderIcon(RequestingIcon) icon: renderIcon(RequestingIcon),
}, },
{ {
label: '未读消息', label: '未读消息',
key: 'unread', key: 'unread',
icon: renderIcon(UnreadIcon) icon: renderIcon(UnreadIcon),
} },
] ];
break; break;
case '系统消息': case '系统消息':
opts = [ opts = [
{ {
label: '所有消息', label: '所有消息',
key: 'all', key: 'all',
icon: renderIcon(AllIcon) icon: renderIcon(AllIcon),
}, },
{ {
label: '我的私信', label: '我的私信',
key: 'whisper', key: 'whisper',
icon: renderIcon(WhisperIcon) icon: renderIcon(WhisperIcon),
}, },
{ {
label: '好友申请', label: '好友申请',
key: 'requesting', key: 'requesting',
icon: renderIcon(RequestingIcon) icon: renderIcon(RequestingIcon),
}, },
{ {
label: '未读消息', label: '未读消息',
key: 'unread', key: 'unread',
icon: renderIcon(UnreadIcon) icon: renderIcon(UnreadIcon),
} },
] ];
break; break;
case '我的私信': case '我的私信':
opts = [ opts = [
{ {
label: '所有消息', label: '所有消息',
key: 'all', key: 'all',
icon: renderIcon(AllIcon) icon: renderIcon(AllIcon),
}, },
{ {
label: '系统消息', label: '系统消息',
key: 'system', key: 'system',
icon: renderIcon(SystemIcon) icon: renderIcon(SystemIcon),
}, },
{ {
label: '好友申请', label: '好友申请',
key: 'requesting', key: 'requesting',
icon: renderIcon(RequestingIcon) icon: renderIcon(RequestingIcon),
}, },
{ {
label: '未读消息', label: '未读消息',
key: 'unread', key: 'unread',
icon: renderIcon(UnreadIcon) icon: renderIcon(UnreadIcon),
} },
] ];
break; break;
case '好友申请': case '好友申请':
opts = [ opts = [
{ {
label: '所有消息', label: '所有消息',
key: 'all', key: 'all',
icon: renderIcon(AllIcon) icon: renderIcon(AllIcon),
}, },
{ {
label: '系统消息', label: '系统消息',
key: 'system', key: 'system',
icon: renderIcon(SystemIcon) icon: renderIcon(SystemIcon),
}, },
{ {
label: '我的私信', label: '我的私信',
key: 'whisper', key: 'whisper',
icon: renderIcon(WhisperIcon) icon: renderIcon(WhisperIcon),
}, },
{ {
label: '未读消息', label: '未读消息',
key: 'unread', key: 'unread',
icon: renderIcon(UnreadIcon) icon: renderIcon(UnreadIcon),
} },
] ];
break; break;
case '未读消息': case '未读消息':
opts = [ opts = [
{ {
label: '所有消息', label: '所有消息',
key: 'all', key: 'all',
icon: renderIcon(AllIcon) icon: renderIcon(AllIcon),
}, },
{ {
label: '系统消息', label: '系统消息',
key: 'system', key: 'system',
icon: renderIcon(SystemIcon) icon: renderIcon(SystemIcon),
}, },
{ {
label: '我的私信', label: '我的私信',
key: 'whisper', key: 'whisper',
icon: renderIcon(WhisperIcon) icon: renderIcon(WhisperIcon),
}, },
{ {
label: '好友申请', label: '好友申请',
key: 'requesting', key: 'requesting',
icon: renderIcon(RequestingIcon) icon: renderIcon(RequestingIcon),
} },
] ];
break; break;
default: default:
opts = []; opts = [];
@ -251,7 +255,7 @@ const options = computed(() => {
}); });
const handleAction = ( const handleAction = (
item: 'all' | 'system' | 'whisper' | 'requesting' | 'unread' item: 'all' | 'system' | 'whisper' | 'requesting' | 'unread',
) => { ) => {
switch (item) { switch (item) {
case 'all': case 'all':
@ -270,32 +274,33 @@ const handleAction = (
messageStyle.value = '未读消息'; messageStyle.value = '未读消息';
break; break;
} }
messageStyleVal.value = item messageStyleVal.value = item;
reset(); reset();
loadMessages(); loadMessages();
}; };
const handleUnreadMessage = () => { const handleUnreadMessage = () => {
handleAction('unread') handleAction('unread');
} };
const handleReadAll = () => { const handleReadAll = () => {
if (store.state.unreadMsgCount > 0 && list.value.length > 0) { if (store.state.unreadMsgCount > 0 && list.value.length > 0) {
readAllMessage().then((_res) => { readAllMessage()
if (messageStyleVal.value != "unread") { .then((_res) => {
if (messageStyleVal.value != 'unread') {
for (let idx in list.value) { for (let idx in list.value) {
list.value[idx].is_read = 1; list.value[idx].is_read = 1;
} }
} else { } else {
list.value = []; list.value = [];
} }
store.commit("updateUnreadMsgCount", 0) store.commit('updateUnreadMsgCount', 0);
}) })
.catch((err) => { .catch((err) => {
console.log(err); console.log(err);
}); });
} }
} };
const onSendWhisper = (user: Item.UserInfo) => { const onSendWhisper = (user: Item.UserInfo) => {
whisperReceiver.value = user; whisperReceiver.value = user;
@ -317,10 +322,11 @@ const loadMessages = () => {
style: messageStyleVal.value, style: messageStyleVal.value,
page: page.value, page: page.value,
page_size: pageSize.value, page_size: pageSize.value,
}).then((res) => { })
.then((res) => {
loading.value = false; loading.value = false;
if (res.list.length === 0) { if (res.list.length === 0) {
noMore.value = true noMore.value = true;
} }
if (page.value > 1) { if (page.value > 1) {
list.value = list.value.concat(res.list); list.value = list.value.concat(res.list);
@ -333,7 +339,7 @@ const loadMessages = () => {
.catch((_err) => { .catch((_err) => {
loading.value = false; loading.value = false;
if (page.value > 1) { if (page.value > 1) {
page.value-- page.value--;
} }
}); });
}; };

@ -61,8 +61,8 @@
import { ref, watch, onMounted, computed } from 'vue'; import { ref, watch, onMounted, computed } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { getPost, getPostComments } from '@/api/post'; import { getPost, getPostComments } from '@/api/post';
import InfiniteLoading from "v3-infinite-loading"; import InfiniteLoading from 'v3-infinite-loading';
import "v3-infinite-loading/lib/style.css"; import 'v3-infinite-loading/lib/style.css';
const route = useRoute(); const route = useRoute();
const post = ref<Item.PostProps>({} as Item.PostProps); const post = ref<Item.PostProps>({} as Item.PostProps);
@ -70,11 +70,11 @@ const loading = ref(false);
const commentLoading = ref(false); const commentLoading = ref(false);
const comments = ref<Item.CommentProps[]>([]); const comments = ref<Item.CommentProps[]>([]);
const postId = computed(() => +(route.query.id as string)); const postId = computed(() => +(route.query.id as string));
const sortStrategy = ref<"default" | "hots" | "newest">('default'); const sortStrategy = ref<'default' | 'hots' | 'newest'>('default');
const defaultCommentsSort = ref<boolean>(true) const defaultCommentsSort = ref<boolean>(true);
const pageSize = 20 const pageSize = 20;
let stateHandler = ({ let stateHandler = {
loading() { loading() {
//nothing //nothing
}, },
@ -87,12 +87,12 @@ let stateHandler = ({
error() { error() {
// nothing // nothing
}, },
}); };
const commentTab = (tab: "default" | "hots" | "newest") => { const commentTab = (tab: 'default' | 'hots' | 'newest') => {
sortStrategy.value = tab; sortStrategy.value = tab;
if (tab === "default") { if (tab === 'default') {
defaultCommentsSort.value = true defaultCommentsSort.value = true;
} }
loadComments(stateHandler); loadComments(stateHandler);
}; };
@ -100,9 +100,11 @@ const commentTab = (tab: "default" | "hots" | "newest") => {
const reloadPost = (post_id: number) => { const reloadPost = (post_id: number) => {
getPost({ getPost({
id: post_id, id: post_id,
}).then((res) => { })
.then((res) => {
post.value = res; post.value = res;
}).catch((_err) => {}); })
.catch((_err) => {});
}; };
const loadPost = () => { const loadPost = () => {
@ -126,11 +128,11 @@ const loadPost = () => {
}; };
let defaultCommmentsPage = 1; let defaultCommmentsPage = 1;
const defaultNoMore = ref<boolean>(false) const defaultNoMore = ref<boolean>(false);
const defaultComments = ref<Item.CommentProps[]>([]); const defaultComments = ref<Item.CommentProps[]>([]);
const loadDefaultComments = ($state: any) => { const loadDefaultComments = ($state: any) => {
if (defaultNoMore.value) { if (defaultNoMore.value) {
return return;
} }
getPostComments({ getPostComments({
id: post.value.id as number, id: post.value.id as number,
@ -140,12 +142,12 @@ const loadDefaultComments = ($state: any) => {
}) })
.then((res) => { .then((res) => {
if ($state !== null) { if ($state !== null) {
stateHandler = $state stateHandler = $state;
} }
if (res.list.length < pageSize) { if (res.list.length < pageSize) {
defaultNoMore.value = true defaultNoMore.value = true;
} else { } else {
defaultCommmentsPage++ defaultCommmentsPage++;
} }
if (res.list.length > 0) { if (res.list.length > 0) {
if (defaultCommmentsPage === 1) { if (defaultCommmentsPage === 1) {
@ -153,7 +155,7 @@ const loadDefaultComments = ($state: any) => {
} else { } else {
defaultComments.value.push(...res.list); defaultComments.value.push(...res.list);
} }
comments.value = defaultComments.value comments.value = defaultComments.value;
} }
stateHandler.loaded(); stateHandler.loaded();
commentLoading.value = false; commentLoading.value = false;
@ -165,11 +167,11 @@ const loadDefaultComments = ($state: any) => {
}; };
let hotsCommmentsPage = 1; let hotsCommmentsPage = 1;
let hotsNoMore = ref<boolean>(false) let hotsNoMore = ref<boolean>(false);
const hotsComments = ref<Item.CommentProps[]>([]); const hotsComments = ref<Item.CommentProps[]>([]);
const loadHotsComments = ($state: any) => { const loadHotsComments = ($state: any) => {
if (hotsNoMore.value) { if (hotsNoMore.value) {
return return;
} }
getPostComments({ getPostComments({
id: post.value.id as number, id: post.value.id as number,
@ -179,12 +181,12 @@ const loadHotsComments = ($state: any) => {
}) })
.then((res) => { .then((res) => {
if ($state !== null) { if ($state !== null) {
stateHandler = $state stateHandler = $state;
} }
if (res.list.length < pageSize) { if (res.list.length < pageSize) {
hotsNoMore.value = true hotsNoMore.value = true;
} else { } else {
hotsCommmentsPage++ hotsCommmentsPage++;
} }
if (res.list.length > 0) { if (res.list.length > 0) {
if (hotsCommmentsPage === 1) { if (hotsCommmentsPage === 1) {
@ -192,7 +194,7 @@ const loadHotsComments = ($state: any) => {
} else { } else {
hotsComments.value.push(...res.list); hotsComments.value.push(...res.list);
} }
comments.value = hotsComments.value comments.value = hotsComments.value;
} }
stateHandler.loaded(); stateHandler.loaded();
commentLoading.value = false; commentLoading.value = false;
@ -204,11 +206,11 @@ const loadHotsComments = ($state: any) => {
}; };
let newestCommmentsPage = 1; let newestCommmentsPage = 1;
let newestNoMore = ref<boolean>(false) let newestNoMore = ref<boolean>(false);
const newestComments = ref<Item.CommentProps[]>([]); const newestComments = ref<Item.CommentProps[]>([]);
const loadNewestComments = ($state: any) => { const loadNewestComments = ($state: any) => {
if (newestNoMore.value) { if (newestNoMore.value) {
return return;
} }
getPostComments({ getPostComments({
id: post.value.id as number, id: post.value.id as number,
@ -218,12 +220,12 @@ const loadNewestComments = ($state: any) => {
}) })
.then((res) => { .then((res) => {
if ($state !== null) { if ($state !== null) {
stateHandler = $state stateHandler = $state;
} }
if (res.list.length < pageSize) { if (res.list.length < pageSize) {
newestNoMore.value = true newestNoMore.value = true;
} else { } else {
newestCommmentsPage++ newestCommmentsPage++;
} }
if (res.list.length > 0) { if (res.list.length > 0) {
if (newestCommmentsPage === 1) { if (newestCommmentsPage === 1) {
@ -231,7 +233,7 @@ const loadNewestComments = ($state: any) => {
} else { } else {
newestComments.value.push(...res.list); newestComments.value.push(...res.list);
} }
comments.value = newestComments.value comments.value = newestComments.value;
} }
stateHandler.loaded(); stateHandler.loaded();
commentLoading.value = false; commentLoading.value = false;
@ -244,20 +246,20 @@ const loadNewestComments = ($state: any) => {
const loadComments = ($state: any) => { const loadComments = ($state: any) => {
if (postId.value < 1) { if (postId.value < 1) {
return return;
} }
if (comments.value.length === 0) { if (comments.value.length === 0) {
commentLoading.value = true; commentLoading.value = true;
} }
if (sortStrategy.value === 'default') { if (sortStrategy.value === 'default') {
comments.value = defaultComments.value comments.value = defaultComments.value;
loadDefaultComments($state) loadDefaultComments($state);
} else if (sortStrategy.value === 'hots') { } else if (sortStrategy.value === 'hots') {
comments.value = hotsComments.value comments.value = hotsComments.value;
loadHotsComments($state) loadHotsComments($state);
} else { } else {
comments.value = newestComments.value comments.value = newestComments.value;
loadNewestComments($state) loadNewestComments($state);
} }
commentLoading.value = false; commentLoading.value = false;
}; };
@ -266,19 +268,19 @@ const reloadComments = () => {
// 这里需要做特殊处理,目前暴力处理,一切都重新加载 // 这里需要做特殊处理,目前暴力处理,一切都重新加载
// TODO:后续持续优化, 这里有大bug!!! // TODO:后续持续优化, 这里有大bug!!!
defaultCommmentsPage = 1; defaultCommmentsPage = 1;
defaultNoMore.value = false defaultNoMore.value = false;
defaultComments.value = [] defaultComments.value = [];
hotsCommmentsPage = 1; hotsCommmentsPage = 1;
hotsNoMore.value = false hotsNoMore.value = false;
hotsComments.value = [] hotsComments.value = [];
newestCommmentsPage = 1; newestCommmentsPage = 1;
newestNoMore.value = false newestNoMore.value = false;
newestComments.value = [] newestComments.value = [];
loadComments(stateHandler) loadComments(stateHandler);
} };
onMounted(() => { onMounted(() => {
loadPost(); loadPost();

@ -213,10 +213,8 @@ import { useDialog, DropdownOption } from 'naive-ui';
import { getUserPosts, followUser, unfollowUser } from '@/api/user'; import { getUserPosts, followUser, unfollowUser } from '@/api/user';
import { formatDate } from '@/utils/formatTime'; import { formatDate } from '@/utils/formatTime';
import { prettyQuoteNum } from '@/utils/count'; import { prettyQuoteNum } from '@/utils/count';
import InfiniteLoading from "v3-infinite-loading"; import InfiniteLoading from 'v3-infinite-loading';
import { import { SettingsOutline } from '@vicons/ionicons5';
SettingsOutline,
} from '@vicons/ionicons5';
import { MoreHorizFilled } from '@vicons/material'; import { MoreHorizFilled } from '@vicons/material';
const store = useStore(); const store = useStore();
@ -231,11 +229,13 @@ const commentList = ref<Item.PostProps[]>([]);
const highlightList = ref<Item.PostProps[]>([]); const highlightList = ref<Item.PostProps[]>([]);
const mediaList = ref<Item.PostProps[]>([]); const mediaList = ref<Item.PostProps[]>([]);
const starList = ref<Item.PostProps[]>([]); const starList = ref<Item.PostProps[]>([]);
const pageType = ref<"post" | "comment" | "highlight" |"media" | "star">('post'); const pageType = ref<'post' | 'comment' | 'highlight' | 'media' | 'star'>(
'post',
);
const postPage = ref(+(route.query.p as string) || 1); const postPage = ref(+(route.query.p as string) || 1);
const commentPage = ref(1) const commentPage = ref(1);
const highlightPage = ref(1) const highlightPage = ref(1);
const mediaPage = ref(1) const mediaPage = ref(1);
const starPage = ref(1); const starPage = ref(1);
const page = ref(+(route.query.p as string) || 1); const page = ref(+(route.query.p as string) || 1);
const pageSize = ref(20); const pageSize = ref(20);
@ -263,29 +263,29 @@ const whisperReceiver = ref<Item.UserInfo>({
const renderIcon = (icon: Component) => { const renderIcon = (icon: Component) => {
return () => { return () => {
return h(NIcon, null, { return h(NIcon, null, {
default: () => h(icon) default: () => h(icon),
}) });
} };
}; };
const userOptions = computed(() => { const userOptions = computed(() => {
let options: DropdownOption[] = [{ let options: DropdownOption[] = [
{
label: '设置', label: '设置',
key: 'setting', key: 'setting',
icon: renderIcon(SettingsOutline) icon: renderIcon(SettingsOutline),
}]; },
];
return options; return options;
}); });
const handleUserAction = ( const handleUserAction = (item: 'setting') => {
item: 'setting'
) => {
switch (item) { switch (item) {
case 'setting': case 'setting':
router.push({ router.push({
name: 'setting', name: 'setting',
query: { query: {
t: (new Date().getTime()) t: new Date().getTime(),
}, },
}); });
break; break;
@ -307,14 +307,18 @@ const onHandleFollowAction = (post: Item.PostProps) => {
dialog.success({ dialog.success({
title: '提示', title: '提示',
content: content:
'确定' + (post.user.is_following ? '取消关注 @' : '关注 @') + post.user.username + ' 吗?', '确定' +
(post.user.is_following ? '取消关注 @' : '关注 @') +
post.user.username +
' 吗?',
positiveText: '确定', positiveText: '确定',
negativeText: '取消', negativeText: '取消',
onPositiveClick: () => { onPositiveClick: () => {
if (post.user.is_following) { if (post.user.is_following) {
unfollowUser({ unfollowUser({
user_id: post.user.id, user_id: post.user.id,
}).then((_res) => { })
.then((_res) => {
window.$message.success('操作成功'); window.$message.success('操作成功');
postFollowAction(post.user_id, false); postFollowAction(post.user_id, false);
}) })
@ -322,7 +326,8 @@ const onHandleFollowAction = (post: Item.PostProps) => {
} else { } else {
followUser({ followUser({
user_id: post.user.id, user_id: post.user.id,
}).then((_res) => { })
.then((_res) => {
window.$message.success('关注成功'); window.$message.success('关注成功');
postFollowAction(post.user_id, true); postFollowAction(post.user_id, true);
}) })
@ -340,7 +345,11 @@ function postFollowAction(userId: number, isFollowing: boolean) {
updateFolloing(starList.value, userId, isFollowing); updateFolloing(starList.value, userId, isFollowing);
} }
function updateFolloing(posts: Item.PostProps[], userId: number, isFollowing: boolean) { function updateFolloing(
posts: Item.PostProps[],
userId: number,
isFollowing: boolean,
) {
if (posts && posts.length > 0) { if (posts && posts.length > 0) {
for (let index in posts) { for (let index in posts) {
if (posts[index].user_id == userId) { if (posts[index].user_id == userId) {
@ -352,19 +361,19 @@ function updateFolloing(posts: Item.PostProps[], userId: number, isFollowing: bo
const loadPage = () => { const loadPage = () => {
switch (pageType.value) { switch (pageType.value) {
case "post": case 'post':
loadPosts(); loadPosts();
break; break;
case "comment": case 'comment':
loadCommentPosts(); loadCommentPosts();
break; break;
case "highlight": case 'highlight':
loadHighlightPosts(); loadHighlightPosts();
break; break;
case "media": case 'media':
loadMediaPosts(); loadMediaPosts();
break; break;
case "star": case 'star':
loadStarPosts(); loadStarPosts();
break; break;
} }
@ -373,14 +382,14 @@ const loadPosts = () => {
loading.value = true; loading.value = true;
getUserPosts({ getUserPosts({
username: store.state.userInfo.username, username: store.state.userInfo.username,
style: "post", style: 'post',
page: page.value, page: page.value,
page_size: pageSize.value, page_size: pageSize.value,
}) })
.then((rsp) => { .then((rsp) => {
loading.value = false; loading.value = false;
if (rsp.list.length === 0) { if (rsp.list.length === 0) {
noMore.value = true noMore.value = true;
} }
if (page.value > 1) { if (page.value > 1) {
list.value = list.value.concat(rsp.list); list.value = list.value.concat(rsp.list);
@ -404,14 +413,14 @@ const loadCommentPosts = () => {
loading.value = true; loading.value = true;
getUserPosts({ getUserPosts({
username: store.state.userInfo.username, username: store.state.userInfo.username,
style: "comment", style: 'comment',
page: page.value, page: page.value,
page_size: pageSize.value, page_size: pageSize.value,
}) })
.then((rsp) => { .then((rsp) => {
loading.value = false; loading.value = false;
if (rsp.list.length === 0) { if (rsp.list.length === 0) {
noMore.value = true noMore.value = true;
} }
if (page.value > 1) { if (page.value > 1) {
list.value = list.value.concat(rsp.list); list.value = list.value.concat(rsp.list);
@ -435,14 +444,14 @@ const loadHighlightPosts = () => {
loading.value = true; loading.value = true;
getUserPosts({ getUserPosts({
username: store.state.userInfo.username, username: store.state.userInfo.username,
style: "highlight", style: 'highlight',
page: page.value, page: page.value,
page_size: pageSize.value, page_size: pageSize.value,
}) })
.then((rsp) => { .then((rsp) => {
loading.value = false; loading.value = false;
if (rsp.list.length === 0) { if (rsp.list.length === 0) {
noMore.value = true noMore.value = true;
} }
if (page.value > 1) { if (page.value > 1) {
list.value = list.value.concat(rsp.list); list.value = list.value.concat(rsp.list);
@ -466,14 +475,14 @@ const loadMediaPosts = () => {
loading.value = true; loading.value = true;
getUserPosts({ getUserPosts({
username: store.state.userInfo.username, username: store.state.userInfo.username,
style: "media", style: 'media',
page: page.value, page: page.value,
page_size: pageSize.value, page_size: pageSize.value,
}) })
.then((rsp) => { .then((rsp) => {
loading.value = false; loading.value = false;
if (rsp.list.length === 0) { if (rsp.list.length === 0) {
noMore.value = true noMore.value = true;
} }
if (page.value > 1) { if (page.value > 1) {
list.value = list.value.concat(rsp.list); list.value = list.value.concat(rsp.list);
@ -497,14 +506,14 @@ const loadStarPosts = () => {
loading.value = true; loading.value = true;
getUserPosts({ getUserPosts({
username: store.state.userInfo.username, username: store.state.userInfo.username,
style: "star", style: 'star',
page: page.value, page: page.value,
page_size: pageSize.value, page_size: pageSize.value,
}) })
.then((rsp) => { .then((rsp) => {
loading.value = false; loading.value = false;
if (rsp.list.length === 0) { if (rsp.list.length === 0) {
noMore.value = true noMore.value = true;
} }
if (page.value > 1) { if (page.value > 1) {
list.value = list.value.concat(rsp.list); list.value = list.value.concat(rsp.list);
@ -524,34 +533,36 @@ const loadStarPosts = () => {
loading.value = false; loading.value = false;
}); });
}; };
const changeTab = (tab: "post" | "comment" | "highlight" | "media" | "star") => { const changeTab = (
tab: 'post' | 'comment' | 'highlight' | 'media' | 'star',
) => {
pageType.value = tab; pageType.value = tab;
switch (pageType.value) { switch (pageType.value) {
case "post": case 'post':
list.value = postList.value; list.value = postList.value;
page.value = postPage.value; page.value = postPage.value;
totalPage.value = postTotalPage.value; totalPage.value = postTotalPage.value;
loadPosts(); loadPosts();
break; break;
case "comment": case 'comment':
list.value = commentList.value; list.value = commentList.value;
page.value = commentPage.value; page.value = commentPage.value;
totalPage.value = commentTotalPage.value; totalPage.value = commentTotalPage.value;
loadCommentPosts(); loadCommentPosts();
break; break;
case "highlight": case 'highlight':
list.value = highlightList.value; list.value = highlightList.value;
page.value = highlightPage.value; page.value = highlightPage.value;
totalPage.value = highlightTotalPage.value; totalPage.value = highlightTotalPage.value;
loadHighlightPosts(); loadHighlightPosts();
break; break;
case "media": case 'media':
list.value = mediaList.value; list.value = mediaList.value;
page.value = mediaPage.value; page.value = mediaPage.value;
totalPage.value = mediaTotalPage.value; totalPage.value = mediaTotalPage.value;
loadMediaPosts(); loadMediaPosts();
break; break;
case "star": case 'star':
list.value = starList.value; list.value = starList.value;
page.value = starPage.value; page.value = starPage.value;
totalPage.value = starTotalPage.value; totalPage.value = starTotalPage.value;
@ -561,23 +572,23 @@ const changeTab = (tab: "post" | "comment" | "highlight" | "media" | "star") =>
}; };
const updatePage = () => { const updatePage = () => {
switch (pageType.value) { switch (pageType.value) {
case "post": case 'post':
postPage.value = page.value; postPage.value = page.value;
loadPosts(); loadPosts();
break; break;
case "comment": case 'comment':
commentPage.value = page.value; commentPage.value = page.value;
loadCommentPosts(); loadCommentPosts();
break; break;
case "highlight": case 'highlight':
highlightPage.value = page.value; highlightPage.value = page.value;
loadHighlightPosts(); loadHighlightPosts();
break; break;
case "media": case 'media':
mediaPage.value = page.value; mediaPage.value = page.value;
loadMediaPosts(); loadMediaPosts();
break; break;
case "star": case 'star':
starPage.value = page.value; starPage.value = page.value;
loadStarPosts(); loadStarPosts();
break; break;
@ -615,7 +626,7 @@ watch(
loadPage(); loadPage();
}, 0); }, 0);
} }
} },
); );
</script> </script>

@ -363,11 +363,12 @@ import type {
const uploadGateway = import.meta.env.VITE_HOST + '/v1/attachment'; const uploadGateway = import.meta.env.VITE_HOST + '/v1/attachment';
const uploadToken = 'Bearer ' + localStorage.getItem('PAOPAO_TOKEN'); const uploadToken = 'Bearer ' + localStorage.getItem('PAOPAO_TOKEN');
const uploadType = ref('public/avatar'); const uploadType = ref('public/avatar');
const allowActivation = (import.meta.env.VITE_ALLOW_ACTIVATION.toLowerCase() === 'true') const allowActivation =
import.meta.env.VITE_ALLOW_ACTIVATION.toLowerCase() === 'true';
const store = useStore(); const store = useStore();
const sending = ref(false); const sending = ref(false);
const binding = ref(false); const binding = ref(false);
const activating = ref(false) const activating = ref(false);
const avatarRef = ref<UploadInst>(); const avatarRef = ref<UploadInst>();
const inputInstRef = ref<InputInst>(); const inputInstRef = ref<InputInst>();
const showNicknameEdit = ref(false); const showNicknameEdit = ref(false);
@ -534,7 +535,7 @@ const handleActivation = (e: MouseEvent) => {
activateUser({ activateUser({
activate_code: activateData.activate_code, activate_code: activateData.activate_code,
captcha_id: activateData.id, captcha_id: activateData.id,
imgCaptcha: activateData.imgCaptcha imgCaptcha: activateData.imgCaptcha,
}) })
.then((res) => { .then((res) => {
activating.value = false; activating.value = false;

@ -40,23 +40,23 @@ import { useStore } from 'vuex';
const store = useStore(); const store = useStore();
const tags = ref<Item.TagProps[]>([]); const tags = ref<Item.TagProps[]>([]);
const tagType = ref<"hot" | "new" | "follow" | "pin">('hot'); const tagType = ref<'hot' | 'new' | 'follow' | 'pin'>('hot');
const loading = ref(false); const loading = ref(false);
const tagsChecked = ref(false) const tagsChecked = ref(false);
const inFollowTab = ref(false) const inFollowTab = ref(false);
const inPinTab = ref(false) const inPinTab = ref(false);
watch(tagsChecked, () => { watch(tagsChecked, () => {
if (!tagsChecked.value) { if (!tagsChecked.value) {
window.$message.success("保存成功"); window.$message.success('保存成功');
store.commit("refreshTopicFollow") store.commit('refreshTopicFollow');
} }
}); });
const tagsEditText = computed({ const tagsEditText = computed({
get: () => { get: () => {
let text = "编辑"; let text = '编辑';
if (tagsChecked.value) { if (tagsChecked.value) {
text = "保存"; text = '保存';
} }
return text; return text;
}, },
@ -80,10 +80,10 @@ const loadTags = () => {
loading.value = false; loading.value = false;
}); });
}; };
const changeTab = (tab: "hot" | "new" | "follow" | "pin") => { const changeTab = (tab: 'hot' | 'new' | 'follow' | 'pin') => {
tagType.value = tab; tagType.value = tab;
inFollowTab.value = (tab === "follow") inFollowTab.value = tab === 'follow';
inPinTab.value = (tab === "pin") inPinTab.value = tab === 'pin';
loadTags(); loadTags();
}; };
onMounted(() => { onMounted(() => {

@ -216,11 +216,18 @@
<script setup lang="ts"> <script setup lang="ts">
import { h, ref, reactive, watch, onMounted, computed } from 'vue'; import { h, ref, reactive, watch, onMounted, computed } from 'vue';
import { NIcon } from 'naive-ui' import { NIcon } from 'naive-ui';
import type { Component, Ref } from 'vue' import type { Component, Ref } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { useRoute, useRouter } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
import { getUserProfile, getUserPosts, changeUserStatus, deleteFriend, followUser, unfollowUser } from '@/api/user'; import {
getUserProfile,
getUserPosts,
changeUserStatus,
deleteFriend,
followUser,
unfollowUser,
} from '@/api/user';
import { useDialog, DropdownOption } from 'naive-ui'; import { useDialog, DropdownOption } from 'naive-ui';
import WhisperAddFriend from '../components/whisper-add-friend.vue'; import WhisperAddFriend from '../components/whisper-add-friend.vue';
import { MoreHorizFilled } from '@vicons/material'; import { MoreHorizFilled } from '@vicons/material';
@ -233,9 +240,9 @@ import {
PersonRemoveOutline, PersonRemoveOutline,
CubeOutline, CubeOutline,
BodyOutline, BodyOutline,
WalkOutline WalkOutline,
} from '@vicons/ionicons5'; } from '@vicons/ionicons5';
import InfiniteLoading from "v3-infinite-loading"; import InfiniteLoading from 'v3-infinite-loading';
const dialog = useDialog(); const dialog = useDialog();
const store = useStore(); const store = useStore();
@ -269,11 +276,13 @@ const mediaList = ref<Item.PostProps[]>([]);
const starList = ref<Item.PostProps[]>([]); const starList = ref<Item.PostProps[]>([]);
const username = ref(route.query.s || ''); const username = ref(route.query.s || '');
const page = ref(+(route.query.p as string) || 1); const page = ref(+(route.query.p as string) || 1);
const pageType = ref<"post" | "comment" | "highlight" | "media" | "star">('post'); const pageType = ref<'post' | 'comment' | 'highlight' | 'media' | 'star'>(
'post',
);
const postPage = ref(+(route.query.p as string) || 1); const postPage = ref(+(route.query.p as string) || 1);
const commentPage = ref(1) const commentPage = ref(1);
const highlightPage = ref(1) const highlightPage = ref(1);
const mediaPage = ref(1) const mediaPage = ref(1);
const starPage = ref(1); const starPage = ref(1);
const pageSize = ref(20); const pageSize = ref(20);
const totalPage = ref(0); const totalPage = ref(0);
@ -285,9 +294,9 @@ const starTotalPage = ref(0);
const onSendWhisper = (receiver: Item.UserInfo) => { const onSendWhisper = (receiver: Item.UserInfo) => {
user.id = receiver.id; user.id = receiver.id;
user.username = receiver.username user.username = receiver.username;
user.nickname = receiver.nickname user.nickname = receiver.nickname;
user.avatar = receiver.avatar user.avatar = receiver.avatar;
showWhisper.value = true; showWhisper.value = true;
}; };
@ -295,14 +304,18 @@ const onHandleFollowAction = (post: Item.PostProps) => {
dialog.success({ dialog.success({
title: '提示', title: '提示',
content: content:
'确定' + (post.user.is_following ? '取消关注 @' : '关注 @') + post.user.username + ' 吗?', '确定' +
(post.user.is_following ? '取消关注 @' : '关注 @') +
post.user.username +
' 吗?',
positiveText: '确定', positiveText: '确定',
negativeText: '取消', negativeText: '取消',
onPositiveClick: () => { onPositiveClick: () => {
if (post.user.is_following) { if (post.user.is_following) {
unfollowUser({ unfollowUser({
user_id: post.user.id, user_id: post.user.id,
}).then((_res) => { })
.then((_res) => {
window.$message.success('操作成功'); window.$message.success('操作成功');
postFollowAction(post.user_id, false); postFollowAction(post.user_id, false);
}) })
@ -310,7 +323,8 @@ const onHandleFollowAction = (post: Item.PostProps) => {
} else { } else {
followUser({ followUser({
user_id: post.user.id, user_id: post.user.id,
}).then((_res) => { })
.then((_res) => {
window.$message.success('关注成功'); window.$message.success('关注成功');
postFollowAction(post.user_id, true); postFollowAction(post.user_id, true);
}) })
@ -328,7 +342,11 @@ function postFollowAction(userId: number, isFollowing: boolean) {
updateFolloing(starList, userId, isFollowing); updateFolloing(starList, userId, isFollowing);
} }
function updateFolloing(posts: Ref<Item.PostProps[]>, userId: number, isFollowing: boolean) { function updateFolloing(
posts: Ref<Item.PostProps[]>,
userId: number,
isFollowing: boolean,
) {
if (posts.value && posts.value.length > 0) { if (posts.value && posts.value.length > 0) {
for (let index in posts.value) { for (let index in posts.value) {
if (posts.value[index].user_id == userId) { if (posts.value[index].user_id == userId) {
@ -343,10 +361,10 @@ const reset = () => {
list.value = []; list.value = [];
postList.value = []; postList.value = [];
commentList.value = []; commentList.value = [];
highlightList.value = [] highlightList.value = [];
mediaList.value = []; mediaList.value = [];
starList.value = [] starList.value = [];
pageType.value = "post"; pageType.value = 'post';
page.value = 1; page.value = 1;
postPage.value = 1; postPage.value = 1;
commentPage.value = 1; commentPage.value = 1;
@ -362,19 +380,19 @@ const reset = () => {
}; };
const loadPage = () => { const loadPage = () => {
switch (pageType.value) { switch (pageType.value) {
case "post": case 'post':
loadPosts(); loadPosts();
break; break;
case "comment": case 'comment':
loadCommentPosts(); loadCommentPosts();
break; break;
case "highlight": case 'highlight':
loadHighlightPosts(); loadHighlightPosts();
break; break;
case "media": case 'media':
loadMediaPosts(); loadMediaPosts();
break; break;
case "star": case 'star':
loadStarPosts(); loadStarPosts();
break; break;
} }
@ -383,14 +401,14 @@ const loadPosts = () => {
loading.value = true; loading.value = true;
getUserPosts({ getUserPosts({
username: username.value as string, username: username.value as string,
style: "post", style: 'post',
page: page.value, page: page.value,
page_size: pageSize.value, page_size: pageSize.value,
}) })
.then((rsp) => { .then((rsp) => {
loading.value = false; loading.value = false;
if (rsp.list.length === 0) { if (rsp.list.length === 0) {
noMore.value = true noMore.value = true;
} }
if (page.value > 1) { if (page.value > 1) {
list.value = list.value.concat(rsp.list); list.value = list.value.concat(rsp.list);
@ -414,14 +432,14 @@ const loadCommentPosts = () => {
loading.value = true; loading.value = true;
getUserPosts({ getUserPosts({
username: username.value as string, username: username.value as string,
style: "comment", style: 'comment',
page: page.value, page: page.value,
page_size: pageSize.value, page_size: pageSize.value,
}) })
.then((rsp) => { .then((rsp) => {
loading.value = false; loading.value = false;
if (rsp.list.length === 0) { if (rsp.list.length === 0) {
noMore.value = true noMore.value = true;
} }
if (page.value > 1) { if (page.value > 1) {
list.value = list.value.concat(rsp.list); list.value = list.value.concat(rsp.list);
@ -445,14 +463,14 @@ const loadHighlightPosts = () => {
loading.value = true; loading.value = true;
getUserPosts({ getUserPosts({
username: username.value as string, username: username.value as string,
style: "highlight", style: 'highlight',
page: page.value, page: page.value,
page_size: pageSize.value, page_size: pageSize.value,
}) })
.then((rsp) => { .then((rsp) => {
loading.value = false; loading.value = false;
if (rsp.list.length === 0) { if (rsp.list.length === 0) {
noMore.value = true noMore.value = true;
} }
if (page.value > 1) { if (page.value > 1) {
list.value = list.value.concat(rsp.list); list.value = list.value.concat(rsp.list);
@ -476,7 +494,7 @@ const loadMediaPosts = () => {
loading.value = true; loading.value = true;
getUserPosts({ getUserPosts({
username: username.value as string, username: username.value as string,
style: "media", style: 'media',
page: page.value, page: page.value,
page_size: pageSize.value, page_size: pageSize.value,
}) })
@ -507,14 +525,14 @@ const loadStarPosts = () => {
loading.value = true; loading.value = true;
getUserPosts({ getUserPosts({
username: username.value as string, username: username.value as string,
style: "star", style: 'star',
page: page.value, page: page.value,
page_size: pageSize.value, page_size: pageSize.value,
}) })
.then((rsp) => { .then((rsp) => {
loading.value = false; loading.value = false;
if (rsp.list.length === 0) { if (rsp.list.length === 0) {
noMore.value = true noMore.value = true;
} }
if (page.value > 1) { if (page.value > 1) {
list.value = list.value.concat(rsp.list); list.value = list.value.concat(rsp.list);
@ -534,34 +552,36 @@ const loadStarPosts = () => {
loading.value = false; loading.value = false;
}); });
}; };
const changeTab = (tab: "post" | "comment" | "highlight" | "media" | "star") => { const changeTab = (
tab: 'post' | 'comment' | 'highlight' | 'media' | 'star',
) => {
pageType.value = tab; pageType.value = tab;
switch (pageType.value) { switch (pageType.value) {
case "post": case 'post':
list.value = postList.value; list.value = postList.value;
page.value = postPage.value; page.value = postPage.value;
totalPage.value = postTotalPage.value; totalPage.value = postTotalPage.value;
loadPosts(); loadPosts();
break; break;
case "comment": case 'comment':
list.value = commentList.value; list.value = commentList.value;
page.value = commentPage.value; page.value = commentPage.value;
totalPage.value = commentTotalPage.value; totalPage.value = commentTotalPage.value;
loadCommentPosts(); loadCommentPosts();
break; break;
case "highlight": case 'highlight':
list.value = highlightList.value; list.value = highlightList.value;
page.value = highlightPage.value; page.value = highlightPage.value;
totalPage.value = highlightTotalPage.value; totalPage.value = highlightTotalPage.value;
loadHighlightPosts(); loadHighlightPosts();
break; break;
case "media": case 'media':
list.value = mediaList.value; list.value = mediaList.value;
page.value = mediaPage.value; page.value = mediaPage.value;
totalPage.value = mediaTotalPage.value; totalPage.value = mediaTotalPage.value;
loadMediaPosts(); loadMediaPosts();
break; break;
case "star": case 'star':
list.value = starList.value; list.value = starList.value;
page.value = starPage.value; page.value = starPage.value;
totalPage.value = starTotalPage.value; totalPage.value = starTotalPage.value;
@ -599,23 +619,23 @@ const loadUser = () => {
}; };
const updatePage = () => { const updatePage = () => {
switch (pageType.value) { switch (pageType.value) {
case "post": case 'post':
postPage.value = page.value; postPage.value = page.value;
loadPosts(); loadPosts();
break; break;
case "comment": case 'comment':
commentPage.value = page.value; commentPage.value = page.value;
loadCommentPosts(); loadCommentPosts();
break; break;
case "highlight": case 'highlight':
highlightPage.value = page.value; highlightPage.value = page.value;
loadHighlightPosts(); loadHighlightPosts();
break; break;
case "media": case 'media':
mediaPage.value = page.value; mediaPage.value = page.value;
loadMediaPosts(); loadMediaPosts();
break; break;
case "star": case 'star':
starPage.value = page.value; starPage.value = page.value;
loadStarPosts(); loadStarPosts();
break; break;
@ -636,35 +656,39 @@ const addFriendWhisperSuccess = () => {
const renderIcon = (icon: Component) => { const renderIcon = (icon: Component) => {
return () => { return () => {
return h(NIcon, null, { return h(NIcon, null, {
default: () => h(icon) default: () => h(icon),
}) });
} };
}; };
const userOptions = computed(() => { const userOptions = computed(() => {
if (store.state.userInfo.username == user.username) { if (store.state.userInfo.username == user.username) {
return [{ return [
{
label: '设置', label: '设置',
key: 'setting', key: 'setting',
icon: renderIcon(SettingsOutline) icon: renderIcon(SettingsOutline),
}]; },
];
} }
let options: DropdownOption[] = [{ let options: DropdownOption[] = [
{
label: '私信', label: '私信',
key: 'whisper', key: 'whisper',
icon: renderIcon(PaperPlaneOutline) icon: renderIcon(PaperPlaneOutline),
}]; },
];
if (store.state.userInfo.is_admin) { if (store.state.userInfo.is_admin) {
if (user.status === 1) { if (user.status === 1) {
options.push({ options.push({
label: '禁言', label: '禁言',
key: 'banned', key: 'banned',
icon: renderIcon(CubeOutline) icon: renderIcon(CubeOutline),
}); });
} else { } else {
options.push({ options.push({
label: '解封', label: '解封',
key: 'deblocking', key: 'deblocking',
icon: renderIcon(CubeOutline) icon: renderIcon(CubeOutline),
}); });
} }
} }
@ -672,34 +696,42 @@ const userOptions = computed(() => {
options.push({ options.push({
label: '取消关注', label: '取消关注',
key: 'unfollow', key: 'unfollow',
icon: renderIcon(WalkOutline) icon: renderIcon(WalkOutline),
}) });
} else { } else {
options.push({ options.push({
label: '关注', label: '关注',
key: 'follow', key: 'follow',
icon: renderIcon(BodyOutline) icon: renderIcon(BodyOutline),
}) });
} }
if (store.state.profile.useFriendship) { if (store.state.profile.useFriendship) {
if (user.is_friend) { if (user.is_friend) {
options.push({ options.push({
label: '删除好友', label: '删除好友',
key: 'delete', key: 'delete',
icon: renderIcon(PersonRemoveOutline) icon: renderIcon(PersonRemoveOutline),
}); });
} else { } else {
options.push({ options.push({
label: '添加朋友', label: '添加朋友',
key: 'requesting', key: 'requesting',
icon: renderIcon(PersonAddOutline) icon: renderIcon(PersonAddOutline),
}); });
} }
} }
return options; return options;
}); });
const handleUserAction = ( const handleUserAction = (
item: 'whisper' | 'follow' | 'unfollow' | 'delete' | 'requesting' | 'banned' | 'deblocking' | 'setting' item:
| 'whisper'
| 'follow'
| 'unfollow'
| 'delete'
| 'requesting'
| 'banned'
| 'deblocking'
| 'setting',
) => { ) => {
switch (item) { switch (item) {
case 'whisper': case 'whisper':
@ -723,7 +755,7 @@ const handleUserAction = (
router.push({ router.push({
name: 'setting', name: 'setting',
query: { query: {
t: (new Date().getTime()) t: new Date().getTime(),
}, },
}); });
break; break;
@ -734,7 +766,10 @@ const handleUserAction = (
const openDeleteFriend = () => { const openDeleteFriend = () => {
dialog.warning({ dialog.warning({
title: '删除好友', title: '删除好友',
content: '将好友 “' + user.nickname + '” 删除,将同时删除 点赞/收藏 列表中关于该朋友的 “好友可见” 推文', content:
'将好友 “' +
user.nickname +
'” 删除,将同时删除 点赞/收藏 列表中关于该朋友的 “好友可见” 推文',
positiveText: '确定', positiveText: '确定',
negativeText: '取消', negativeText: '取消',
onPositiveClick: () => { onPositiveClick: () => {
@ -744,7 +779,7 @@ const openDeleteFriend = () => {
}) })
.then((res) => { .then((res) => {
userLoading.value = false; userLoading.value = false;
user.is_friend = false user.is_friend = false;
loadPosts(); loadPosts();
}) })
.catch((err) => { .catch((err) => {
@ -758,7 +793,10 @@ const handleFollowUser = () => {
dialog.success({ dialog.success({
title: '提示', title: '提示',
content: content:
'确定' + (user.is_following ? '取消关注 @' : '关注 @') + user.username + ' 吗?', '确定' +
(user.is_following ? '取消关注 @' : '关注 @') +
user.username +
' 吗?',
positiveText: '确定', positiveText: '确定',
negativeText: '取消', negativeText: '取消',
onPositiveClick: () => { onPositiveClick: () => {
@ -766,7 +804,8 @@ const handleFollowUser = () => {
if (user.is_following) { if (user.is_following) {
unfollowUser({ unfollowUser({
user_id: user.id, user_id: user.id,
}).then((_res) => { })
.then((_res) => {
userLoading.value = false; userLoading.value = false;
window.$message.success('操作成功'); window.$message.success('操作成功');
loadUser(); loadUser();
@ -778,7 +817,8 @@ const handleFollowUser = () => {
} else { } else {
followUser({ followUser({
user_id: user.id, user_id: user.id,
}).then((_res) => { })
.then((_res) => {
userLoading.value = false; userLoading.value = false;
window.$message.success('操作成功'); window.$message.success('操作成功');
loadUser(); loadUser();
@ -795,9 +835,7 @@ const banUser = () => {
dialog.warning({ dialog.warning({
title: '警告', title: '警告',
content: content:
'确定对该用户进行' + '确定对该用户进行' + (user.status === 1 ? '禁言' : '解封') + '处理吗?',
(user.status === 1 ? '禁言' : '解封') +
'处理吗?',
positiveText: '确定', positiveText: '确定',
negativeText: '取消', negativeText: '取消',
onPositiveClick: () => { onPositiveClick: () => {
@ -845,7 +883,7 @@ watch(
reset(); reset();
loadUser(); loadUser();
} }
} },
); );
</script> </script>

@ -222,14 +222,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({

8
web/src/vuex.d.ts vendored

@ -1,14 +1,14 @@
import { ComponentCustomProperties } from 'vue' import { ComponentCustomProperties } from 'vue';
import { Store } from 'vuex' import { Store } from 'vuex';
declare module '@vue/runtime-core' { declare module '@vue/runtime-core' {
// 声明自己的 store state // 声明自己的 store state
interface State { interface State {
[key: string]: any [key: string]: any;
} }
// 为 `this.$store` 提供类型声明 // 为 `this.$store` 提供类型声明
interface ComponentCustomProperties { interface ComponentCustomProperties {
$store: Store<State> $store: Store<State>;
} }
} }

@ -9,13 +9,10 @@
"resolveJsonModule": true, "resolveJsonModule": true,
"esModuleInterop": true, "esModuleInterop": true,
"lib": ["esnext", "dom"], "lib": ["esnext", "dom"],
"types": [ "types": ["node"],
"node"
],
"paths": { "paths": {
"@/*": ["./src/*"] "@/*": ["./src/*"]
} }
}, },
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"] "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
} }

@ -1,14 +1,14 @@
import { defineConfig, type PluginOption } from "vite"; import { defineConfig, type PluginOption } from 'vite';
import path from "path"; import path from 'path';
import vue from "@vitejs/plugin-vue"; import vue from '@vitejs/plugin-vue';
import Components from "unplugin-vue-components/vite"; import Components from 'unplugin-vue-components/vite';
import { visualizer } from "rollup-plugin-visualizer"; import { visualizer } from 'rollup-plugin-visualizer';
import { NaiveUiResolver } from "unplugin-vue-components/resolvers"; import { NaiveUiResolver } from 'unplugin-vue-components/resolvers';
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig({ export default defineConfig({
server: { server: {
host: "0.0.0.0", host: '0.0.0.0',
}, },
plugins: [ plugins: [
vue({ vue({
@ -21,7 +21,7 @@ export default defineConfig({
], ],
resolve: { resolve: {
alias: { alias: {
"@": path.resolve(__dirname, "src"), '@': path.resolve(__dirname, 'src'),
}, },
}, },
build: { build: {
@ -29,11 +29,11 @@ export default defineConfig({
rollupOptions: { rollupOptions: {
output: { output: {
manualChunks(id) { manualChunks(id) {
if (id.includes("node_modules")) { if (id.includes('node_modules')) {
return id return id
.toString() .toString()
.split("node_modules/")[1] .split('node_modules/')[1]
.split("/")[0] .split('/')[0]
.toString(); .toString();
} }
}, },

Loading…
Cancel
Save