fix: 修复已知的问题和更新相关的依赖

This commit is contained in:
fonghehe 2026-01-22 16:44:03 +08:00
parent 58addfde56
commit 293bcb0291
33 changed files with 4702 additions and 3945 deletions

View File

@ -16,6 +16,7 @@
"ShallowRef": true, "ShallowRef": true,
"Slot": true, "Slot": true,
"Slots": true, "Slots": true,
"Snackbar": true,
"VNode": true, "VNode": true,
"WritableComputedRef": true, "WritableComputedRef": true,
"acceptHMRUpdate": true, "acceptHMRUpdate": true,
@ -71,6 +72,7 @@
"shallowReactive": true, "shallowReactive": true,
"shallowReadonly": true, "shallowReadonly": true,
"shallowRef": true, "shallowRef": true,
"showToast": true,
"storeToRefs": true, "storeToRefs": true,
"toRaw": true, "toRaw": true,
"toRef": true, "toRef": true,

View File

@ -1,5 +1,22 @@
{ {
"recommendations": [ "recommendations": [
"vue.volar" // Vue 3
"Vue.volar",
// ESLint JavaScript VS Code
"dbaeumer.vscode-eslint",
// 使 Prettier
"esbenp.prettier-vscode",
// dotenv
"mikestead.dotenv",
//
"streetsidesoftware.code-spell-checker",
// i18n
"Lokalise.i18n-ally",
// CSS
"vunguyentuan.vscode-css-variables",
],
"unwantedRecommendations": [
// volar
"octref.vetur"
] ]
} }

24
.vscode/settings.json vendored
View File

@ -87,21 +87,8 @@
"source.fixAll.eslint": "explicit" "source.fixAll.eslint": "explicit"
}, },
"[vue]": { "[vue]": {
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.fixAll.stylelint": "explicit"
},
"editor.defaultFormatter": "esbenp.prettier-vscode" "editor.defaultFormatter": "esbenp.prettier-vscode"
}, },
"i18n-ally.localesPaths": ["src/locales/lang"],
"i18n-ally.keystyle": "nested",
"i18n-ally.sortKeys": true,
"i18n-ally.namespace": true,
"i18n-ally.pathMatcher": "{locale}/{namespaces}.{ext}",
"i18n-ally.enabledParsers": ["ts"],
"i18n-ally.sourceLanguage": "en",
"i18n-ally.displayLanguage": "zh-CN",
"i18n-ally.enabledFrameworks": ["vue", "react"],
"cSpell.words": [ "cSpell.words": [
"antd", "antd",
"antv", "antv",
@ -147,5 +134,14 @@
"windi", "windi",
"windicss", "windicss",
"zxcvbn" "zxcvbn"
] ],
"i18n-ally.localesPaths": ["src/locales/langs"],
"i18n-ally.pathMatcher": "{locale}/{namespace}.{ext}",
"i18n-ally.enabledParsers": ["json"],
"i18n-ally.sourceLanguage": "en",
"i18n-ally.displayLanguage": "zh-CN",
"i18n-ally.enabledFrameworks": ["vue", "react"],
"i18n-ally.keystyle": "nested",
"i18n-ally.sortKeys": true,
"i18n-ally.namespace": true
} }

View File

@ -21,6 +21,6 @@ export const ConfigAutoComponentsPlugin = () => {
directives: true, directives: true,
include: [/\.vue$/, /\.vue\?vue/, /\.md$/], include: [/\.vue$/, /\.vue\?vue/, /\.md$/],
exclude: [/[\\/]node_modules[\\/]/, /[\\/]\.git[\\/]/, /[\\/]\.nuxt[\\/]/], exclude: [/[\\/]node_modules[\\/]/, /[\\/]\.git[\\/]/, /[\\/]\.nuxt[\\/]/],
resolvers: [VueUseComponentsResolver(), VantResolver(), VarletImportResolver(), NutUIResolver({ importStyle: 'sass' })], resolvers: [VueUseComponentsResolver(), VantResolver(), VarletImportResolver(), NutUIResolver()],
}); });
}; };

