fix(mobile): 统一移动端汉堡菜单与PC端用户菜单选项
CI / Backend tests (push) Canceled after 0s
CI / Frontend build (push) Canceled after 0s

- SettingDrawer 新增「重新扫描」「包清单定时配置」,与 PC 端 AppTopbar pick() 保持一致
- 引入 useStore 读取 loading 状态,扫描中禁用重新扫描项
- 引入 PkgListConfigDialog,点击「包清单定时配置」弹出与 PC 端一致
- App.vue SettingDrawer 新增 @rescan=doRescan 事件监听
- 补充 .disabled 样式,扫描时置灰不可点
This commit is contained in:
yinjun.chen1
2026-09-21 23:03:39 +08:00
parent 765d9f5170
commit 72699ae422
3 changed files with 396 additions and 371 deletions
+1 -1
View File
@@ -101,7 +101,7 @@ const fmtScanBytes = computed(() => {
</router-view> </router-view>
<MobileTabbar v-if="!isLogin() && isMobile()" :kb="kbOpen" /> <MobileTabbar v-if="!isLogin() && isMobile()" :kb="kbOpen" />
<SettingDrawer v-model="settingsOpen" /> <SettingDrawer v-model="settingsOpen" @rescan="doRescan" />
</template> </template>
<style scoped> <style scoped>
+26 -1
View File
@@ -1,13 +1,18 @@
<script setup> <script setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { useTheme } from '../composables/useTheme' import { useTheme } from '../composables/useTheme'
import { useStore } from '../store'
import api from '../api' import api from '../api'
import { storage } from '../utils/storage' import { storage } from '../utils/storage'
import PkgListConfigDialog from './PkgListConfigDialog.vue'
const props = defineProps({ modelValue: Boolean }) const props = defineProps({ modelValue: Boolean })
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue', 'rescan'])
const router = useRouter() const router = useRouter()
const { theme, toggle } = useTheme() const { theme, toggle } = useTheme()
const { state } = useStore()
const pkgConfigOpen = ref(false)
const user = storage.getJSON('vcm-user', { name: '管理员', email: 'admin@verdaccio.local' }) const user = storage.getJSON('vcm-user', { name: '管理员', email: 'admin@verdaccio.local' })
@@ -15,11 +20,22 @@ function close() {
emit('update:modelValue', false) emit('update:modelValue', false)
} }
function goRescan() {
if (state.loading) return
close()
emit('rescan')
}
function goThresholds() { function goThresholds() {
close() close()
router.push('/thresholds') router.push('/thresholds')
} }
function goPkgConfig() {
close()
pkgConfigOpen.value = true
}
async function logout() { async function logout() {
await api.logout() // 先销毁后端会话并清本地 token,再跳登录页 await api.logout() // 先销毁后端会话并清本地 token,再跳登录页
close() close()
@@ -46,6 +62,9 @@ async function logout() {
<span>{{ user.email }}</span> <span>{{ user.email }}</span>
</div> </div>
</div> </div>
<div class="m-drawer-item" :class="{ disabled: state.loading }" @click="goRescan">
<span style="font-family: var(--sans)">{{ state.loading ? '⏳ 扫描中…' : '🔄 重新扫描' }}</span>
</div>
<div class="m-drawer-item" @click="toggle"> <div class="m-drawer-item" @click="toggle">
<span style="font-family: var(--sans)">🌙 主题切换</span> <span style="font-family: var(--sans)">🌙 主题切换</span>
<span>{{ theme === 'dark' ? '暗色 ▸' : '亮色 ▸' }}</span> <span>{{ theme === 'dark' ? '暗色 ▸' : '亮色 ▸' }}</span>
@@ -54,6 +73,10 @@ async function logout() {
<span style="font-family: var(--sans)">⚙️ 预警设置</span> <span style="font-family: var(--sans)">⚙️ 预警设置</span>
<span>阈值 ▸</span> <span>阈值 ▸</span>
</div> </div>
<div class="m-drawer-item" @click="goPkgConfig">
<span style="font-family: var(--sans)">⏱️ 包清单定时配置</span>
<span>定时 ▸</span>
</div>
<div class="m-drawer-item"> <div class="m-drawer-item">
<span style="font-family: var(--sans)">📦 版本信息</span> <span style="font-family: var(--sans)">📦 版本信息</span>
<span>v1.0.0</span> <span>v1.0.0</span>
@@ -65,6 +88,7 @@ async function logout() {
</aside> </aside>
</Transition> </Transition>
</Teleport> </Teleport>
<PkgListConfigDialog v-model:visible="pkgConfigOpen" />
</template> </template>
<style scoped> <style scoped>
@@ -149,6 +173,7 @@ async function logout() {
transition: .15s; transition: .15s;
} }
.m-drawer-item:hover { background: var(--orange-soft); color: var(--orange); } .m-drawer-item:hover { background: var(--orange-soft); color: var(--orange); }
.m-drawer-item.disabled { opacity: .5; pointer-events: none; }
.m-drawer-item span { font-family: var(--num); font-size: 11px; color: var(--ink-faint); font-weight: 600; white-space: nowrap; } .m-drawer-item span { font-family: var(--num); font-size: 11px; color: var(--ink-faint); font-weight: 600; white-space: nowrap; }
.m-drawer-item span:first-child { font-family: var(--sans); font-size: 13px; color: var(--ink); font-weight: 600; } .m-drawer-item span:first-child { font-family: var(--sans); font-size: 13px; color: var(--ink); font-weight: 600; }
.m-drawer-item:hover span:first-child { color: var(--orange); } .m-drawer-item:hover span:first-child { color: var(--orange); }
+1 -1
View File
@@ -9,7 +9,7 @@ import PkgLogo from '../components/PkgLogo.vue'
import { useStore, fmtSize } from '../store' import { useStore, fmtSize } from '../store'
import { storage } from '../utils/storage' import { storage } from '../utils/storage'
const { state, stats, refreshPackages, ignorePkg, unignorePkg, cleanPkg, deleteVersion, syncLatest, const { state, refreshPackages, ignorePkg, unignorePkg, deleteVersion, syncLatest,
refreshPkgList, refreshPkgListConfig, triggerPkgPull } = useStore() refreshPkgList, refreshPkgListConfig, triggerPkgPull } = useStore()
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()