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
*.sw?
bun.lock
yarn.lock
package-lock.json
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",
"build": "vite build",
"preview": "vite preview",
"check": "biome check --write",
"format": "biome format --write",
"tauri": "tauri"
},
"dependencies": {
@ -32,6 +34,7 @@
"vuex": "^4.1.0"
},
"devDependencies": {
"@biomejs/biome": "^1.9.4",
"@tauri-apps/cli": "^1.5.10",
"@types/node": "^22.14.1",
"@types/qrcode": "^1.5.5",

@ -1,10 +1,9 @@
self.addEventListener("install", (event) => {
self.addEventListener('install', (event) => {
event.waitUntil((async () => {})());
});
self.addEventListener("activate", (event) => {
self.addEventListener('activate', (event) => {
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() {
store.commit('loadDefaultSiteProfile');
if (import.meta.env.VITE_USE_WEB_PROFILE.toLowerCase() === "true") {
getSiteProfile().then((res) => {
if (import.meta.env.VITE_USE_WEB_PROFILE.toLowerCase() === 'true') {
getSiteProfile()
.then((res) => {
store.commit('updateSiteProfile', res);
}).catch((err) => {
})
.catch((err) => {
console.log(err);
});
}

@ -1,7 +1,9 @@
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({
method: 'post',
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({
method: 'post',
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({
method: 'get',
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({
method: 'post',
url: '/v1/api/user/password',

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

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

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

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

@ -142,12 +142,15 @@ const replyAtUsername = ref('');
const replyComposeRef = ref();
const emit = defineEmits<{
(e: 'reload'): void
(e: 'reload'): void;
}>();
const props = withDefaults(defineProps<{
comment: Item.CommentProps,
postUserId: number
}>(), {})
const props = withDefaults(
defineProps<{
comment: Item.CommentProps;
postUserId: number;
}>(),
{},
);
const comment = computed(() => {
let comment: Item.CommentComponentProps = Object.assign(
@ -155,7 +158,7 @@ const comment = computed(() => {
texts: [],
imgs: [],
},
props.comment
props.comment,
);
comment.contents.map((content: any) => {
if (+content.type === 1 || +content.type === 2) {
@ -220,7 +223,7 @@ const execHightlightAction = () => {
})
.then((res) => {
comment.value.is_essence = res.highlight_status;
window.$message.success("操作成功");
window.$message.success('操作成功');
setTimeout(() => {
reload();
}, 50);

@ -170,9 +170,7 @@
import { onMounted, computed, ref } from 'vue';
import { useStore } from 'vuex';
import { debounce } from 'lodash';
import {
ImageOutline,
} from '@vicons/ionicons5';
import { ImageOutline } from '@vicons/ionicons5';
import { createComment } from '@/api/post';
import { getSuggestUsers } from '@/api/user';
import { parsePostTag } from '@/utils/content';
@ -189,7 +187,7 @@ const props = withDefaults(
{
lock: 0,
postId: 0,
}
},
);
const store = useStore();
@ -203,8 +201,12 @@ const uploadRef = ref<UploadInst>();
const uploadType = ref('public/image');
const fileQueue = ref<UploadFileInfo[]>([]);
const imageContents = ref<Item.CommentItemProps[]>([]);
const allowUserRegister = ref(import.meta.env.VITE_ALLOW_USER_REGISTER.toLowerCase() === 'true')
const defaultCommentMaxLength = Number(import.meta.env.VITE_DEFAULT_COMMENT_MAX_LENGTH)
const allowUserRegister = ref(
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 uploadToken = computed(() => {
@ -255,7 +257,12 @@ const updateUpload = (list: UploadFileInfo[]) => {
var basename: string = name.split('.').slice(0, -1).join('.');
var ext: string = name.split('.').pop()!;
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;
@ -265,7 +272,7 @@ const beforeUpload = async (data: any) => {
if (
uploadType.value === 'public/image' &&
!['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 格式');

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

@ -315,9 +315,11 @@ const imageContents = ref<Item.CommentItemProps[]>([]);
const videoContents = ref<Item.CommentItemProps[]>([]);
const attachmentContents = ref<Item.AttachmentProps[]>([]);
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 uploadToken = computed(() => {
@ -326,12 +328,12 @@ const uploadToken = computed(() => {
const visibilities = computed(() => {
let res = [
{value: VisibilityEnum.PUBLIC, label: "公开"},
{value: VisibilityEnum.PRIVATE, label: "私密"},
{value: VisibilityEnum.Following, label: "关注可见"},
{ value: VisibilityEnum.PUBLIC, label: '公开' },
{ value: VisibilityEnum.PRIVATE, label: '私密' },
{ value: VisibilityEnum.Following, label: '关注可见' },
];
if (store.state.profile.useFriendship) {
res.push({value: VisibilityEnum.FRIEND, label: "好友可见"});
res.push({ value: VisibilityEnum.FRIEND, label: '好友可见' });
}
return res;
});
@ -339,14 +341,14 @@ const visibilities = computed(()=> {
const switchLink = () => {
showLinkSet.value = !showLinkSet.value;
if (showLinkSet.value && showEyeSet.value) {
showEyeSet.value = false
showEyeSet.value = false;
}
};
const switchEye = () => {
showEyeSet.value = !showEyeSet.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 ext: string = name.split('.').pop()!;
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;
@ -429,9 +436,13 @@ const beforeUpload = async (data: any) => {
// 图片类型校验
if (
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 格式');
return false;
@ -451,17 +462,12 @@ const beforeUpload = async (data: any) => {
return false;
}
if (
uploadType.value === 'public/video' &&
data.file.file?.size > 104857600
) {
if (uploadType.value === 'public/video' && data.file.file?.size > 104857600) {
window.$message.warning('视频大小不能超过100MB');
return false;
}
// 附件类型校验
if (
uploadType.value === 'attachment' && !(await isZipFile(data.file.file))
) {
if (uploadType.value === 'attachment' && !(await isZipFile(data.file.file))) {
window.$message.warning('附件仅允许 zip 格式');
return false;
}
@ -593,7 +599,7 @@ const submitPost = () => {
tags: Array.from(new Set(tags)),
users: Array.from(new Set(users)),
attachment_price: +attachmentPrice.value * 100,
visibility: visitType.value
visibility: visitType.value,
})
.then((res) => {
window.$message.success('发布成功');
@ -621,15 +627,15 @@ const triggerAuth = (key: string) => {
store.commit('triggerAuthKey', key);
};
onMounted(() => {
const defaultVisibility = store.state.profile.defaultTweetVisibility
const defaultVisibility = store.state.profile.defaultTweetVisibility;
if (store.state.profile.useFriendship && defaultVisibility === 'friend') {
defaultVisitType.value = VisibilityEnum.FRIEND
defaultVisitType.value = VisibilityEnum.FRIEND;
} else if (defaultVisibility === 'following') {
defaultVisitType.value = VisibilityEnum.Following
defaultVisitType.value = VisibilityEnum.Following;
} else if (defaultVisibility === 'public') {
defaultVisitType.value = VisibilityEnum.PUBLIC
defaultVisitType.value = VisibilityEnum.PUBLIC;
} else {
defaultVisitType.value = VisibilityEnum.PRIVATE
defaultVisitType.value = VisibilityEnum.PRIVATE;
}
visitType.value = defaultVisitType.value;
});

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

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

@ -65,12 +65,17 @@ import { onMounted, ref } from 'vue';
import { useStore } from 'vuex';
import { useRouter } from 'vue-router';
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 router = useRouter();
const activeDrawerRef = ref(false)
const placementRef = ref<DrawerPlacement>('left')
const activeDrawerRef = ref(false);
const placementRef = ref<DrawerPlacement>('left');
const props = withDefaults(
defineProps<{
@ -82,7 +87,7 @@ const props = withDefaults(
title: '',
back: false,
theme: true,
}
},
);
const switchTheme = (theme: boolean) => {
if (theme) {
@ -103,7 +108,7 @@ const goBack = () => {
}
};
const activeDrawer = () => {
activeDrawerRef.value = true
activeDrawerRef.value = true;
};
onMounted(() => {

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

@ -8,11 +8,14 @@
</template>
<script setup lang="ts">
const props = withDefaults(defineProps<{
num: number
}>(), {
num: 1
});
const props = withDefaults(
defineProps<{
num: number;
}>(),
{
num: 1,
},
);
</script>
<style lang="less" scoped>

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

@ -48,7 +48,7 @@ const props = withDefaults(
{
attachments: () => [],
price: 0,
}
},
);
const showDownloadModal = ref(false);
const downloadTip = ref<any>('');
@ -67,7 +67,7 @@ const download = (attachment: Item.PostItemProps) => {
{},
'这是一个收费附件,下载将收取' +
(props.price / 100).toFixed(2) +
'元'
'元',
),
]);
@ -78,11 +78,7 @@ const download = (attachment: Item.PostItemProps) => {
if (res.paid) {
downloadTip.value = () =>
h('div', {}, [
h(
'p',
{},
'此次下载您已支付或无需付费,请确认下载'
),
h('p', {}, '此次下载您已支付或无需付费,请确认下载'),
]);
}
})

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

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

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

@ -13,11 +13,14 @@
<script setup lang="ts">
import { LinkOutline } from '@vicons/ionicons5';
const props = withDefaults(defineProps<{
links: Item.PostItemProps[]
}>(), {
links: () => []
});
const props = withDefaults(
defineProps<{
links: Item.PostItemProps[];
}>(),
{
links: () => [],
},
);
</script>
<style lang="less" scoped>

@ -11,11 +11,14 @@
</template>
<script setup lang="ts">
const props = withDefaults(defineProps<{
num: number,
}>(), {
num: 1
});
const props = withDefaults(
defineProps<{
num: number;
}>(),
{
num: 1,
},
);
</script>
<style lang="less" scoped>

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

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

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

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

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

@ -60,7 +60,7 @@ const props = withDefaults(
}>(),
{
show: false,
}
},
);
const content = ref('');
const loading = ref(false);

@ -60,7 +60,7 @@ const props = withDefaults(
}>(),
{
show: false,
}
},
);
const content = ref('');
const loading = ref(false);

@ -1,20 +1,20 @@
import { createApp } from 'vue'
import router from './router'
import store from './store'
import App from './App.vue'
import { createApp } from 'vue';
import router from './router';
import store from './store';
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 {
interface Window {
$message: MessageApiInjection,
$store: any
$message: MessageApiInjection;
$store: any;
}
}

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

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

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

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

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

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

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

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

@ -2,12 +2,12 @@
* @file 格式化日期
*/
import moment from "moment";
import "moment/dist/locale/zh-cn";
moment.locale("zh-cn");
import moment from 'moment';
import 'moment/dist/locale/zh-cn';
moment.locale('zh-cn');
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) => {
@ -22,9 +22,9 @@ export const formatPrettyTime = (time: number) => {
let mt = moment.unix(time);
let now = moment();
if (mt.year() != now.year()) {
return mt.utc(true).format("YYYY-MM-DD HH:mm");
} else if (moment().diff(mt, "month") > 3) {
return mt.utc(true).format("MM-DD HH:mm");
return mt.utc(true).format('YYYY-MM-DD HH:mm');
} else if (moment().diff(mt, 'month') > 3) {
return mt.utc(true).format('MM-DD HH:mm');
}
return mt.fromNow();
};
@ -33,13 +33,13 @@ export const formatPrettyDate = (time: number) => {
let mt = moment.unix(time);
let now = moment();
if (mt.year() != now.year()) {
return mt.utc(true).format("YYYY-MM-DD");
} else if (moment().diff(mt, "month") > 3) {
return mt.utc(true).format("MM-DD");
return mt.utc(true).format('YYYY-MM-DD');
} else if (moment().diff(mt, 'month') > 3) {
return mt.utc(true).format('MM-DD');
}
return mt.fromNow();
};
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> => {
const fileReader = new FileReader();
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);
};
@ -44,4 +48,4 @@ export const isZipFile = (file: File): Promise<unknown> => {
fileReader.readAsArrayBuffer(file.slice(0, 4));
});
}
};

@ -6,21 +6,22 @@ const service = axios.create({
});
service.interceptors.request.use(
config => {
(config) => {
// 鉴权Header
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;
},
error => {
(error) => {
return Promise.reject(error);
}
},
);
service.interceptors.response.use(
response => {
(response) => {
const { data = {}, code = 0 } = response?.data || {};
if (+code === 0) {
return data || {};
@ -44,7 +45,7 @@ service.interceptors.response.use(
window.$message.error(response?.data?.msg || '请求失败');
}
return Promise.reject(response?.data || {});
}
},
);
export default service;

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

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

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

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

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

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

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

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

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

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

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

@ -222,14 +222,10 @@ const handleRecharge = (amount: any) => {
rechargeQrcode.value = res.pay;
// 生成二维码
QRCode.toCanvas(
document.querySelector('#qrcode-container'),
res.pay,
{
QRCode.toCanvas(document.querySelector('#qrcode-container'), res.pay, {
width: 150,
margin: 2,
}
);
});
const s = setInterval(() => {
getRecharge({

8
web/src/vuex.d.ts vendored

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

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

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

Loading…
Cancel
Save