View File

@ -6,7 +6,6 @@ import skipFormatting from '@vue/eslint-config-prettier/skip-formatting';
export default defineConfigWithVueTs( export default defineConfigWithVueTs(
pluginVue.configs['flat/essential'], pluginVue.configs['flat/essential'],
vueTsConfigs.recommended, vueTsConfigs.recommended,
skipFormatting, skipFormatting,
{ {
name: 'app/files-to-lint', name: 'app/files-to-lint',
@ -17,6 +16,5 @@ export default defineConfigWithVueTs(
'vue/multi-word-component-names': 'off', 'vue/multi-word-component-names': 'off',
}, },
}, },
globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']), globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']),
); );

2554
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -16,65 +16,65 @@
"dependencies": { "dependencies": {
"@nutui/icons-vue": "^0.1.1", "@nutui/icons-vue": "^0.1.1",
"@nutui/nutui": "^4.3.13", "@nutui/nutui": "^4.3.13",
"@varlet/ui": "^3.12.0", "@varlet/ui": "^3.13.0",
"@vueuse/core": "13.9.0", "@vueuse/core": "14.1.0",
"@vueuse/integrations": "13.9.0", "@vueuse/integrations": "14.1.0",
"axios": "1.12.2", "axios": "1.13.2",
"dayjs": "^1.11.18", "dayjs": "^1.11.19",
"mitt": "^3.0.1", "mitt": "^3.0.1",
"pinia": "^3.0.2", "pinia": "^3.0.4",
"pinia-plugin-persistedstate": "^4.5.0", "pinia-plugin-persistedstate": "^4.7.1",
"universal-cookie": "^8.0.1", "universal-cookie": "^8.0.1",
"vant": "^4.9.19", "vant": "^4.9.22",
"vue": "^3.5.22", "vue": "^3.5.27",
"vue-i18n": "^11.1.12", "vue-i18n": "^11.2.8",
"vue-router": "^4.6.3" "vue-router": "^4.6.4"
}, },
"devDependencies": { "devDependencies": {
"@commitlint/cli": "^20.1.0", "@commitlint/cli": "^20.3.1",
"@commitlint/config-conventional": "^20.0.0", "@commitlint/config-conventional": "^20.3.1",
"@nutui/auto-import-resolver": "^1.0.0", "@nutui/auto-import-resolver": "^1.0.0",
"@stylistic/stylelint-plugin": "^4.0.0", "@stylistic/stylelint-plugin": "^4.0.0",
"@tsconfig/node22": "^22.0.2", "@tsconfig/node22": "^22.0.5",
"@types/jsdom": "^21.1.7", "@types/jsdom": "^21.1.7",
"@types/node": "^24.8.1", "@types/node": "^24.8.1",
"@typescript-eslint/parser": "^8.46.1", "@typescript-eslint/parser": "^8.53.1",
"@vant/auto-import-resolver": "^1.3.0", "@vant/auto-import-resolver": "^1.3.0",
"@varlet/import-resolver": "^3.12.0", "@varlet/import-resolver": "^3.13.0",
"@vitejs/plugin-basic-ssl": "^2.0.0", "@vitejs/plugin-basic-ssl": "^2.1.4",
"@vitejs/plugin-legacy": "^7.2.1", "@vitejs/plugin-legacy": "^7.2.1",
"@vitejs/plugin-vue": "^6.0.1", "@vitejs/plugin-vue": "^6.0.3",
"@vitejs/plugin-vue-jsx": "^5.1.1", "@vitejs/plugin-vue-jsx": "^5.1.3",
"@vue/eslint-config-prettier": "^10.2.0", "@vue/eslint-config-prettier": "^10.2.0",
"@vue/eslint-config-typescript": "^14.5.0", "@vue/eslint-config-typescript": "^14.5.0",
"@vue/test-utils": "^2.4.0", "@vue/test-utils": "^2.4.0",
"@vue/tsconfig": "^0.8.1", "@vue/tsconfig": "^0.8.1",
"@zhaojjiang/vite-plugin-eruda": "^0.0.5", "@zhaojjiang/vite-plugin-eruda": "^0.0.5",
"amfe-flexible": "^2.2.1", "amfe-flexible": "^2.2.1",
"autoprefixer": "^10.4.21", "autoprefixer": "^10.4.23",
"cnjm-postcss-px-to-viewport": "^1.0.1", "cnjm-postcss-px-to-viewport": "^1.0.1",
"consola": "^3.4.2", "consola": "^3.4.2",
"cross-env": "^10.0.0", "cross-env": "^10.1.0",
"cz-git": "^1.11.1", "cz-git": "^1.11.1",
"czg": "^1.11.1", "czg": "^1.11.1",
"eruda": "^3.4.1", "eruda": "^3.4.1",
"eslint": "^9.37.0", "eslint": "^9.39.2",
"eslint-define-config": "^2.1.0", "eslint-define-config": "^2.1.0",
"eslint-plugin-import": "^2.31.0", "eslint-plugin-import": "^2.31.0",
"eslint-plugin-prettier": "^5.5.4", "eslint-plugin-prettier": "^5.5.5",
"eslint-plugin-simple-import-sort": "^12.1.1", "eslint-plugin-simple-import-sort": "^12.1.1",
"eslint-plugin-vue": "^10.5.1", "eslint-plugin-vue": "^10.7.0",
"git-cz": "^4.9.0", "git-cz": "^4.9.0",
"husky": "9.1.7", "husky": "9.1.7",
"jsdom": "^26.1.0", "jsdom": "^27.4.0",
"lint-staged": "16.2.4", "lint-staged": "16.2.7",
"mockjs": "^1.1.0", "mockjs": "^1.1.0",
"node": "^22.18.0", "node": "^22.18.0",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"postcss": "^8.5.3", "postcss": "^8.5.3",
"postcss-html": "1.8.0", "postcss-html": "1.8.1",
"postcss-scss": "^4.0.9", "postcss-scss": "^4.0.9",
"prettier": "^3.5.3", "prettier": "^3.8.0",
"rollup-plugin-visualizer": "^6.0.5", "rollup-plugin-visualizer": "^6.0.5",
"stylelint": "^16.25.0", "stylelint": "^16.25.0",
"stylelint-config-recess-order": "^7.4.0", "stylelint-config-recess-order": "^7.4.0",
@ -82,27 +82,27 @@
"stylelint-config-recommended-scss": "^16.0.0", "stylelint-config-recommended-scss": "^16.0.0",
"stylelint-config-recommended-vue": "^1.5.0", "stylelint-config-recommended-vue": "^1.5.0",
"stylelint-config-standard": "^39.0.1", "stylelint-config-standard": "^39.0.1",
"stylelint-order": "^7.0.0", "stylelint-order": "^7.0.1",
"stylelint-prettier": "^5.0.3", "stylelint-prettier": "^5.0.3",
"stylelint-scss": "^6.11.0", "stylelint-scss": "^6.11.0",
"terser": "^5.19.0", "terser": "^5.46.0",
"typescript": "5.9.3", "typescript": "5.9.3",
"unplugin-auto-import": "^20.2.0", "unplugin-auto-import": "^21.0.0",
"unplugin-vue-components": "^29.1.0", "unplugin-vue-components": "^31.0.0",
"vite": "^7.1.10", "vite": "^7.3.1",
"vite-plugin-compression": "^0.5.1", "vite-plugin-compression": "^0.5.1",
"vite-plugin-imagemin": "^0.6.1", "vite-plugin-imagemin": "^0.6.1",
"vite-plugin-mock": "^3.0.2", "vite-plugin-mock": "^3.0.2",
"vite-plugin-pages": "^0.33.0", "vite-plugin-pages": "^0.33.2",
"vite-plugin-progress": "^0.0.7", "vite-plugin-progress": "^0.0.7",
"vite-plugin-pwa": "^1.1.0", "vite-plugin-pwa": "^1.2.0",
"vite-plugin-qrcode": "^0.3.0", "vite-plugin-qrcode": "^0.3.0",
"vite-plugin-restart": "^1.0.0", "vite-plugin-restart": "^2.0.0",
"vite-plugin-svg-icons": "^2.0.1", "vite-plugin-svg-icons": "^2.0.1",
"vite-plugin-vue-setup-extend-plus": "^0.1.0", "vite-plugin-vue-setup-extend-plus": "^0.1.0",
"vitest": "^3.1.3", "vitest": "^4.0.17",
"vue-eslint-parser": "^10.1.3", "vue-eslint-parser": "^10.1.3",
"vue-tsc": "^3.1.1" "vue-tsc": "^3.2.2"
}, },
"engines": { "engines": {
"node": ">=20.10.0", "node": ">=20.10.0",
@ -141,7 +141,6 @@
"prettier --write" "prettier --write"
] ]
}, },
"packageManager": "pnpm@10.26.2",
"config": { "config": {
"commitizen": { "commitizen": {
"path": "node_modules/cz-git" "path": "node_modules/cz-git"

2338
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

View File

@ -1,27 +0,0 @@
import { createI18n } from 'vue-i18n';
export function loadLang() {
const modules: Record<string, any> = import.meta.glob('./lang/*.ts', { eager: true });
const langs: Record<string, any> = {};
for (const path in modules) {
const name = path.replace(/(\.\/lang\/|\.ts)/g, '');
langs[name] = modules[path].lang;
}
return langs;
}
export const i18n = createI18n({
// globalInjection: true,
legacy: false,
locale: 'zh-cn',
fallbackLocale: 'zh-cn',
messages: loadLang(),
});
export function setLang(locale?: string) {
if (locale) {
localStorage.setItem('lang', locale);
}
i18n.global.locale.value = locale || localStorage.getItem('lang') || '';
}

View File

@ -1,27 +0,0 @@
import type { langType } from './lang-base';
export const lang: langType = {
title: 'VUE H5 development template',
tabbar: {
home: 'Home',
list: 'List',
member: 'Member',
demo: 'demo',
},
language: {
en: 'English',
zh: 'Chinese',
},
introduction: 'A rapid development vue3 of mobile terminal template',
home: {
support: 'support',
cssMultiLanguage: 'CSS picture multi-language',
},
list: {
details: 'list details',
},
btn: {
confirm: 'confirm',
cancel: 'cancel',
},
};

View File

@ -1,27 +0,0 @@
import type { langType } from './lang-base';
export const lang: langType = {
title: 'VUE H5开发模板',
tabbar: {
home: '首页',
list: '列表',
member: '我的',
demo: '示例',
},
language: {
en: '英文',
zh: '中文',
},
introduction: '一个快速开发vue3的移动端模板',
home: {
support: '支持',
cssMultiLanguage: 'css图片多语言',
},
list: {
details: '列表详情',
},
btn: {
confirm: '确认',
cancel: '取消',
},
};

View File

@ -1,16 +1,25 @@
<template> <template>
<van-nav-bar :title="$t($route.meta.title as string)" :left-arrow="!tabbarVisible" @click-left="goBack" /> <div class="main-page">
<div class="main-page" :class="{ tabbar: tabbarVisible, border: showBorder }"> <van-nav-bar :title="$t($route.meta.title as string)" :left-arrow="!tabbarVisible" @click-left="goBack" />
<RouterView v-slot="{ Component }" v-if="$route.meta.keepAlive"> <div class="main-box" :class="{ tabbar: tabbarVisible, border: showBorder }">
<keep-alive> <RouterView v-slot="{ Component }" v-if="$route.meta.keepAlive">
<component :is="Component" :key="$route.path" /> <keep-alive>
</keep-alive> <component :is="Component" :key="$route.path" />
</RouterView> </keep-alive>
<RouterView v-if="!$route.meta.keepAlive" :key="$route.path" /> </RouterView>
<RouterView v-if="!$route.meta.keepAlive" :key="$route.path" />
</div>
<nut-tabbar
unactive-color="#364636"
active-color="#1989fa"
v-model="activeTab"
v-show="tabbarVisible"
@tab-switch="tabSwitch"
safe-area-inset-bottom
>
<nut-tabbar-item v-for="item in tabItem" :key="item.key" :tab-title="$t(`common.tabbar.${item.key}`)" :icon="item.icon" />
</nut-tabbar>
</div> </div>
<nut-tabbar unactive-color="#364636" active-color="#1989fa" bottom v-model="activeTab" v-show="tabbarVisible" @tab-switch="tabSwitch">
<nut-tabbar-item v-for="item in tabItem" :key="item.key" :tab-title="$t(`tabbar.${item.key}`)" :icon="item.icon" />
</nut-tabbar>
</template> </template>
<script lang="ts" setup name="BasicLayoutPage"> <script lang="ts" setup name="BasicLayoutPage">
@ -43,7 +52,7 @@
{ deep: true, immediate: true }, { deep: true, immediate: true },
); );
const tabSwitch = (_item, index) => { const tabSwitch = (_item: any, index: number) => {
switch (index) { switch (index) {
case 0: case 0:
router.push('/home'); router.push('/home');
@ -72,14 +81,16 @@
} }
.main-page { .main-page {
box-sizing: border-box; display: flex;
height: calc(100vh - 92px); flex-direction: column;
overflow: hidden scroll; width: 100dvw;
} height: 100dvh;
.tabbar { .main-box {
height: calc(100vh - 92px); flex: auto;
padding-bottom: 100px; min-height: 0;
overflow: hidden auto;
}
} }
.border { .border {

78
src/locales/index.ts Normal file
View File

@ -0,0 +1,78 @@
import { createI18n } from 'vue-i18n';
import type { App } from 'vue';
const LOCALE_KEY = 'lang';
const DEFAULT_LOCALE = 'zh-CN';
/**
*
*/
const modules = import.meta.glob('./langs/**/*.json');
const localeLoaders: Record<string, () => Promise<any>> = {};
Object.keys(modules).forEach((path) => {
// ./langs/zh-CN/common.json
const match = path.match(/\.\/langs\/([^/]+)\/(.+)\.json$/);
if (!match) return;
const locale: any = match[1];
if (!localeLoaders[locale]) {
localeLoaders[locale] = async () => {
const messages: Record<string, any> = {};
for (const p in modules) {
const m = p.match(new RegExp(`./langs/${locale}/(.+)\\.json$`));
if (!m) continue;
const namespace: any = m[1];
if (modules[p]) {
const mod: any = await modules[p]();
messages[namespace] = mod.default;
}
}
return messages;
};
}
});
/**
* i18n messages
*/
export const i18n = createI18n({
legacy: false,
globalInjection: true,
locale: '',
fallbackLocale: DEFAULT_LOCALE,
messages: {},
});
/**
*
*/
export async function setLang(locale?: string) {
const target = locale || localStorage.getItem(LOCALE_KEY) || DEFAULT_LOCALE;
if (!i18n.global.availableLocales.includes(target)) {
const loader = localeLoaders[target];
if (loader) {
const messages = await loader();
console.log(messages);
i18n.global.setLocaleMessage(target, messages);
}
}
i18n.global.locale.value = target;
localStorage.setItem(LOCALE_KEY, target);
document.documentElement.lang = target;
}
/**
* main.ts
*/
export async function setupI18n(app: App) {
app.use(i18n);
await setLang();
}

View File

@ -13,7 +13,6 @@ export type langType = {
introduction: string; introduction: string;
home: { home: {
support: string; support: string;
cssMultiLanguage: string;
}; };
list: { list: {
details: string; details: string;

View File

@ -0,0 +1,25 @@
{
"title": "VUE H5 development template",
"tabbar": {
"home": "Home",
"list": "List",
"member": "Member",
"demo": "demo"
},
"language": {
"en": "English",
"zh": "Chinese"
},
"introduction": "A rapid development vue3 of mobile terminal template",
"home": {
"support": "support"
},
"list": {
"details": "list details"
},
"btn": {
"confirm": "confirm",
"cancel": "cancel"
}
}

View File

@ -0,0 +1,24 @@
{
"title": "VUE H5开发模板",
"tabbar": {
"home": "首页",
"list": "列表",
"member": "我的",
"demo": "示例"
},
"language": {
"en": "英文",
"zh": "中文"
},
"introduction": "一个快速开发vue3的移动端模板",
"home": {
"support": "支持"
},
"list": {
"details": "列表详情"
},
"btn": {
"confirm": "确认",
"cancel": "取消"
}
}

View File

@ -1,9 +1,10 @@
import { createApp } from 'vue'; import { createApp } from 'vue';
import App from './App.vue'; import App from './App.vue';
import { i18n } from '@/i18n'; import { setupI18n } from '@/locales';
import router from '@/router'; import router from '@/router';
import store from '@/store'; import store from '@/store';
import './assets/font/iconfont.css'; import './assets/font/iconfont.css';
import '@/styles/index.scss';
import '@nutui/nutui/dist/packages/toast/style/css'; import '@nutui/nutui/dist/packages/toast/style/css';
import '@nutui/nutui/dist/packages/notify/style/css'; import '@nutui/nutui/dist/packages/notify/style/css';
@ -16,7 +17,7 @@ const app = createApp(App);
app.use(router); app.use(router);
// 国际化 // 国际化
app.use(i18n); await setupI18n(app);
// 状态管理 // 状态管理
app.use(store); app.use(store);

View File

@ -1,4 +1,6 @@
export const routes = [ import type { RouteRecordRaw } from 'vue-router';
export const routes: RouteRecordRaw[] = [
{ {
path: '/', path: '/',
redirect: '/home', redirect: '/home',
@ -8,7 +10,7 @@ export const routes = [
path: 'home', path: 'home',
component: () => import('@/views/home/index.vue'), component: () => import('@/views/home/index.vue'),
meta: { meta: {
title: 'tabbar.home', title: 'common.tabbar.home',
keepAlive: true, keepAlive: true,
}, },
}, },
@ -16,7 +18,7 @@ export const routes = [
path: 'list', path: 'list',
component: () => import('@/views/list/index.vue'), component: () => import('@/views/list/index.vue'),
meta: { meta: {
title: 'tabbar.list', title: 'common.tabbar.list',
keepAlive: true, keepAlive: true,
}, },
}, },
@ -24,7 +26,7 @@ export const routes = [
path: 'member', path: 'member',
component: () => import('@/views/member/index.vue'), component: () => import('@/views/member/index.vue'),
meta: { meta: {
title: 'tabbar.member', title: 'common.tabbar.member',
keepAlive: true, keepAlive: true,
}, },
}, },
@ -32,7 +34,7 @@ export const routes = [
path: 'demo', path: 'demo',
component: () => import('@/views/demo/index.vue'), component: () => import('@/views/demo/index.vue'),
meta: { meta: {
title: 'tabbar.demo', title: 'common.tabbar.demo',
keepAlive: true, keepAlive: true,
}, },
}, },
@ -41,7 +43,7 @@ export const routes = [
path: '/details', path: '/details',
component: () => import('@/views/list/details/index.vue'), component: () => import('@/views/list/details/index.vue'),
meta: { meta: {
title: 'list.details', title: 'common.list.details',
border: false, border: false,
}, },
}, },

View File

@ -1,16 +1,32 @@
.abc { *,
width: 10px; *::before,
*::after {
box-sizing: border-box;
margin: 0;
font-weight: normal;
} }
html, body {
body,
h1,
h2,
h3,
h4,
h5,
h6,
p {
padding: 0;
margin: 0; margin: 0;
font-family:
Inter,
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
Oxygen,
Ubuntu,
Cantarell,
'Fira Sans',
'Droid Sans',
'Helvetica Neue',
sans-serif;
color: var(--color-text);
background: var(--color-background);
text-rendering: optimizelegibility;
transition:
color 0.5s,
background-color 0.5s;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
} }

View File

@ -1,25 +0,0 @@
@mixin main-lang-bg($width, $height, $preUrl, $posUrl) {
width: $width;
height: $height;
background-repeat: no-repeat;
background-size: 100% 100%;
@include loop-lang-bg($preUrl, $posUrl);
}
// 背景图多语言
@mixin loop-lang-bg($preUrl, $posUrl) {
$list: zh-cn, en-us;
@each $i in $list {
&.#{$i} {
background-image: url('#{$preUrl}/#{$i}/#{$posUrl}');
}
}
}
@mixin center {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}

View File

@ -1,5 +0,0 @@
:root {
.van-popup {
max-width: 750px;
}
}

0
src/styles/variable.scss Normal file
View File

View File

@ -1,2 +0,0 @@
$primary-color: green;
$primary-color-end: #496af2;

View File

@ -1,42 +1,32 @@
<template> <template>
<header class="header"> <header class="header">
<img src="https://cdn.jsdelivr.net/gh/fonghehe/picture/vue-h5-template/logo.png" alt="" /><span> {{ $t('title') }}</span> <img src="https://cdn.jsdelivr.net/gh/fonghehe/picture/vue-h5-template/logo.png" alt="" /><span> {{ $t('common.title') }}</span>
</header> </header>
<div class="intro-header"> <div class="intro-header">
<div>{{ $t('introduction') }}</div> <div>{{ $t('common.introduction') }} </div>
<a href="https://github.com/sunniejs/vue-h5-template.git"> <a href="https://github.com/sunniejs/vue-h5-template.git">
<Github /> <Github />
</a> </a>
</div> </div>
<nut-cell-group :title="$t('home.support')" class="supportList"> <nut-cell-group :title="$t('common.home.support')" class="supportList">
<nut-cell v-for="(item, index) in cellList" :key="index" :title="item"> <nut-cell v-for="(item, index) in cellList" :key="index" :title="item">
<template #icon> <template #icon>
<Check /> <Check />
</template> </template>
</nut-cell> </nut-cell>
</nut-cell-group> </nut-cell-group>
<nut-cell-group :title="$t('home.cssMultiLanguage')" class="supportList">
<nut-cell>
<div :class="['btn-confirm', locale]"></div>
</nut-cell>
</nut-cell-group>
<div class="btn-wrap"> <div class="btn-wrap">
<nut-button shape="square" size="small" type="default" @click="changeLang('zh-cn')"> <nut-button shape="square" size="small" type="default" @click="changeLang('zh-CN')">
{{ $t('language.zh') }} {{ $t('common.language.zh') }}
</nut-button>
<nut-button shape="square" size="small" type="default" @click="changeLang('en-us')">
{{ $t('language.en') }}
</nut-button> </nut-button>
<nut-button shape="square" size="small" type="default" @click="changeLang('en-US')"> {{ $t('common.language.en') }}</nut-button>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { setLang } from '@/i18n'; import { setLang } from '@/locales';
import { useI18n } from 'vue-i18n';
import { Github, Check } from '@nutui/icons-vue'; import { Github, Check } from '@nutui/icons-vue';
const { locale } = useI18n();
const cellList = ['vue3', 'vite', 'vue-router', 'axios', 'Pinia', 'vue-i18n', 'postcss-px-to-viewport', 'varlet / vant / nutUI', 'eruda']; const cellList = ['vue3', 'vite', 'vue-router', 'axios', 'Pinia', 'vue-i18n', 'postcss-px-to-viewport', 'varlet / vant / nutUI', 'eruda'];
const changeLang = (type: string) => { const changeLang = (type: string) => {
@ -45,18 +35,16 @@
</script> </script>
<style lang="scss"> <style lang="scss">
@use '@/styles/mixin.scss' as *;
.header { .header {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
padding: 10px 20px; padding: 10px 20px;
font-size: 40px; font-size: 36px;
img { img {
width: 90px; width: 60px;
height: 90px; height: 60px;
} }
} }
@ -79,8 +67,4 @@
.btn-wrap { .btn-wrap {
margin: 20px; margin: 20px;
} }
.btn-confirm {
@include main-lang-bg(302px, 82px, '@/assets/button', 'confirm.png');
}
</style> </style>

View File

@ -12,13 +12,29 @@
</span> </span>
</div> </div>
<div> <div>
<span>{{ details.data?.title }}}</span> <span>{{ details.data?.title }}</span>
</div> </div>
</section> </section>
<!-- 底部固定购买栏 -->
<div :gutter="4" class="bottom-bar">
<div class="btn-icon">
<Dshop color="#fa2c19" />
<span>店铺</span>
</div>
<div class="btn-icon"><Dongdong /> <span>店铺</span></div>
<div class="btn-icon"><Cart /> <span>店铺</span></div>
<div class="btn-group">
<nut-button type="primary"> 加入购物车 </nut-button>
<nut-button type="warning"> 立即购买 </nut-button>
</div>
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { detailsData } from '../data'; import { detailsData } from '../data';
import { Dshop, Dongdong, Cart } from '@nutui/icons-vue';
const router = useRouter(); const router = useRouter();
const page = ref(1); const page = ref(1);
@ -50,10 +66,52 @@
display: inline-block; display: inline-block;
font-size: 32px; font-size: 32px;
color: #f2270c; color: #f2270c;
}
}
em { .bottom-bar {
font-size: 56px; position: fixed;
font-style: normal; bottom: 0;
left: 0;
z-index: 100;
display: flex;
align-items: center;
width: 100%;
height: 100px;
background-color: #fff;
box-shadow: 0 -2px 8px rgb(0 0 0 / 10%);
.btn-icon {
position: relative;
display: flex;
flex: 0 0 14%;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
cursor: pointer;
user-select: none;
.nut-icon {
width: 40px;
height: 40px;
}
span {
margin-top: 12px;
font-size: 18px;
}
}
.btn-group {
display: flex;
flex: 1;
justify-content: space-between;
.nut-button {
flex: 1;
padding: 0;
margin-right: 10px;
} }
} }
} }

View File

@ -27,7 +27,7 @@
<style lang="scss" scoped> <style lang="scss" scoped>
.nut-card { .nut-card {
padding: 15px; padding: 15px 0;
border-bottom: 1px solid #e5e5e5; border-bottom: 1px solid #e5e5e5;
} }
</style> </style>

View File

@ -13,7 +13,7 @@ export default function ({ command, mode }: ConfigEnv): UserConfig {
const env = loadEnv(mode, root); const env = loadEnv(mode, root);
const viteEnv = wrapperEnv(env); const viteEnv = wrapperEnv(env);
const devOptimizeDepsInclude: Array<string> = ['eruda', 'vant/es,@varlet/ui']; const devOptimizeDepsInclude: Array<string> = ['eruda'];
if (!isProduction) { if (!isProduction) {
const excludedDirs = ['utils', 'style', 'composables']; const excludedDirs = ['utils', 'style', 'composables'];
const __dirname = dirname(fileURLToPath(import.meta.url)); const __dirname = dirname(fileURLToPath(import.meta.url));
@ -80,7 +80,8 @@ export default function ({ command, mode }: ConfigEnv): UserConfig {
preprocessorOptions: { preprocessorOptions: {
scss: { scss: {
// 配置 nutui 全局 scss 变量 // 配置 nutui 全局 scss 变量
additionalData: `@import "@/styles/varible.scss";@import "@nutui/nutui/dist/styles/variables-jdt.scss";` additionalData: `@use "@/styles/variable.scss" as *;@use "@nutui/nutui/dist/styles/variables.scss" as *;`,
quietDeps: true,
}, },
}, },
}, },

3169
yarn.lock

File diff suppressed because it is too large Load Diff