mirror of
https://github.com/nagisa77/OpenIsle.git
synced 2026-06-08 11:07:34 +08:00
fix: setup 迁移完成 v1
This commit is contained in:
@@ -11,29 +11,20 @@
|
||||
</BasePopup>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import BasePopup from '~/components/BasePopup.vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
export default {
|
||||
name: 'ActivityPopup',
|
||||
components: { BasePopup },
|
||||
props: {
|
||||
visible: { type: Boolean, default: false },
|
||||
icon: String,
|
||||
text: String,
|
||||
},
|
||||
emits: ['close'],
|
||||
setup(props, { emit }) {
|
||||
const router = useRouter()
|
||||
const gotoActivity = () => {
|
||||
emit('close')
|
||||
router.push('/activities')
|
||||
}
|
||||
const close = () => emit('close')
|
||||
return { gotoActivity, close }
|
||||
},
|
||||
const props = defineProps({
|
||||
visible: { type: Boolean, default: false },
|
||||
icon: String,
|
||||
text: String,
|
||||
})
|
||||
const emit = defineEmits(['close'])
|
||||
const gotoActivity = async () => {
|
||||
emit('close')
|
||||
await navigateTo('/activities', { replace: true })
|
||||
}
|
||||
const close = () => emit('close')
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -12,25 +12,15 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { useRouter } from 'vue-router'
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
category: { type: Object, default: null },
|
||||
})
|
||||
|
||||
export default {
|
||||
name: 'ArticleCategory',
|
||||
props: {
|
||||
category: { type: Object, default: null },
|
||||
},
|
||||
setup(props) {
|
||||
const router = useRouter()
|
||||
const gotoCategory = () => {
|
||||
if (!props.category) return
|
||||
const value = encodeURIComponent(props.category.id ?? props.category.name)
|
||||
router.push({ path: '/', query: { category: value } }).then(() => {
|
||||
window.location.reload()
|
||||
})
|
||||
}
|
||||
return { gotoCategory }
|
||||
},
|
||||
const gotoCategory = async () => {
|
||||
if (!props.category) return
|
||||
const value = encodeURIComponent(props.category.id ?? props.category.name)
|
||||
await navigateTo({ path: '/', query: { category: value } }, { replace: true })
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -17,24 +17,14 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { useRouter } from 'vue-router'
|
||||
<script setup>
|
||||
defineProps({
|
||||
tags: { type: Array, default: () => [] },
|
||||
})
|
||||
|
||||
export default {
|
||||
name: 'ArticleTags',
|
||||
props: {
|
||||
tags: { type: Array, default: () => [] },
|
||||
},
|
||||
setup() {
|
||||
const router = useRouter()
|
||||
const gotoTag = (tag) => {
|
||||
const value = encodeURIComponent(tag.id ?? tag.name)
|
||||
router.push({ path: '/', query: { tags: value } }).then(() => {
|
||||
window.location.reload()
|
||||
})
|
||||
}
|
||||
return { gotoTag }
|
||||
},
|
||||
const gotoTag = async (tag) => {
|
||||
const value = encodeURIComponent(tag.id ?? tag.name)
|
||||
await navigateTo({ path: '/', query: { tags: value } }, { replace: true })
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -91,7 +91,6 @@
|
||||
<script setup>
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import VueEasyLightbox from 'vue-easy-lightbox'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { toast } from '~/main'
|
||||
import { authState, getToken } from '~/utils/auth'
|
||||
import { handleMarkdownClick, renderMarkdown } from '~/utils/markdown'
|
||||
@@ -121,7 +120,6 @@ const props = defineProps({
|
||||
|
||||
const emit = defineEmits(['deleted'])
|
||||
|
||||
const router = useRouter()
|
||||
const showReplies = ref(props.level === 0 ? true : props.defaultShowReplies)
|
||||
watch(
|
||||
() => props.defaultShowReplies,
|
||||
@@ -237,11 +235,11 @@ const submitReply = async (parentUserName, text, clear) => {
|
||||
reply: [],
|
||||
openReplies: false,
|
||||
src: r.author.avatar,
|
||||
iconClick: () => router.push(`/users/${r.author.id}`),
|
||||
iconClick: () => navigateTo(`/users/${r.author.id}`),
|
||||
})),
|
||||
openReplies: false,
|
||||
src: data.author.avatar,
|
||||
iconClick: () => router.push(`/users/${data.author.id}`),
|
||||
iconClick: () => navigateTo(`/users/${data.author.id}`),
|
||||
})
|
||||
clear()
|
||||
showEditor.value = false
|
||||
|
||||
@@ -15,9 +15,11 @@
|
||||
import ActivityPopup from '~/components/ActivityPopup.vue'
|
||||
import MedalPopup from '~/components/MedalPopup.vue'
|
||||
import NotificationSettingPopup from '~/components/NotificationSettingPopup.vue'
|
||||
import { API_BASE_URL } from '~/main'
|
||||
import { authState } from '~/utils/auth'
|
||||
|
||||
const config = useRuntimeConfig()
|
||||
const API_BASE_URL = config.public.apiBaseUrl
|
||||
|
||||
const showMilkTeaPopup = ref(false)
|
||||
const milkTeaIcon = ref('')
|
||||
const showNotificationPopup = ref(false)
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
</header>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { ClientOnly } from '#components'
|
||||
import { computed, nextTick, ref, watch } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
@@ -57,141 +57,109 @@ import SearchDropdown from '~/components/SearchDropdown.vue'
|
||||
import { authState, clearToken, loadCurrentUser } from '~/utils/auth'
|
||||
import { fetchUnreadCount, notificationState } from '~/utils/notification'
|
||||
import { useIsMobile } from '~/utils/screen'
|
||||
|
||||
export default {
|
||||
name: 'HeaderComponent',
|
||||
components: { DropdownMenu, SearchDropdown },
|
||||
props: {
|
||||
showMenuBtn: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
const props = defineProps({
|
||||
showMenuBtn: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
setup(props, { expose }) {
|
||||
const isLogin = computed(() => authState.loggedIn)
|
||||
const isMobile = useIsMobile()
|
||||
const unreadCount = computed(() => notificationState.unreadCount)
|
||||
const router = useRouter()
|
||||
const avatar = ref('')
|
||||
const showSearch = ref(false)
|
||||
const searchDropdown = ref(null)
|
||||
const userMenu = ref(null)
|
||||
const menuBtn = ref(null)
|
||||
})
|
||||
|
||||
expose({
|
||||
menuBtn,
|
||||
})
|
||||
const isLogin = computed(() => authState.loggedIn)
|
||||
const isMobile = useIsMobile()
|
||||
const unreadCount = computed(() => notificationState.unreadCount)
|
||||
const router = useRouter()
|
||||
const avatar = ref('')
|
||||
const showSearch = ref(false)
|
||||
const searchDropdown = ref(null)
|
||||
const userMenu = ref(null)
|
||||
const menuBtn = ref(null)
|
||||
|
||||
const goToHome = () => {
|
||||
router.push('/').then(() => {
|
||||
window.location.reload()
|
||||
})
|
||||
const goToHome = async () => {
|
||||
await navigateTo('/', { replace: true })
|
||||
}
|
||||
const search = () => {
|
||||
showSearch.value = true
|
||||
nextTick(() => {
|
||||
searchDropdown.value.toggle()
|
||||
})
|
||||
}
|
||||
const closeSearch = () => {
|
||||
nextTick(() => {
|
||||
showSearch.value = false
|
||||
})
|
||||
}
|
||||
const goToLogin = () => {
|
||||
navigateTo('/login', { replace: true })
|
||||
}
|
||||
const goToSettings = () => {
|
||||
navigateTo('/settings', { replace: true })
|
||||
}
|
||||
const goToProfile = async () => {
|
||||
if (!authState.loggedIn) {
|
||||
navigateTo('/login', { replace: true })
|
||||
return
|
||||
}
|
||||
let id = authState.username || authState.userId
|
||||
if (!id) {
|
||||
const user = await loadCurrentUser()
|
||||
if (user) {
|
||||
id = user.username || user.id
|
||||
}
|
||||
const search = () => {
|
||||
showSearch.value = true
|
||||
nextTick(() => {
|
||||
searchDropdown.value.toggle()
|
||||
})
|
||||
}
|
||||
const closeSearch = () => {
|
||||
nextTick(() => {
|
||||
showSearch.value = false
|
||||
})
|
||||
}
|
||||
const goToLogin = () => {
|
||||
router.push('/login')
|
||||
}
|
||||
const goToSettings = () => {
|
||||
router.push('/settings')
|
||||
}
|
||||
const goToProfile = async () => {
|
||||
if (!authState.loggedIn) {
|
||||
router.push('/login')
|
||||
return
|
||||
}
|
||||
let id = authState.username || authState.userId
|
||||
if (!id) {
|
||||
const user = await loadCurrentUser()
|
||||
if (user) {
|
||||
id = user.username || user.id
|
||||
}
|
||||
}
|
||||
if (id) {
|
||||
router.push(`/users/${id}`)
|
||||
}
|
||||
if (id) {
|
||||
navigateTo(`/users/${id}`, { replace: true })
|
||||
}
|
||||
}
|
||||
const goToSignup = () => {
|
||||
navigateTo('/signup', { replace: true })
|
||||
}
|
||||
const goToLogout = () => {
|
||||
clearToken()
|
||||
navigateTo('/login', { replace: true })
|
||||
}
|
||||
|
||||
const headerMenuItems = computed(() => [
|
||||
{ text: '设置', onClick: goToSettings },
|
||||
{ text: '个人主页', onClick: goToProfile },
|
||||
{ text: '退出', onClick: goToLogout },
|
||||
])
|
||||
|
||||
onMounted(async () => {
|
||||
const updateAvatar = async () => {
|
||||
if (authState.loggedIn) {
|
||||
const user = await loadCurrentUser()
|
||||
if (user && user.avatar) {
|
||||
avatar.value = user.avatar
|
||||
}
|
||||
}
|
||||
const goToSignup = () => {
|
||||
router.push('/signup')
|
||||
}
|
||||
const goToLogout = () => {
|
||||
clearToken()
|
||||
this.$router.push('/login')
|
||||
}
|
||||
const updateUnread = async () => {
|
||||
if (authState.loggedIn) {
|
||||
await fetchUnreadCount()
|
||||
} else {
|
||||
notificationState.unreadCount = 0
|
||||
}
|
||||
}
|
||||
|
||||
const headerMenuItems = computed(() => [
|
||||
{ text: '设置', onClick: goToSettings },
|
||||
{ text: '个人主页', onClick: goToProfile },
|
||||
{ text: '退出', onClick: goToLogout },
|
||||
])
|
||||
|
||||
onMounted(async () => {
|
||||
const updateAvatar = async () => {
|
||||
if (authState.loggedIn) {
|
||||
const user = await loadCurrentUser()
|
||||
if (user && user.avatar) {
|
||||
avatar.value = user.avatar
|
||||
}
|
||||
}
|
||||
}
|
||||
const updateUnread = async () => {
|
||||
if (authState.loggedIn) {
|
||||
await fetchUnreadCount()
|
||||
} else {
|
||||
notificationState.unreadCount = 0
|
||||
}
|
||||
}
|
||||
await updateAvatar()
|
||||
await updateUnread()
|
||||
|
||||
watch(
|
||||
() => authState.loggedIn,
|
||||
async () => {
|
||||
await updateAvatar()
|
||||
await updateUnread()
|
||||
},
|
||||
)
|
||||
|
||||
watch(
|
||||
() => authState.loggedIn,
|
||||
async () => {
|
||||
await updateAvatar()
|
||||
await updateUnread()
|
||||
},
|
||||
)
|
||||
|
||||
watch(
|
||||
() => router.currentRoute.value.fullPath,
|
||||
() => {
|
||||
if (userMenu.value) userMenu.value.close()
|
||||
showSearch.value = false
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
return {
|
||||
isLogin,
|
||||
isMobile,
|
||||
headerMenuItems,
|
||||
unreadCount,
|
||||
goToHome,
|
||||
search,
|
||||
closeSearch,
|
||||
goToLogin,
|
||||
goToSettings,
|
||||
goToProfile,
|
||||
goToSignup,
|
||||
goToLogout,
|
||||
showSearch,
|
||||
searchDropdown,
|
||||
userMenu,
|
||||
avatar,
|
||||
menuBtn,
|
||||
}
|
||||
},
|
||||
}
|
||||
watch(
|
||||
() => router.currentRoute.value.fullPath,
|
||||
() => {
|
||||
if (userMenu.value) userMenu.value.close()
|
||||
showSearch.value = false
|
||||
},
|
||||
)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -9,18 +9,9 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
export default {
|
||||
name: 'LoginOverlay',
|
||||
setup() {
|
||||
const router = useRouter()
|
||||
const goLogin = () => {
|
||||
router.push('/login')
|
||||
}
|
||||
return { goLogin }
|
||||
},
|
||||
<script setup>
|
||||
const goLogin = () => {
|
||||
navigateTo('/login', { replace: true })
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -16,33 +16,25 @@
|
||||
</BasePopup>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import BasePopup from '~/components/BasePopup.vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { authState } from '~/utils/auth'
|
||||
|
||||
export default {
|
||||
name: 'MedalPopup',
|
||||
components: { BasePopup },
|
||||
props: {
|
||||
visible: { type: Boolean, default: false },
|
||||
medals: { type: Array, default: () => [] },
|
||||
},
|
||||
emits: ['close'],
|
||||
setup(props, { emit }) {
|
||||
const router = useRouter()
|
||||
const gotoMedals = () => {
|
||||
emit('close')
|
||||
if (authState.username) {
|
||||
router.push(`/users/${authState.username}?tab=achievements`)
|
||||
} else {
|
||||
router.push('/')
|
||||
}
|
||||
}
|
||||
const close = () => emit('close')
|
||||
return { gotoMedals, close }
|
||||
},
|
||||
defineProps({
|
||||
visible: { type: Boolean, default: false },
|
||||
medals: { type: Array, default: () => [] },
|
||||
})
|
||||
const emit = defineEmits(['close'])
|
||||
|
||||
const gotoMedals = () => {
|
||||
emit('close')
|
||||
if (authState.username) {
|
||||
navigateTo(`/users/${authState.username}?tab=achievements`, { replace: true })
|
||||
} else {
|
||||
navigateTo('/', { replace: true })
|
||||
}
|
||||
}
|
||||
const close = () => emit('close')
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -124,10 +124,10 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, watch, onMounted } from 'vue'
|
||||
import { themeState, cycleTheme, ThemeMode } from '~/utils/theme'
|
||||
import { authState } from '~/utils/auth'
|
||||
import { fetchUnreadCount, notificationState } from '~/utils/notification'
|
||||
import { ref, computed, watch, onMounted } from 'vue'
|
||||
const config = useRuntimeConfig()
|
||||
const API_BASE_URL = config.public.apiBaseUrl
|
||||
|
||||
@@ -140,7 +140,6 @@ const props = defineProps({
|
||||
|
||||
const emit = defineEmits(['item-click'])
|
||||
|
||||
const router = useRouter()
|
||||
const categoryOpen = ref(true)
|
||||
const tagOpen = ref(true)
|
||||
const isLoadingCategory = ref(false)
|
||||
@@ -193,9 +192,7 @@ onMounted(async () => {
|
||||
})
|
||||
|
||||
const handleHomeClick = () => {
|
||||
router.push('/').then(() => {
|
||||
window.location.reload()
|
||||
})
|
||||
navigateTo('/', { replace: true })
|
||||
}
|
||||
|
||||
const handleItemClick = () => {
|
||||
@@ -209,13 +206,13 @@ const isImageIcon = (icon) => {
|
||||
|
||||
const gotoCategory = (c) => {
|
||||
const value = encodeURIComponent(c.id ?? c.name)
|
||||
router.push({ path: '/', query: { category: value } })
|
||||
navigateTo({ path: '/', query: { category: value } }, { replace: true })
|
||||
handleItemClick()
|
||||
}
|
||||
|
||||
const gotoTag = (t) => {
|
||||
const value = encodeURIComponent(t.id ?? t.name)
|
||||
router.push({ path: '/', query: { tags: value } })
|
||||
navigateTo({ path: '/', query: { tags: value } }, { replace: true })
|
||||
handleItemClick()
|
||||
}
|
||||
|
||||
|
||||
@@ -11,27 +11,19 @@
|
||||
</BasePopup>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import BasePopup from '~/components/BasePopup.vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
export default {
|
||||
name: 'NotificationSettingPopup',
|
||||
components: { BasePopup },
|
||||
props: {
|
||||
visible: { type: Boolean, default: false },
|
||||
},
|
||||
emits: ['close'],
|
||||
setup(props, { emit }) {
|
||||
const router = useRouter()
|
||||
const gotoSetting = () => {
|
||||
emit('close')
|
||||
router.push('/message?tab=control')
|
||||
}
|
||||
const close = () => emit('close')
|
||||
return { gotoSetting, close }
|
||||
},
|
||||
defineProps({
|
||||
visible: { type: Boolean, default: false },
|
||||
})
|
||||
const emit = defineEmits(['close'])
|
||||
|
||||
const gotoSetting = () => {
|
||||
emit('close')
|
||||
navigateTo('/message?tab=control', { replace: true })
|
||||
}
|
||||
const close = () => emit('close')
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -54,6 +54,17 @@ import { reactionEmojiMap } from '~/utils/reactions'
|
||||
const config = useRuntimeConfig()
|
||||
const API_BASE_URL = config.public.apiBaseUrl
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const props = defineProps({
|
||||
modelValue: { type: Array, default: () => [] },
|
||||
contentType: { type: String, required: true },
|
||||
contentId: { type: [Number, String], required: true },
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(v) => (reactions.value = v),
|
||||
)
|
||||
|
||||
const reactions = ref(props.modelValue)
|
||||
const reactionTypes = ref([])
|
||||
|
||||
@@ -76,17 +87,6 @@ const fetchTypes = async () => {
|
||||
return cachedTypes
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: { type: Array, default: () => [] },
|
||||
contentType: { type: String, required: true },
|
||||
contentId: { type: [Number, String], required: true },
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(v) => (reactions.value = v),
|
||||
)
|
||||
|
||||
onMounted(async () => {
|
||||
reactionTypes.value = await fetchTypes()
|
||||
})
|
||||
|
||||
@@ -37,17 +37,15 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue'
|
||||
import { useIsMobile } from '~/utils/screen'
|
||||
import { useRouter } from 'vue-router'
|
||||
import Dropdown from '~/components/Dropdown.vue'
|
||||
import { stripMarkdown } from '~/utils/markdown'
|
||||
import { ref, watch } from 'vue'
|
||||
const config = useRuntimeConfig()
|
||||
const API_BASE_URL = config.public.apiBaseUrl
|
||||
|
||||
const emit = defineEmits(['close'])
|
||||
|
||||
const router = useRouter()
|
||||
const keyword = ref('')
|
||||
const selected = ref(null)
|
||||
const results = ref([])
|
||||
@@ -97,17 +95,17 @@ watch(selected, (val) => {
|
||||
const opt = results.value.find((r) => r.id === val)
|
||||
if (!opt) return
|
||||
if (opt.type === 'post' || opt.type === 'post_title') {
|
||||
router.push(`/posts/${opt.id}`)
|
||||
navigateTo(`/posts/${opt.id}`, { replace: true })
|
||||
} else if (opt.type === 'user') {
|
||||
router.push(`/users/${opt.id}`)
|
||||
navigateTo(`/users/${opt.id}`, { replace: true })
|
||||
} else if (opt.type === 'comment') {
|
||||
if (opt.postId) {
|
||||
router.push(`/posts/${opt.postId}#comment-${opt.id}`)
|
||||
navigateTo(`/posts/${opt.postId}#comment-${opt.id}`, { replace: true })
|
||||
}
|
||||
} else if (opt.type === 'category') {
|
||||
router.push({ path: '/', query: { category: opt.id } })
|
||||
navigateTo({ path: '/', query: { category: opt.id } }, { replace: true })
|
||||
} else if (opt.type === 'tag') {
|
||||
router.push({ path: '/', query: { tags: opt.id } })
|
||||
navigateTo({ path: '/', query: { tags: opt.id } }, { replace: true })
|
||||
}
|
||||
selected.value = null
|
||||
keyword.value = ''
|
||||
|
||||
@@ -11,20 +11,15 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import BasePlaceholder from '~/components/BasePlaceholder.vue'
|
||||
|
||||
export default {
|
||||
name: 'UserList',
|
||||
components: { BasePlaceholder },
|
||||
props: {
|
||||
users: { type: Array, default: () => [] },
|
||||
},
|
||||
methods: {
|
||||
handleUserClick(user) {
|
||||
this.$router.push(`/users/${user.id}`)
|
||||
},
|
||||
},
|
||||
defineProps({
|
||||
users: { type: Array, default: () => [] },
|
||||
})
|
||||
|
||||
const handleUserClick = (user) => {
|
||||
navigateTo(`/users/${user.id}`, { replace: true })
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user