Compare commits

...

10 Commits

Author SHA1 Message Date
CharleeWa 1156ef497b chore: release v3.6.0 2025-02-20 22:15:33 +08:00
CharleeWa 831732c719 chore: replace husky with simple-git-hooks (#143) 2025-02-20 22:12:54 +08:00
CharleeWa 24f15fde5c refactor: Update viewport containing block config (#129) 2025-02-19 11:04:11 +08:00
CharleeWa dd4d5e83f0 chore: Update all deps 2025-02-19 10:28:00 +08:00
CharleeWa 637360f8dc chore: release v3.5.3 2025-02-16 20:25:07 +08:00
CharleeWa c489b81c4b refactor: clean dark mode 2025-02-16 20:21:11 +08:00
CharleeWa e9913758ba chore: release v3.5.2 2025-02-14 13:36:11 +08:00
CharleeWa 9157e69046 chore: use eslint builtin ts config file support (#112) 2025-02-14 13:25:53 +08:00
CharleeWa 131d4e38d4 chore: Downgrade pnpm from v10 to v9
- nodejs/corepack#612
2025-02-10 14:46:44 +08:00
CharleeWa 0ad1afb26f chore: Update all deps 2025-02-10 10:19:53 +08:00
15 changed files with 2287 additions and 2106 deletions

View File

@ -1 +0,0 @@
node scripts/verifyCommit.js

View File

@ -1 +0,0 @@
pnpm lint

32
commitlint.config.ts Normal file
View File

@ -0,0 +1,32 @@
import type { UserConfig } from '@commitlint/types'
import { RuleConfigSeverity } from '@commitlint/types'
const Configuration: UserConfig = {
extends: ['@commitlint/config-conventional'],
formatter: '@commitlint/format',
rules: {
'type-enum': [
RuleConfigSeverity.Error,
'always',
[
'feat',
'fix',
'perf',
'style',
'docs',
'test',
'refactor',
'build',
'ci',
'chore',
'revert',
'wip',
'workflow',
'types',
'release',
],
],
},
}
export default Configuration

View File

@ -1,92 +1,97 @@
{
"name": "vue3-vant-mobile",
"type": "module",
"version": "3.5.1",
"version": "3.6.0",
"packageManager": "pnpm@9.15.4",
"description": "An mobile web apps template based on the Vue 3 ecosystem",
"license": "MIT",
"scripts": {
"dev": "cross-env MOCK_SERVER_PORT=8086 vite",
"build": "vue-tsc --noEmit && vite build",
"build:dev": "vue-tsc --noEmit && vite build --mode=development",
"preview": "vite preview",
"test": "vitest",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"test": "vitest",
"release": "bumpp --commit --push --tag",
"prepare": "husky",
"typecheck": "vue-tsc --noEmit"
"typecheck": "vue-tsc --noEmit",
"commitlint": "commitlint --edit",
"prepare": "simple-git-hooks"
},
"dependencies": {
"@unhead/vue": "^1.11.18",
"@unhead/vue": "~1.11.19",
"@vant/touch-emulator": "^1.4.0",
"@vant/use": "^1.6.0",
"@vueuse/core": "^12.5.0",
"@vueuse/core": "^12.7.0",
"axios": "^1.7.9",
"echarts": "^5.6.0",
"lodash-es": "^4.17.21",
"nprogress": "^0.2.0",
"pinia": "^2.3.1",
"pinia": "^3.0.1",
"pinia-plugin-persistedstate": "^4.2.0",
"resize-detector": "^0.3.0",
"vant": "^4.9.16",
"vant": "^4.9.17",
"vconsole": "^3.15.1",
"vue": "^3.5.13",
"vue-i18n": "^11.0.1",
"vue-i18n": "^11.1.1",
"vue-router": "^4.5.0"
},
"devDependencies": {
"@antfu/eslint-config": "4.1.0",
"@iconify-json/carbon": "^1.2.5",
"@antfu/eslint-config": "4.3.0",
"@commitlint/cli": "^19.7.1",
"@commitlint/config-conventional": "^19.7.1",
"@commitlint/types": "^19.5.0",
"@iconify-json/carbon": "^1.2.7",
"@intlify/unplugin-vue-i18n": "^6.0.3",
"@types/lodash-es": "^4.17.12",
"@types/node": "^22.10.10",
"@types/node": "^22.13.4",
"@types/nprogress": "^0.2.3",
"@unocss/eslint-plugin": "65.4.3",
"@unocss/preset-rem-to-px": "65.4.3",
"@unocss/eslint-plugin": "66.0.0",
"@unocss/preset-rem-to-px": "66.0.0",
"@vant/auto-import-resolver": "^1.2.1",
"@vitejs/plugin-legacy": "^6.0.0",
"@vitejs/plugin-legacy": "^6.0.1",
"@vitejs/plugin-vue": "^5.2.1",
"autoprefixer": "^10.4.20",
"bumpp": "^10.0.1",
"bumpp": "^10.0.3",
"consola": "^3.4.0",
"cross-env": "^7.0.3",
"eslint": "^9.19.0",
"eslint": "^9.20.1",
"eslint-plugin-format": "^1.0.1",
"husky": "^9.1.7",
"less": "^4.2.2",
"lint-staged": "^15.4.3",
"mockjs": "^1.1.0",
"postcss-mobile-forever": "^4.3.2",
"rollup": "^4.32.0",
"terser": "^5.37.0",
"postcss-mobile-forever": "^4.4.0",
"rollup": "^4.34.8",
"simple-git-hooks": "^2.11.1",
"terser": "^5.39.0",
"typescript": "^5.7.3",
"unocss": "65.4.3",
"unplugin-auto-import": "^19.0.0",
"unplugin-vue-components": "^28.0.0",
"unocss": "66.0.0",
"unplugin-auto-import": "^19.1.0",
"unplugin-vue-components": "^28.2.0",
"unplugin-vue-router": "^0.11.2",
"vite": "^6.0.11",
"vite-plugin-mock-dev-server": "^1.8.3",
"vite": "^6.1.0",
"vite-plugin-mock-dev-server": "^1.8.4",
"vite-plugin-pwa": "^0.21.1",
"vite-plugin-sitemap": "^0.7.1",
"vite-plugin-vconsole": "^2.1.1",
"vite-plugin-vue-devtools": "^7.7.1",
"vitest": "^3.0.4",
"vue-tsc": "^2.2.0"
"vite-plugin-vue-devtools": "^7.7.2",
"vitest": "^3.0.6",
"vue-tsc": "^2.2.2"
},
"pnpm": {
"allowedDeprecatedVersions": {
"glob": "7.2.3",
"inflight": "1.0.6",
"sourcemap-codec": "1.4.8"
},
"peerDependencyRules": {
"allowedVersions": {
"@intlify/shared": "^11.x",
"vue-i18n": "^11.x"
}
}
},
"resolutions": {
"vite": "^6.0.11"
"vite": "^6.1.0"
},
"simple-git-hooks": {
"pre-commit": "pnpm lint-staged",
"commit-msg": "pnpm commitlint $1"
},
"lint-staged": {
"*": "eslint --fix"
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +0,0 @@
import fs from 'node:fs'
import process from 'node:process'
const msg = fs.readFileSync('.git/COMMIT_EDITMSG', 'utf-8').trim()
const commitRE = /^(revert: )?(feat|fix|docs|dx|style|refactor|perf|test|workflow|build|ci|chore|types|wip|release)(\(.+\))?: .{1,50}/
const mergeRe = /^(Merge pull request|Merge branch)/
if (!commitRE.test(msg)) {
if (!mergeRe.test(msg)) {
console.log('git commit unpass')
console.error('git commit error, needs title(scope): desc')
process.exit(1)
}
}
else {
console.log('git commit pass')
}

View File

@ -1,8 +1,5 @@
<script setup lang="ts">
import { storeToRefs } from 'pinia'
import useAppStore from '@/stores/modules/app'
import useRouteCache from '@/stores/modules/routeCache'
import useAutoThemeSwitcher from '@/hooks/useAutoThemeSwitcher'
useHead({
title: 'Vue3 Vant Mobile',
@ -25,23 +22,18 @@ useHead({
],
})
const appStore = useAppStore()
const { mode } = storeToRefs(appStore)
const { initializeThemeSwitcher } = useAutoThemeSwitcher(appStore)
const keepAliveRouteNames = computed(() => {
return useRouteCache().routeCaches as string[]
})
onMounted(() => {
initializeThemeSwitcher()
const mode = computed(() => {
return isDark.value ? 'dark' : 'light'
})
</script>
<template>
<VanConfigProvider :theme="mode">
<NavBar />
<van-config-provider :theme="mode">
<nav-bar />
<router-view v-slot="{ Component, route }">
<section class="app-wrapper">
<keep-alive :include="keepAliveRouteNames">
@ -49,8 +41,8 @@ onMounted(() => {
</keep-alive>
</section>
</router-view>
<TabBar />
</VanConfigProvider>
<tab-bar />
</van-config-provider>
</template>
<style scoped>

View File

@ -1,6 +1,6 @@
const contrastColor = 'rgba(255, 255, 255, 0.65)'
const backgroundColor = 'transparent'
const axisCommon = function () {
function axisCommon() {
return {
axisLine: {
lineStyle: {

View File

@ -1,24 +0,0 @@
import type { AppStore } from '@/stores/modules/app'
export default function useAutoThemeSwitcher(appStore: AppStore) {
const handleAttributeChange = () => {
const rootElement = document.documentElement
const mode = rootElement.classList.contains('dark') ? 'dark' : 'light'
appStore.switchMode(mode)
}
const observerOptions = {
attributes: true,
attributeFilter: ['class'],
}
const observer = new MutationObserver(handleAttributeChange)
const targetElement = document.querySelector('html')
const initializeThemeSwitcher = () => {
observer.observe(targetElement, observerOptions)
}
return { initializeThemeSwitcher }
}

View File

@ -1,26 +1,18 @@
<script setup lang="ts">
import type { PickerColumn } from 'vant'
import useAppStore from '@/stores/modules/app'
import { languageColumns, locale } from '@/utils/i18n'
const appStore = useAppStore()
const checked = ref<boolean>(isDark.value)
watch(
() => isDark.value,
(newMode) => {
checked.value = newMode
},
{ immediate: true },
)
function toggle() {
toggleDark()
appStore.switchMode(isDark.value ? 'dark' : 'light')
}
const { t } = useI18n()
const menuItems = computed(() => ([
{ title: t('menus.mockGuide'), route: 'mock' },
{ title: t('menus.echartsDemo'), route: 'charts' },
{ title: t('menus.unocssExample'), route: 'unocss' },
{ title: t('menus.persistPiniaState'), route: 'counter' },
{ title: t('menus.keepAlive'), route: 'keepalive' },
{ title: t('menus.404Demo'), route: 'unknown' },
]))
const showLanguagePicker = ref(false)
const languageValues = ref<Array<string>>([locale.value])
const language = computed(() => languageColumns.find(l => l.value === locale.value).text)
@ -30,37 +22,44 @@ function onLanguageConfirm(event: { selectedOptions: PickerColumn }) {
showLanguagePicker.value = false
}
const menuItems = computed(() => ([
{ title: t('menus.mockGuide'), route: 'mock' },
{ title: t('menus.echartsDemo'), route: 'charts' },
{ title: t('menus.unocssExample'), route: 'unocss' },
{ title: t('menus.persistPiniaState'), route: 'counter' },
{ title: t('menus.keepAlive'), route: 'keepalive' },
{ title: t('menus.404Demo'), route: 'unknown' },
]))
const checked = ref<boolean>(isDark.value)
watchEffect(() => {
checked.value = isDark.value
})
function toggle(val: boolean) {
checked.value = val
toggleDark()
}
</script>
<template>
<VanCellGroup :title="t('menus.basicSettings')" :border="false" :inset="true">
<VanCell center :title="t('menus.darkMode')">
<van-cell-group :title="t('menus.basicSettings')" :border="false" :inset="true">
<van-cell center :title="t('menus.darkMode')">
<template #right-icon>
<VanSwitch v-model="checked" size="20px" aria-label="on/off Dark Mode" @click="toggle()" />
<van-switch
v-model="checked"
size="20px"
aria-label="on/off Dark Mode"
@change="toggle"
/>
</template>
</VanCell>
</van-cell>
<VanCell
<van-cell
is-link
:title="t('menus.language')"
:value="language"
@click="showLanguagePicker = true"
/>
</VanCellGroup>
</van-cell-group>
<VanCellGroup :title="t('menus.exampleComponents')" :border="false" :inset="true">
<van-cell-group :title="t('menus.exampleComponents')" :border="false" :inset="true">
<template v-for="item in menuItems" :key="item.route">
<VanCell :title="item.title" :to="item.route" is-link />
<van-cell :title="item.title" :to="item.route" is-link />
</template>
</VanCellGroup>
</van-cell-group>
<van-popup v-model:show="showLanguagePicker" position="bottom">
<van-picker

View File

@ -1,11 +1,10 @@
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
import useAppStore from './modules/app'
import useUserStore from './modules/user'
const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)
export { useAppStore, useUserStore }
export { useUserStore }
export default pinia

View File

@ -1,28 +0,0 @@
import { defineStore } from 'pinia'
import type { ConfigProviderTheme } from 'vant'
export interface AppStore {
switchMode: (val: ConfigProviderTheme) => void
}
const prefersDark
= window.matchMedia
&& window.matchMedia('(prefers-color-scheme: dark)').matches
const useAppStore = defineStore('app', () => {
const theme = prefersDark ? 'dark' : 'light'
const mode = ref<ConfigProviderTheme>(theme)
const switchMode = (val: ConfigProviderTheme) => {
mode.value = val
}
return {
mode,
switchMode,
}
}, {
persist: true,
})
export default useAppStore

View File

@ -1,32 +1,26 @@
import {
defineConfig,
presetAttributify,
presetIcons,
presetMini,
presetUno,
} from 'unocss'
import presetRemToPx from '@unocss/preset-rem-to-px'
// 刚使用unocss的朋友可以借助这个工具 https://to-unocss.netlify.app
export default defineConfig({
presets: [
presetUno,
presetAttributify,
presetIcons(),
// 为什么要用到这个插件?
// 模板使用 viewport 作为移动端适配方案unocss 默认单位为 rem
// 所以需要转成 px然后由 postcss 把 px 转成 vw/vh完成适配
presetRemToPx({
// 这里为什么要设置基础字体大小?看下面这篇文章
// https://juejin.cn/post/7262975395620618298
baseFontSize: 4,
}),
presetMini(),
],
shortcuts: [
// shortcuts to multiple utilities
['btn', 'px-6 py-3 rounded-3 border-none inline-block bg-green-400 text-white cursor-pointer !outline-none hover:bg-green-600 disabled:cursor-default disabled:bg-gray-600 disabled:opacity-50'],
],
})
import {
defineConfig,
presetAttributify,
presetIcons,
presetMini,
} from 'unocss'
import presetWind3 from '@unocss/preset-wind3'
// https://unocss.dev/presets/rem-to-px
import presetRemToPx from '@unocss/preset-rem-to-px'
export default defineConfig({
presets: [
presetWind3(),
presetAttributify,
presetIcons(),
presetRemToPx({
baseFontSize: 4,
}),
presetMini(),
],
shortcuts: [
// shortcuts to multiple utilities
['btn', 'px-6 py-3 rounded-3 border-none inline-block bg-green-400 text-white cursor-pointer !outline-none hover:bg-green-600 disabled:cursor-default disabled:bg-gray-600 disabled:opacity-50'],
],
})

View File

@ -45,10 +45,7 @@ export default ({ mode }: ConfigEnv): UserConfig => {
appSelector: '#app',
viewportWidth: 375,
maxDisplayWidth: 600,
rootContainingBlockSelectorList: [
'van-tabbar',
'van-popup',
],
appContainingBlock: 'auto',
border: true,
}),
],