Skip to content

Commit

Permalink
fix: 使用路由守卫更新页面 title
Browse files Browse the repository at this point in the history
enchant: 搜索框移动到 TopBar 中
fix: 修改设置页面翻译
  • Loading branch information
HoshinoSuzumi committed Jun 14, 2023
1 parent 48a43c7 commit 1a28d63
Show file tree
Hide file tree
Showing 10 changed files with 184 additions and 72 deletions.
4 changes: 2 additions & 2 deletions api/gateway.js
@@ -1,8 +1,8 @@
export default axios => ({
call: (mod, method, params = null, file = null) => {
call: (mod, method, params = null, file = null, progress = true) => {
let formData = new FormData();
if (params) formData.append('args', JSON.stringify(params));
if (file) formData.append('file', file);
return axios.post(`/gateway/call/${mod}?method=${method}`, formData)
return axios.post(`/gateway/call/${mod}?method=${method}`, formData, {progress: progress})
},
})
2 changes: 1 addition & 1 deletion api/releases.js
Expand Up @@ -2,6 +2,6 @@ import gateway from "~/api/gateway";

export default axios => ({
releases_behind: (timestamp) => {
return gateway(axios).call('releasenote', 'releases_behind', {timestamp: timestamp});
return gateway(axios).call('releasenote', 'releases_behind', {timestamp: timestamp}, null, false);
}
})
136 changes: 83 additions & 53 deletions components/TopBar.vue
Expand Up @@ -2,18 +2,20 @@
<div>
<div
class="fixed z-20 top-0 w-full bg-white/80 dark:bg-slate-900/80 backdrop-blur-md transition-shadow flex flex-col items-center h-16"
:class="{'shadow dark:shadow-slate-800/50 hover:shadow-md': !isToolPage()}"
:class="{'shadow dark:shadow-slate-800/50 hover:shadow-md': !showMiniBar}"
>
<div class="w-full h-16 px-4 container flex justify-between items-center">
<div>
<nuxt-link :to="localePath('/')" class="text-lg dark:text-slate-200">
<div class="w-fit h-full flex flex-row items-center space-x-2.5 ml-1">
<img src="/icon.svg" class="w-6 h-6" alt="CTFever Logo">
<span
:class="{'subtitle-show': isToolPage() || isTagPage(), 'cursor-default pointer-events-none': !(isToolPage() || isTagPage())}"
class="font-medium cursor-pointer pointer-events-auto transition duration-500 translate-x-2 opacity-0">{{
getTagName ?? currentToolName
}}</span>
class="font-medium cursor-default pointer-events-none transition duration-500 translate-x-2 opacity-0 w-fit"
:class="{
'subtitle-show cursor-pointer pointer-events-auto': appbarTitle.show
}">
{{ appbarTitle.title }}
</span>
</div>
</nuxt-link>
</div>
Expand All @@ -22,50 +24,36 @@
$t('topbar.install_pwa')
}}
</UniButton>
<a-dropdown :trigger="['hover']" placement="bottomRight">
<div class="hidden md:block">
<UniInput v-model="searchText" placeholder="搜索" hotkey="ctrl+k"/>
</div>
<div class="flex flex-row items-center gap-4">
<a-dropdown :trigger="['hover']" placement="bottomRight">
<span class="ant-dropdown-link cursor-pointer" @click="e => e.preventDefault()">
<Icon icon="prime:language" class="text-xl inline -mt-1 pointer-events-none"/>
</span>
<a-menu slot="overlay" class="dark:bg-slate-800">
<a-menu-item v-for="(locale, k) in availableLocales" :key="k">
<nuxt-link
class="px-2 py-px"
:key="locale.code"
:to="switchLocalePath(locale.code)">{{ locale.name }}
</nuxt-link>
</a-menu-item>
</a-menu>
</a-dropdown>
<!-- <a-dropdown :trigger="['hover']" placement="bottomRight">-->
<!-- <span class="ant-dropdown-link cursor-pointer" @click="e => e.preventDefault()">-->
<!-- <Icon :icon="currentAppearanceIcon" class="text-lg inline -mt-1 pointer-events-none transition"/>-->
<!-- </span>-->
<!-- <a-menu slot="overlay" class="dark:bg-slate-800">-->
<!-- <a-menu-item v-for="(mode, k) in colorModes" :key="k"-->
<!-- class="flex flex-row items-center space-x-0.5 dark:text-slate-300"-->
<!-- :class="{'dropdown-item-active': $store.state.settings.settings.appearance === mode.code}"-->
<!-- @click="switchDarkMode(mode.code)">-->
<!-- <Icon :icon="mode.icon" class="text-lg inline"/>-->
<!-- <nuxt-link-->
<!-- class="px-2 py-px"-->
<!-- :class="{'dropdown-item-active': $store.state.settings.settings.appearance === mode.code}"-->
<!-- :key="mode.code"-->
<!-- :to="switchLocalePath(mode.code)">{{ $t(mode.name) }}-->
<!-- </nuxt-link>-->
<!-- </a-menu-item>-->
<!-- </a-menu>-->
<!-- </a-dropdown>-->
<nuxt-link :to="localePath('/settings')">
<Icon icon="tabler:settings-2" class="text-lg inline -mt-1 pointer-events-none"/>
</nuxt-link>
<a-menu slot="overlay" class="dark:bg-slate-800">
<a-menu-item v-for="(locale, k) in availableLocales" :key="k">
<nuxt-link
class="px-2 py-px"
:key="locale.code"
:to="switchLocalePath(locale.code)">{{ locale.name }}
</nuxt-link>
</a-menu-item>
</a-menu>
</a-dropdown>
<nuxt-link :to="localePath('/settings')">
<Icon icon="tabler:settings-2" class="text-lg inline -mt-1"/>
</nuxt-link>
</div>
<!-- TODO: CTFever Premium -->
<!-- <TinyButtonLink :to="localePath('/premium-active')" accent>Premium</TinyButtonLink> -->
</div>
</div>
</div>
<div
class="fixed z-10 top-16 w-full h-8 bg-white/80 dark:bg-slate-900/80 backdrop-blur-md opacity-0 -translate-y-8 transition duration-500 flex flex-col items-center"
:class="{'shadow dark:shadow-slate-800/50 hover:shadow-md opacity-100 translate-y-0': isToolPage()}"
:class="{'shadow dark:shadow-slate-800/50 hover:shadow-md opacity-100 translate-y-0': showMiniBar}"
>
<div class="w-full h-full px-4 container flex justify-between items-center border-t border-t-gray-150
dark:border-t-slate-700 dark:text-slate-300">
Expand Down Expand Up @@ -110,6 +98,12 @@ import {Icon} from "@iconify/vue2";
export default {
name: "TopBar",
components: {Icon, TinyButtonLink},
props: {
title: {
type: String,
default: ''
},
},
computed: {
availableLocales() {
return this.$i18n.locales.filter(i => i.code !== this.$i18n.locale)
Expand Down Expand Up @@ -141,9 +135,15 @@ export default {
}
return icon;
},
getTagName() {
return this.isTagPage() ? this.$t(`tags.${this.$route.params.tag}`) : null;
currentTitle() {
return this.$store.state.runtime.currentTitle;
},
showTitle() {
return !!this.currentTitle;
},
showMiniBar() {
return this.$store.state.runtime.showMiniBar;
}
},
data() {
return {
Expand All @@ -164,26 +164,31 @@ export default {
icon: 'tabler:device-desktop-cog'
}
],
isToolPage: () => /^.*\/tools\/.*/.test(this.currentPath),
isTagPage: () => /^.*\/tag\/.*/.test(this.currentPath),
isMarked: false,
currentToolName: '',
appbarTitle: {
show: false,
title: ''
},
pwaAvailable: false,
deferredPrompt: null,
isDrawerOpen: false,
searchText: '',
}
},
mounted() {
const self = this;
this.$nextTick(() => {
this.updateMarkStatus(this.currentPath);
this.updateTitle(this.currentPath);
this.updateTitle(true);
});
window.addEventListener('beforeinstallprompt', (e) => {
// e.preventDefault();
self.pwaAvailable = true;
this.deferredPrompt = e;
});
if (this.$route.query.q) {
this.searchText = this.$route.query.q;
}
},
methods: {
markTool() {
Expand All @@ -197,12 +202,18 @@ export default {
updateMarkStatus(route) {
this.markedTools.filter(f => f.route === wrapI18nPath2MetaRoute(route)).length > 0 ? this.isMarked = true : this.isMarked = false;
},
updateTitle(route) {
if (this.isToolPage()) {
this.currentToolName = this.$t(getToolByRoute(route).title);
}
if (this.isTagPage()) {
this.currentToolName = this.getTagName;
updateTitle(show) {
if (show) {
this.appbarTitle.show = false
setTimeout(() => {
this.appbarTitle.show = true
this.appbarTitle.title = this.$t(this.currentTitle)
}, 500)
} else {
this.appbarTitle.show = false
setTimeout(() => {
this.appbarTitle.title = ''
}, 500)
}
},
switchDarkMode(mode) {
Expand Down Expand Up @@ -232,11 +243,30 @@ export default {
watch: {
currentPath(val) {
this.updateMarkStatus(val);
this.updateTitle(val);
},
isDrawerOpen(val) {
this.$emit('switchDrawer', val);
},
currentTitle(val) {
this.updateTitle(true);
},
showTitle(val) {
this.updateTitle(val);
},
searchText(val) {
if (val) {
this.$router.push({
path: this.localePath('/'),
query: {
q: val
}
});
} else {
this.$router.push({
path: this.localePath('/')
});
}
}
},
}
</script>
Expand All @@ -257,6 +287,6 @@ export default {
}
.subtitle-show {
@apply translate-x-0 opacity-100;
@apply !translate-x-0 !opacity-100;
}
</style>
10 changes: 9 additions & 1 deletion components/uni/Input.vue
Expand Up @@ -81,6 +81,14 @@ export default defineComponent({
}
},
methods: {
onFocus() {
this.focused = true
this.$emit('focus')
},
onBlur() {
this.focused = false
this.$emit('blur')
},
validate(str) {
if (this.pattern) {
this.pattern.lastIndex = 0;
Expand Down Expand Up @@ -135,7 +143,7 @@ export default defineComponent({
'!border-red-500': !isValid,
[inputClass]: inputClass
}"
:id="inputFieldId" @focus="focused = true" @blur="focused = false"
:id="inputFieldId" @focus="onFocus" @blur="onBlur"
v-model="inputText" :type="type"
:disabled="disabled" ref="input"
:placeholder="placeholder"/>
Expand Down
3 changes: 3 additions & 0 deletions lang/en-US.js
Expand Up @@ -150,6 +150,9 @@ export default {
desc: 'Tools that you marked as favorite',
},
},
settings: {
title: 'Preferences'
},
notFound: {
title: 'Page Not Found',
message: 'The spirit of exploration is valuable, but unfortunately there is nothing here :(',
Expand Down
3 changes: 3 additions & 0 deletions lang/zh-CN.js
Expand Up @@ -150,6 +150,9 @@ export default {
desc: '收藏的常用工具集'
},
},
settings: {
title: '首选项'
},
notFound: {
title: '未找到页面',
message: '探索的精神可贵,但很遗憾这里什么都没有 :(',
Expand Down
13 changes: 12 additions & 1 deletion layouts/default.vue
Expand Up @@ -2,7 +2,7 @@
<div class="flex-col min-h-screen antialiased dark:bg-slate-900 flex">
<script async src="https://analytics.uniiem.com/script.js"
data-website-id="6426a9b9-ff68-4701-967a-546d0574b5e4"></script>
<TopBar ref="topbar" @switchDrawer="switchDrawer"/>
<TopBar ref="topbar" :title="'TEST'" @switchDrawer="switchDrawer"/>
<div class="container mx-auto p-4 pt-20 overscroll-none"
:class="{'pt-28': isToolPage(), 'pt-20': !isToolPage()}">
<Nuxt/>
Expand Down Expand Up @@ -129,6 +129,14 @@ import {Icon} from "@iconify/vue2";
export default {
name: "index",
components: {Icon, PrimaryInput, Tool},
middleware: ['title-guard'],
asyncData(context) {
const myRoute = context.app.data.myRoute
return {
myRoute
}
},
computed: {
currentAppearance() {
return this.$store.state.settings.settings.appearance;
Expand Down Expand Up @@ -313,6 +321,9 @@ export default {
this.$refs.topbar.isDrawerOpen = false;
}, 150);
}
},
myRoute(val) {
console.log(val)
}
},
methods: {
Expand Down
32 changes: 32 additions & 0 deletions middleware/title-guard.js
@@ -0,0 +1,32 @@
import {getToolByRoute} from "~/libs/common";

const preferences = {
previousPath: ''
}

const regexps = {
index: /^index/i,
tools: /^tools/i,
tag: /^tag/i,
settings: /^settings/i,
}

export default function ({route, store, app}) {
if (route.path !== preferences.previousPath) {
if (regexps.index.test(route.name)) {
store.commit('runtime/setCurrentTitle', '')
} else if (regexps.tools.test(route.name)) {
const universalPath = route.path.replace(/^\/[a-z]{2}\//i, '/')
store.commit('runtime/setCurrentTitle', getToolByRoute(universalPath).title)
} else if (regexps.tag.test(route.name)) {
store.commit('runtime/setCurrentTitle', `tags.${route.params.tag}`)
} else if (regexps.settings.test(route.name)) {
store.commit('runtime/setCurrentTitle', 'page.settings.title')
}

store.commit('runtime/setShowMiniBar', regexps.tools.test(route.name))
} else {
/* ignore */
}
preferences.previousPath = route.path
}

1 comment on commit 1a28d63

@vercel
Copy link

@vercel vercel bot commented on 1a28d63 Jun 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.