fix: 全局格式化

This commit is contained in:
Tim
2025-08-11 18:16:13 +08:00
parent 31cff70f63
commit 1c4df40f12
76 changed files with 1442 additions and 939 deletions

View File

@@ -10,11 +10,12 @@ export const authState = reactive({
loggedIn: false,
userId: null,
username: null,
role: null
role: null,
})
if (process.client) {
authState.loggedIn = localStorage.getItem(TOKEN_KEY) !== null && localStorage.getItem(TOKEN_KEY) !== ''
authState.loggedIn =
localStorage.getItem(TOKEN_KEY) !== null && localStorage.getItem(TOKEN_KEY) !== ''
authState.userId = localStorage.getItem(USER_ID_KEY)
authState.username = localStorage.getItem(USERNAME_KEY)
authState.role = localStorage.getItem(ROLE_KEY)
@@ -68,7 +69,7 @@ export async function fetchCurrentUser() {
if (!token) return null
try {
const res = await fetch(`${API_BASE_URL}/api/users/me`, {
headers: { Authorization: `Bearer ${token}` }
headers: { Authorization: `Bearer ${token}` },
})
if (!res.ok) return null
return await res.json()
@@ -94,7 +95,7 @@ export async function checkToken() {
if (!token) return false
try {
const res = await fetch(`${API_BASE_URL}/api/auth/check`, {
headers: { Authorization: `Bearer ${token}` }
headers: { Authorization: `Bearer ${token}` },
})
authState.loggedIn = res.ok
return res.ok

View File

@@ -1,5 +1,5 @@
export function clearVditorStorage() {
Object.keys(localStorage).forEach(key => {
Object.keys(localStorage).forEach((key) => {
if (key.startsWith('vditoreditor-') || key === 'vditor') {
localStorage.removeItem(key)
}

View File

@@ -18,7 +18,12 @@ export async function discordExchange(code, state, reason) {
const res = await fetch(`${API_BASE_URL}/api/auth/discord`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ code, redirectUri: `${window.location.origin}/discord-callback`, reason, state })
body: JSON.stringify({
code,
redirectUri: `${window.location.origin}/discord-callback`,
reason,
state,
}),
})
const data = await res.json()
if (res.ok && data.token) {
@@ -28,27 +33,27 @@ export async function discordExchange(code, state, reason) {
registerPush()
return {
success: true,
needReason: false
needReason: false,
}
} else if (data.reason_code === 'NOT_APPROVED') {
toast.info('当前为注册审核模式,请填写注册理由')
return {
success: false,
needReason: true,
token: data.token
token: data.token,
}
} else if (data.reason_code === 'IS_APPROVING') {
toast.info('您的注册理由正在审批中')
return {
success: true,
needReason: false
needReason: false,
}
} else {
toast.error(data.error || '登录失败')
return {
success: false,
needReason: false,
error: data.error || '登录失败'
error: data.error || '登录失败',
}
}
} catch (e) {
@@ -56,7 +61,7 @@ export async function discordExchange(code, state, reason) {
return {
success: false,
needReason: false,
error: '登录失败'
error: '登录失败',
}
}
}

View File

@@ -18,7 +18,12 @@ export async function githubExchange(code, state, reason) {
const res = await fetch(`${API_BASE_URL}/api/auth/github`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ code, redirectUri: `${window.location.origin}/github-callback`, reason, state })
body: JSON.stringify({
code,
redirectUri: `${window.location.origin}/github-callback`,
reason,
state,
}),
})
const data = await res.json()
if (res.ok && data.token) {
@@ -28,27 +33,27 @@ export async function githubExchange(code, state, reason) {
registerPush()
return {
success: true,
needReason: false
needReason: false,
}
} else if (data.reason_code === 'NOT_APPROVED') {
toast.info('当前为注册审核模式,请填写注册理由')
return {
success: false,
needReason: true,
token: data.token
token: data.token,
}
} else if (data.reason_code === 'IS_APPROVING') {
toast.info('您的注册理由正在审批中')
return {
success: true,
needReason: false
needReason: false,
}
} else {
toast.error(data.error || '登录失败')
return {
success: false,
needReason: false,
error: data.error || '登录失败'
error: data.error || '登录失败',
}
}
} catch (e) {
@@ -56,7 +61,7 @@ export async function githubExchange(code, state, reason) {
return {
success: false,
needReason: false,
error: '登录失败'
error: '登录失败',
}
}
}

View File

@@ -13,7 +13,7 @@ export async function googleGetIdToken() {
window.google.accounts.id.initialize({
client_id: GOOGLE_CLIENT_ID,
callback: ({ credential }) => resolve(credential),
use_fedcm: true
use_fedcm: true,
})
window.google.accounts.id.prompt()
})
@@ -35,7 +35,7 @@ export async function googleAuthWithToken(idToken, redirect_success, redirect_no
const res = await fetch(`${API_BASE_URL}/api/auth/google`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ idToken })
body: JSON.stringify({ idToken }),
})
const data = await res.json()
if (res.ok && data.token) {
@@ -72,8 +72,8 @@ export function loginWithGoogle() {
() => {
router.push('/')
},
token => {
(token) => {
router.push('/signup-reason?token=' + token)
}
},
)
}
}

View File

@@ -1,6 +1,6 @@
export const LEVEL_EXP = [100, 200, 300, 600, 1200, 10000]
export const prevLevelExp = level => {
export const prevLevelExp = (level) => {
if (level <= 0) return 0
if (level - 1 < LEVEL_EXP.length) return LEVEL_EXP[level - 1]
return LEVEL_EXP[LEVEL_EXP.length - 1]

View File

@@ -16,7 +16,7 @@ function mentionPlugin(md) {
tokenOpen.attrs = [
['href', `/users/${match[1]}`],
['target', '_blank'],
['class', 'mention-link']
['class', 'mention-link'],
]
const text = state.push('text', '', 0)
text.content = `@${match[1]}`
@@ -62,7 +62,7 @@ const md = new MarkdownIt({
code = hljs.highlightAuto(str).value
}
return `<pre class="code-block"><button class="copy-code-btn">Copy</button><code class="hljs language-${lang || ''}">${code}</code></pre>`
}
},
})
md.use(mentionPlugin)
@@ -89,7 +89,10 @@ export function stripMarkdown(text) {
// SSR 环境下没有 document
if (typeof window === 'undefined') {
// 用正则去除 HTML 标签
return html.replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim()
return html
.replace(/<[^>]+>/g, '')
.replace(/\s+/g, ' ')
.trim()
} else {
const el = document.createElement('div')
el.innerHTML = html

View File

@@ -2,7 +2,7 @@ export const medalTitles = {
COMMENT: '评论达人',
POST: '发帖达人',
SEED: '种子用户',
CONTRIBUTOR: '贡献者'
CONTRIBUTOR: '贡献者',
}
export function getMedalTitle(type) {

View File

@@ -3,7 +3,7 @@ import { getToken } from './auth'
import { reactive } from 'vue'
export const notificationState = reactive({
unreadCount: 0
unreadCount: 0,
})
export async function fetchUnreadCount() {
@@ -14,7 +14,7 @@ export async function fetchUnreadCount() {
return 0
}
const res = await fetch(`${API_BASE_URL}/api/notifications/unread-count`, {
headers: { Authorization: `Bearer ${token}` }
headers: { Authorization: `Bearer ${token}` },
})
if (!res.ok) {
notificationState.unreadCount = 0
@@ -37,9 +37,9 @@ export async function markNotificationsRead(ids) {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json'
'Content-Type': 'application/json',
},
body: JSON.stringify({ ids })
body: JSON.stringify({ ids }),
})
return res.ok
} catch (e) {

View File

@@ -2,7 +2,7 @@ import { API_BASE_URL } from '../main'
import { getToken } from './auth'
function urlBase64ToUint8Array(base64String) {
const padding = '='.repeat((4 - base64String.length % 4) % 4)
const padding = '='.repeat((4 - (base64String.length % 4)) % 4)
const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/')
const rawData = atob(base64)
const outputArray = new Uint8Array(rawData.length)
@@ -28,19 +28,19 @@ export async function registerPush() {
const { key } = await res.json()
const sub = await reg.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(key)
applicationServerKey: urlBase64ToUint8Array(key),
})
await fetch(`${API_BASE_URL}/api/push/subscribe`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${getToken()}`
Authorization: `Bearer ${getToken()}`,
},
body: JSON.stringify({
endpoint: sub.endpoint,
p256dh: arrayBufferToBase64(sub.getKey('p256dh')),
auth: arrayBufferToBase64(sub.getKey('auth'))
})
auth: arrayBufferToBase64(sub.getKey('auth')),
}),
})
} catch (e) {
// ignore

View File

@@ -21,5 +21,5 @@ export const reactionEmojiMap = {
CHINA: '🇨🇳',
USA: '🇺🇸',
JAPAN: '🇯🇵',
KOREA: '🇰🇷'
KOREA: '🇰🇷',
}

View File

@@ -16,11 +16,19 @@ export const useIsMobile = () => {
}
const mobileKeywords = [
'android', 'iphone', 'ipad', 'ipod', 'blackberry', 'windows phone',
'mobile', 'tablet', 'opera mini', 'iemobile'
'android',
'iphone',
'ipad',
'ipod',
'blackberry',
'windows phone',
'mobile',
'tablet',
'opera mini',
'iemobile',
]
return mobileKeywords.some(keyword => userAgent.includes(keyword))
return mobileKeywords.some((keyword) => userAgent.includes(keyword))
}
if (typeof window !== 'undefined') {
@@ -43,4 +51,3 @@ export const useIsMobile = () => {
return isMobileUserAgent()
})
}

View File

@@ -4,20 +4,22 @@ import { toast } from '~/main'
export const ThemeMode = {
SYSTEM: 'system',
LIGHT: 'light',
DARK: 'dark'
DARK: 'dark',
}
const THEME_KEY = 'theme-mode'
export const themeState = reactive({
mode: ThemeMode.SYSTEM
mode: ThemeMode.SYSTEM,
})
function apply(mode) {
if (!process.client) return
const root = document.documentElement
if (mode === ThemeMode.SYSTEM) {
root.dataset.theme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
root.dataset.theme = window.matchMedia('(prefers-color-scheme: dark)').matches
? 'dark'
: 'light'
} else {
root.dataset.theme = mode
}

View File

@@ -1,4 +1,5 @@
export const TIEBA_EMOJI_CDN = 'https://cdn.jsdelivr.net/gh/microlong666/tieba_mobile_emotions@master/'
export const TIEBA_EMOJI_CDN =
'https://cdn.jsdelivr.net/gh/microlong666/tieba_mobile_emotions@master/'
// export const TIEBA_EMOJI_CDN = 'https://openisle-1307107697.cos.ap-guangzhou.myqcloud.com/assert/vditor/dist/images/emoji/'
export const tiebaEmoji = (() => {

View File

@@ -52,8 +52,8 @@ export async function twitterExchange(code, state, reason) {
redirectUri: `${window.location.origin}/twitter-callback`,
reason,
state,
codeVerifier
})
codeVerifier,
}),
})
const data = await res.json()
if (res.ok && data.token) {

View File

@@ -22,7 +22,9 @@ export async function fetchAdmins() {
export async function searchUsers(keyword) {
if (!keyword) return []
try {
const res = await fetch(`${API_BASE_URL}/api/search/users?keyword=${encodeURIComponent(keyword)}`)
const res = await fetch(
`${API_BASE_URL}/api/search/users?keyword=${encodeURIComponent(keyword)}`,
)
return res.ok ? await res.json() : []
} catch (e) {
return []

View File

@@ -13,22 +13,17 @@ export function getPreviewTheme() {
}
export function createVditor(editorId, options = {}) {
const {
placeholder = '',
preview = {},
input,
after
} = options
const { placeholder = '', preview = {}, input, after } = options
const fetchMentions = async (value) => {
if (!value) {
const [followings, admins] = await Promise.all([
fetchFollowings(authState.username),
fetchAdmins()
fetchAdmins(),
])
const combined = [...followings, ...admins]
const seen = new Set()
return combined.filter(u => {
return combined.filter((u) => {
if (seen.has(u.id)) return false
seen.add(u.id)
return true
@@ -56,7 +51,7 @@ export function createVditor(editorId, options = {}) {
'redo',
'|',
'link',
'upload'
'upload',
]
let vditor
@@ -64,9 +59,12 @@ export function createVditor(editorId, options = {}) {
placeholder,
height: 'auto',
theme: getEditorTheme(),
preview: Object.assign({
theme: { current: getPreviewTheme() },
}, preview),
preview: Object.assign(
{
theme: { current: getPreviewTheme() },
},
preview,
),
hint: {
emoji: tiebaEmoji,
extend: [
@@ -74,9 +72,9 @@ export function createVditor(editorId, options = {}) {
key: '@',
hint: async (key) => {
const list = await fetchMentions(key)
return list.map(u => ({
return list.map((u) => ({
value: `@[${u.username}]`,
html: `<img src="${u.avatar}" /> @${u.username}`
html: `<img src="${u.avatar}" /> @${u.username}`,
}))
},
},
@@ -93,7 +91,7 @@ export function createVditor(editorId, options = {}) {
vditor.disabled()
const res = await fetch(
`${API_BASE_URL}/api/upload/presign?filename=${encodeURIComponent(file.name)}`,
{ headers: { Authorization: `Bearer ${getToken()}` } }
{ headers: { Authorization: `Bearer ${getToken()}` } },
)
if (!res.ok) {
vditor.enable()
@@ -122,7 +120,7 @@ export function createVditor(editorId, options = {}) {
'pjpeg',
'png',
'svg',
'webp'
'webp',
]
const audioExts = ['wav', 'mp3', 'ogg']
let md
@@ -137,7 +135,7 @@ export function createVditor(editorId, options = {}) {
vditor.enable()
vditor.tip('上传成功')
return null
}
},
},
// upload: {
// fieldName: 'file',
@@ -168,7 +166,7 @@ export function createVditor(editorId, options = {}) {
toolbarConfig: { pin: true },
cache: { enable: false },
input,
after
after,
})
return vditor