chore: 优化项目的整体结构

This commit is contained in:
fonghehe 2025-08-27 14:28:41 +08:00
parent bd3e6cb8e6
commit 1ab51e68d8
47 changed files with 13483 additions and 13216 deletions

View File

@ -3,11 +3,21 @@
"Component": true,
"ComponentPublicInstance": true,
"ComputedRef": true,
"DirectiveBinding": true,
"EffectScope": true,
"ExtractDefaultPropTypes": true,
"ExtractPropTypes": true,
"ExtractPublicPropTypes": true,
"InjectionKey": true,
"MaybeRef": true,
"MaybeRefOrGetter": true,
"PropType": true,
"Ref": true,
"ShallowRef": true,
"Slot": true,
"Slots": true,
"VNode": true,
"WritableComputedRef": true,
"acceptHMRUpdate": true,
"computed": true,
"createApp": true,
@ -20,12 +30,14 @@
"getActivePinia": true,
"getCurrentInstance": true,
"getCurrentScope": true,
"getCurrentWatcher": true,
"h": true,
"inject": true,
"isProxy": true,
"isReactive": true,
"isReadonly": true,
"isRef": true,
"isShallow": true,
"mapActions": true,
"mapGetters": true,
"mapState": true,
@ -48,6 +60,7 @@
"onServerPrefetch": true,
"onUnmounted": true,
"onUpdated": true,
"onWatcherCleanup": true,
"provide": true,
"reactive": true,
"readonly": true,
@ -62,30 +75,22 @@
"toRaw": true,
"toRef": true,
"toRefs": true,
"toValue": true,
"triggerRef": true,
"unref": true,
"useAttrs": true,
"useCssModule": true,
"useCssVars": true,
"useId": true,
"useLink": true,
"useModel": true,
"useRoute": true,
"useRouter": true,
"useSlots": true,
"useTemplateRef": true,
"watch": true,
"watchEffect": true,
"watchPostEffect": true,
"watchSyncEffect": true,
"toValue": true,
"DirectiveBinding": true,
"ExtractDefaultPropTypes": true,
"ExtractPropTypes": true,
"ExtractPublicPropTypes": true,
"MaybeRef": true,
"MaybeRefOrGetter": true,
"WritableComputedRef": true,
"onWatcherCleanup": true,
"useId": true,
"useModel": true,
"useTemplateRef": true
"watchSyncEffect": true
}
}

View File

@ -12,7 +12,7 @@ export function wrapperEnv(envConf: Recordable): ViteEnv {
if (envName === 'VITE_PROXY' && realName) {
try {
realName = JSON.parse(realName.replace(/'/g, '"'));
} catch (error) {
} catch {
realName = '';
}
}

View File

@ -6,7 +6,6 @@
import type { PluginOption } from 'vite';
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
import vueSetupExtend from 'vite-plugin-vue-setup-extend-plus';
import { ConfigSvgIconsPlugin } from './svgIcons';
import { AutoRegistryComponents } from './component';
import { AutoImportDeps } from './autoImport';
@ -28,8 +27,6 @@ export function createVitePlugins(env: ViteEnv, isBuild: boolean) {
vue(),
// JSX支持
vueJsx(),
// setup语法糖组件名支持
vueSetupExtend(),
];
// 自动按需引入组件
@ -48,25 +45,35 @@ export function createVitePlugins(env: ViteEnv, isBuild: boolean) {
vitePlugins.push(ConfigProgressPlugin());
// eruda
VITE_USE_ERUDA && vitePlugins.push(ConfigEruda());
if (VITE_USE_ERUDA) {
vitePlugins.push(ConfigEruda());
}
// rollup-plugin-visualizer
VITE_USE_REPORT && vitePlugins.push(ConfigVisualizerConfig());
if (VITE_USE_REPORT) {
vitePlugins.push(ConfigVisualizerConfig());
}
// vite-plugin-mock
VITE_USE_MOCK && vitePlugins.push(ConfigMockPlugin(isBuild));
if (VITE_USE_MOCK) {
vitePlugins.push(ConfigMockPlugin(isBuild));
}
// vite-plugin-svg-icons
vitePlugins.push(ConfigSvgIconsPlugin(isBuild));
VITE_USE_HTTPS && vitePlugins.push(basicSsl());
if (VITE_USE_HTTPS) {
vitePlugins.push(basicSsl());
}
if (isBuild) {
// vite-plugin-imagemin
vitePlugins.push(ConfigImageminPlugin());
// 开启.gz压缩 rollup-plugin-gzip
VITE_USE_COMPRESS && vitePlugins.push(ConfigCompressPlugin());
if (VITE_USE_COMPRESS) {
vitePlugins.push(ConfigCompressPlugin());
}
}
return vitePlugins;

View File

@ -1,28 +1,22 @@
import eslint from '@eslint/js';
import eslintConfigPrettier from 'eslint-config-prettier';
import eslintPluginVue from 'eslint-plugin-vue';
import globals from 'globals';
import typescriptEslint from 'typescript-eslint';
import { globalIgnores } from 'eslint/config';
import { defineConfigWithVueTs, vueTsConfigs } from '@vue/eslint-config-typescript';
import pluginVue from 'eslint-plugin-vue';
import skipFormatting from '@vue/eslint-config-prettier/skip-formatting';
export default typescriptEslint.config(
{ ignores: ['*.d.ts', '**/coverage', '**/dist'] },
export default defineConfigWithVueTs(
pluginVue.configs['flat/essential'],
vueTsConfigs.recommended,
skipFormatting,
{
extends: [eslint.configs.recommended, ...typescriptEslint.configs.recommended, ...eslintPluginVue.configs['flat/recommended']],
files: ['**/*.{ts,vue}'],
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
globals: globals.browser,
parserOptions: {
parser: typescriptEslint.parser,
ecmaFeatures: {
jsx: true,
},
},
},
name: 'app/files-to-lint',
files: ['**/*.{ts,mts,tsx,vue}'],
rules: {
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/consistent-type-imports': ['error', { prefer: 'type-imports' }],
'vue/multi-word-component-names': 'off',
},
},
eslintConfigPrettier,
globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']),
);

View File

@ -1,4 +1,4 @@
import { MockMethod, Recordable } from 'vite-plugin-mock';
import type { MockMethod, Recordable } from 'vite-plugin-mock';
interface Response {
body: Recordable;

9240
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -16,91 +16,89 @@
"dependencies": {
"@nutui/icons-vue": "^0.1.1",
"@nutui/nutui": "^4.3.13",
"@varlet/ui": "^3.8.7",
"@vueuse/core": "12.7.0",
"@vueuse/integrations": "12.7.0",
"axios": "1.7.9",
"@varlet/ui": "^3.11.3",
"@vueuse/core": "13.7.0",
"@vueuse/integrations": "13.7.0",
"axios": "1.11.0",
"dayjs": "^1.11.13",
"mitt": "^3.0.1",
"pinia": "^3.0.1",
"pinia-plugin-persistedstate": "^4.2.0",
"quarkd": "^2.0.5",
"universal-cookie": "^7.2.2",
"vant": "^4.9.17",
"vue": "^3.5.13",
"vue-i18n": "^11.1.1",
"vue-router": "^4.5.0"
"pinia": "^3.0.2",
"pinia-plugin-persistedstate": "^4.5.0",
"universal-cookie": "^8.0.1",
"vant": "^4.9.19",
"vue": "^3.5.20",
"vue-i18n": "^11.1.3",
"vue-router": "^4.5.1"
},
"devDependencies": {
"@commitlint/cli": "^19.7.1",
"@commitlint/config-conventional": "^19.7.1",
"@eslint/js": "^9.20.0",
"@nutui/auto-import-resolver": "^1.0.0",
"@stylistic/stylelint-plugin": "^3.1.2",
"@typescript-eslint/parser": "^8.24.1",
"@vitejs/plugin-basic-ssl": "^1.2.0",
"@vitejs/plugin-legacy": "^6.0.1",
"@vitejs/plugin-vue": "^5.2.1",
"@vitejs/plugin-vue-jsx": "^4.1.1",
"@stylistic/stylelint-plugin": "^4.0.0",
"@tsconfig/node22": "^22.0.2",
"@types/jsdom": "^21.1.7",
"@types/node": "^22.18.0",
"@typescript-eslint/parser": "^8.41.0",
"@vitejs/plugin-basic-ssl": "^2.0.0",
"@vitejs/plugin-legacy": "^7.2.1",
"@vitejs/plugin-vue": "^6.0.1",
"@vitejs/plugin-vue-jsx": "^5.1.0",
"@vue/eslint-config-prettier": "^10.2.0",
"@vue/eslint-config-typescript": "^14.4.0",
"@vue/eslint-config-typescript": "^14.5.0",
"@vue/test-utils": "^2.4.0",
"@vue/tsconfig": "^0.7.0",
"@vue/tsconfig": "^0.8.1",
"amfe-flexible": "^2.2.1",
"autoprefixer": "^10.4.20",
"autoprefixer": "^10.4.21",
"cnjm-postcss-px-to-viewport": "^1.0.1",
"consola": "^3.2.3",
"cross-env": "^7.0.3",
"cz-git": "^1.11.0",
"czg": "^1.11.0",
"consola": "^3.4.2",
"cross-env": "^10.0.0",
"cz-git": "^1.11.1",
"czg": "^1.11.1",
"eruda": "^3.4.1",
"eslint": "^9.20.1",
"eslint-config-prettier": "^10.0.1",
"eslint": "^9.34.0",
"eslint-define-config": "^2.1.0",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-prettier": "^5.2.3",
"eslint-plugin-prettier": "^5.5.4",
"eslint-plugin-simple-import-sort": "^12.1.1",
"eslint-plugin-vue": "^9.32.0",
"eslint-plugin-vue": "^10.4.0",
"git-cz": "^4.9.0",
"globals": "^15.15.0",
"husky": "9.1.7",
"jsdom": "^22.1.0",
"lint-staged": "15.4.3",
"jsdom": "^26.1.0",
"lint-staged": "16.1.5",
"mockjs": "^1.1.0",
"node": "^22.18.0",
"npm-run-all": "^4.1.5",
"postcss": "^8.5.2",
"postcss": "^8.5.3",
"postcss-html": "1.8.0",
"postcss-less": "^6.0.0",
"prettier": "^3.5.1",
"rollup-plugin-visualizer": "^5.9.1",
"stylelint": "^15.10.1",
"stylelint-config-property-sort-order-smacss": "^9.1.0",
"stylelint-config-recess-order": "^6.0.0",
"stylelint-config-recommended": "^13.0.0",
"postcss-scss": "^4.0.9",
"prettier": "^3.5.3",
"rollup-plugin-visualizer": "^6.0.3",
"stylelint": "^16.23.1",
"stylelint-config-recess-order": "^7.2.0",
"stylelint-config-recommended": "^17.0.0",
"stylelint-config-recommended-scss": "^16.0.0",
"stylelint-config-recommended-vue": "^1.5.0",
"stylelint-config-standard": "^34.0.0",
"stylelint-config-standard-scss": "^10.0.0",
"stylelint-order": "^6.0.3",
"stylelint-prettier": "^4.0.0",
"stylelint-config-standard": "^39.0.0",
"stylelint-order": "^7.0.0",
"stylelint-prettier": "^5.0.3",
"stylelint-scss": "^6.11.0",
"terser": "^5.19.0",
"typescript": "^5.7.3",
"typescript-eslint": "^8.24.1",
"unplugin-auto-import": "^19.1.0",
"unplugin-vue-components": "^28.2.0",
"vite": "^6.1.0",
"typescript": "5.8.3",
"unplugin-auto-import": "^20.0.0",
"unplugin-vue-components": "^29.0.0",
"vite": "^7.1.3",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-eruda": "^1.0.1",
"vite-plugin-imagemin": "^0.6.1",
"vite-plugin-mock": "^3.0.2",
"vite-plugin-pages": "^0.32.4",
"vite-plugin-pages": "^0.33.0",
"vite-plugin-progress": "^0.0.7",
"vite-plugin-restart": "^0.4.2",
"vite-plugin-restart": "^1.0.0",
"vite-plugin-svg-icons": "^2.0.1",
"vite-plugin-vue-setup-extend-plus": "^0.1.0",
"vitest": "^3.0.5",
"vue-eslint-parser": "^9.4.3",
"vue-tsc": "^2.2.2"
"vitest": "^3.1.3",
"vue-eslint-parser": "^10.1.3",
"vue-tsc": "^3.0.6"
},
"engines": {
"node": ">=20.10.0",

8229
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +0,0 @@
html,
body,
h1,
h2,
h3,
h4,
h5,
h6,
p {
margin: 0;
padding: 0;
}

View File

@ -1,536 +0,0 @@
/* Logo 字体 */
@font-face {
font-family: 'iconfont logo';
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
}
.logo {
font-family: 'iconfont logo';
font-size: 160px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* tabs */
.nav-tabs {
position: relative;
}
.nav-tabs .nav-more {
position: absolute;
right: 0;
bottom: 0;
height: 42px;
line-height: 42px;
color: #666;
}
#tabs {
border-bottom: 1px solid #eee;
}
#tabs li {
cursor: pointer;
width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 16px;
border-bottom: 2px solid transparent;
position: relative;
z-index: 1;
margin-bottom: -1px;
color: #666;
}
#tabs .active {
border-bottom-color: #f00;
color: #222;
}
.tab-container .content {
display: none;
}
/* 页面布局 */
.main {
padding: 30px 100px;
width: 960px;
margin: 0 auto;
}
.main .logo {
color: #333;
text-align: left;
margin-bottom: 30px;
line-height: 1;
height: 110px;
margin-top: -50px;
overflow: hidden;
*zoom: 1;
}
.main .logo a {
font-size: 160px;
color: #333;
}
.helps {
margin-top: 40px;
}
.helps pre {
padding: 20px;
margin: 10px 0;
border: solid 1px #e7e1cd;
background-color: #fffdef;
overflow: auto;
}
.icon_lists {
width: 100% !important;
overflow: hidden;
*zoom: 1;
}
.icon_lists li {
width: 100px;
margin-bottom: 10px;
margin-right: 20px;
text-align: center;
list-style: none !important;
cursor: default;
}
.icon_lists li .code-name {
line-height: 1.2;
}
.icon_lists .icon {
display: block;
height: 100px;
line-height: 100px;
font-size: 42px;
margin: 10px auto;
color: #333;
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
-moz-transition: font-size 0.25s linear, width 0.25s linear;
transition: font-size 0.25s linear, width 0.25s linear;
}
.icon_lists .icon:hover {
font-size: 100px;
}
.icon_lists .svg-icon {
/* 通过设置 font-size 来改变图标大小 */
width: 1em;
/* 图标和文字相邻时,垂直对齐 */
vertical-align: -0.15em;
/* 通过设置 color 来改变 SVG 的颜色/fill */
fill: currentColor;
/* path stroke 溢出 viewBox 部分在 IE 下会显示
normalize.css 中也包含这行 */
overflow: hidden;
}
.icon_lists li .name,
.icon_lists li .code-name {
color: #666;
}
/* markdown 样式 */
.markdown {
color: #666;
font-size: 14px;
line-height: 1.8;
}
.highlight {
line-height: 1.5;
}
.markdown img {
vertical-align: middle;
max-width: 100%;
}
.markdown h1 {
color: #404040;
font-weight: 500;
line-height: 40px;
margin-bottom: 24px;
}
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
color: #404040;
margin: 1.6em 0 0.6em 0;
font-weight: 500;
clear: both;
}
.markdown h1 {
font-size: 28px;
}
.markdown h2 {
font-size: 22px;
}
.markdown h3 {
font-size: 16px;
}
.markdown h4 {
font-size: 14px;
}
.markdown h5 {
font-size: 12px;
}
.markdown h6 {
font-size: 12px;
}
.markdown hr {
height: 1px;
border: 0;
background: #e9e9e9;
margin: 16px 0;
clear: both;
}
.markdown p {
margin: 1em 0;
}
.markdown > p,
.markdown > blockquote,
.markdown > .highlight,
.markdown > ol,
.markdown > ul {
width: 80%;
}
.markdown ul > li {
list-style: circle;
}
.markdown > ul li,
.markdown blockquote ul > li {
margin-left: 20px;
padding-left: 4px;
}
.markdown > ul li p,
.markdown > ol li p {
margin: 0.6em 0;
}
.markdown ol > li {
list-style: decimal;
}
.markdown > ol li,
.markdown blockquote ol > li {
margin-left: 20px;
padding-left: 4px;
}
.markdown code {
margin: 0 3px;
padding: 0 5px;
background: #eee;
border-radius: 3px;
}
.markdown strong,
.markdown b {
font-weight: 600;
}
.markdown > table {
border-collapse: collapse;
border-spacing: 0px;
empty-cells: show;
border: 1px solid #e9e9e9;
width: 95%;
margin-bottom: 24px;
}
.markdown > table th {
white-space: nowrap;
color: #333;
font-weight: 600;
}
.markdown > table th,
.markdown > table td {
border: 1px solid #e9e9e9;
padding: 8px 16px;
text-align: left;
}
.markdown > table th {
background: #f7f7f7;
}
.markdown blockquote {
font-size: 90%;
color: #999;
border-left: 4px solid #e9e9e9;
padding-left: 0.8em;
margin: 1em 0;
}
.markdown blockquote p {
margin: 0;
}
.markdown .anchor {
opacity: 0;
transition: opacity 0.3s ease;
margin-left: 8px;
}
.markdown .waiting {
color: #ccc;
}
.markdown h1:hover .anchor,
.markdown h2:hover .anchor,
.markdown h3:hover .anchor,
.markdown h4:hover .anchor,
.markdown h5:hover .anchor,
.markdown h6:hover .anchor {
opacity: 1;
display: inline-block;
}
.markdown > br,
.markdown > p > br {
clear: both;
}
.hljs {
display: block;
background: white;
padding: 0.5em;
color: #333333;
overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
color: #969896;
}
.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #a71d5d;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}
.hljs-section,
.hljs-name {
color: #63a35c;
}
.hljs-tag {
color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #795da3;
}
.hljs-addition {
color: #55a532;
background-color: #eaffea;
}
.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}
.hljs-link {
text-decoration: underline;
}
/* 代码高亮 */
/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*='language-'],
pre[class*='language-'] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*='language-']::-moz-selection,
pre[class*='language-'] ::-moz-selection,
code[class*='language-']::-moz-selection,
code[class*='language-'] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*='language-']::selection,
pre[class*='language-'] ::selection,
code[class*='language-']::selection,
code[class*='language-'] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*='language-'],
pre[class*='language-'] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*='language-'] {
padding: 1em;
margin: 0.5em 0;
overflow: auto;
}
:not(pre) > code[class*='language-'],
pre[class*='language-'] {
background: #f5f2f0;
}
/* Inline code */
:not(pre) > code[class*='language-'] {
padding: 0.1em;
border-radius: 0.3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: 0.7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, 0.5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #dd4a68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}

View File

@ -1,37 +1,39 @@
@font-face {
font-family: 'iconfont'; /* Project id 3210904 */
src: url('iconfont.woff2?t=1646452970429') format('woff2'), url('iconfont.woff?t=1646452970429') format('woff'),
font-family: iconfont; /* Project id 3210904 */
src:
url('iconfont.woff2?t=1646452970429') format('woff2'),
url('iconfont.woff?t=1646452970429') format('woff'),
url('iconfont.ttf?t=1646452970429') format('truetype');
}
.iconfont {
font-family: 'iconfont' !important;
font-family: iconfont !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-custom-ok:before {
.icon-custom-ok::before {
content: '\e631';
}
.icon-github-fill:before {
.icon-github-fill::before {
content: '\e885';
}
.icon-l-search:before {
.icon-l-search::before {
content: '\e79e';
}
.icon-home:before {
.icon-home::before {
content: '\e603';
}
.icon-member:before {
.icon-member::before {
content: '\e602';
}
.icon-list:before {
.icon-list::before {
content: '\e601';
}

View File

@ -1,51 +0,0 @@
{
"id": "3210904",
"name": "fast-vue3",
"font_family": "iconfont",
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "517495",
"name": "ok",
"font_class": "custom-ok",
"unicode": "e631",
"unicode_decimal": 58929
},
{
"icon_id": "4937000",
"name": "github-fill",
"font_class": "github-fill",
"unicode": "e885",
"unicode_decimal": 59525
},
{
"icon_id": "12932129",
"name": "l-search",
"font_class": "l-search",
"unicode": "e79e",
"unicode_decimal": 59294
},
{
"icon_id": "109751",
"name": "home",
"font_class": "home",
"unicode": "e603",
"unicode_decimal": 58883
},
{
"icon_id": "663138",
"name": "member",
"font_class": "member",
"unicode": "e602",
"unicode_decimal": 58882
},
{
"icon_id": "21513638",
"name": "list",
"font_class": "list",
"unicode": "e601",
"unicode_decimal": 58881
}
]
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1 +0,0 @@
export { openFactoryModal } from './src/hooks/useFactoryModal';

View File

@ -1,49 +0,0 @@
<template>
<Popup
:show="props.show"
teleport="body"
:style="`overflow-y: auto;`"
:close-on-click-overlay="closeOnClickOverlay"
@close="$emit('update:show', false)"
>
<div :class="['modal-content', size]">
<div class="content">
<slot>内容</slot>
</div>
<div class="btn">
<div class="btn-confirm" @click="$emit('confirm')">{{ $t('btn.confirm') }}</div>
<div class="btn-cancel" @click="$emit('update:show', false)">{{ $t('btn.cancel') }}</div>
</div>
</div>
</Popup>
</template>
<script lang="ts">
export default {
name: 'BasicModal',
};
</script>
<script setup lang="ts">
import { Popup } from 'vant';
import 'vant/es/popup/style/index';
const props = withDefaults(
defineProps<{
show: boolean;
closeOnClickOverlay?: boolean;
size?: 'normal' | 'large';
}>(),
{
show: false,
closeOnClickOverlay: false,
size: 'large',
},
);
defineEmits<{
(event: 'confirm'): void;
(event: 'update:show', data: boolean): void;
}>();
</script>
<style scoped lang="scss">
@use './index.scss' as *;
</style>

View File

@ -1,62 +0,0 @@
/*
* @Author: Vinton
* @Date: 2023-05-10 11:46:19
* @Description: file content
*/
import { i18n } from '@/i18n';
import { Component } from 'vue';
import BaseModal from '../BasicModal.vue';
import { createApp, ref, defineComponent } from 'vue';
export const openFactoryModal = ({ renderComp, size }: { size?: 'normal' | 'large'; renderComp: Function }) => {
return new Promise<string>((resolve, reject) => {
// eslint-disable-next-line prefer-const
let u;
const Wrapper = defineComponent({
setup() {
const show = ref(true);
const onChange = (s) => {
show.value = s;
if (!s) {
// unmount app and remove root dom
if (u) u();
reject('user closed modal manually');
}
};
const onConfirm = () => {
resolve('confirm');
onChange(false);
};
return { show, onChange, onConfirm, size };
},
render(proxy) {
return (
<BaseModal size={proxy.size} show={proxy.show} {...{ 'onUpdate:show': proxy.onChange }} onConfirm={proxy.onConfirm}>
{renderComp()}
</BaseModal>
);
},
});
const { unmount } = mountPropModal(Wrapper);
u = unmount;
});
};
const mountPropModal = (component: Component) => {
const app = createApp(component);
app.use(i18n);
const root = document.createElement('div');
document.body.appendChild(root);
const instance = app.mount(root);
return {
instance,
unmount() {
app.unmount();
document.body.removeChild(root);
},
};
};

View File

@ -1,54 +0,0 @@
@use '@/styles/mixin' as *;
.modal-content {
@include center();
position: relative;
width: 650px;
background-repeat: no-repeat;
background-size: cover;
&.normal {
height: 604px;
background-image: url('@/assets/baseModal/modal-bg-normal.png');
}
&.large {
height: 754px;
background-image: url('@/assets/baseModal/modal-bg-large.png');
}
.content {
@include center();
width: 100%;
}
.btn {
display: flex;
position: absolute;
bottom: 10px;
justify-content: space-around;
width: 100%;
&-cancel {
@extend .btn-common;
background-color: coral;
}
&-confirm {
@extend .btn-common;
background-color: skyblue;
}
}
}
.btn-common {
@include center();
width: 250px;
height: 100px;
border-radius: 10px;
}

View File

@ -1,4 +1,4 @@
import { langType } from './lang-base';
import type { langType } from './lang-base';
export const lang: langType = {
title: 'VUE H5 development template',

View File

@ -1,4 +1,4 @@
import { langType } from './lang-base';
import type { langType } from './lang-base';
export const lang: langType = {
title: 'VUE H5开发模板',

View File

@ -74,8 +74,7 @@
.main-page {
box-sizing: border-box;
height: calc(100vh - 92px);
overflow-y: scroll;
overflow-x: hidden;
overflow: hidden scroll;
}
.tabbar {
@ -84,7 +83,7 @@
}
.border {
padding-left: 30px;
padding-right: 30px;
padding-left: 30px;
}
</style>

View File

@ -4,7 +4,6 @@ import { i18n } from '@/i18n';
import router from '@/router';
import store from '@/store';
import './assets/font/iconfont.css';
import './assets/app.css';
const app = createApp(App);

View File

@ -1,4 +1,5 @@
import { createRouter, createWebHistory, Router } from 'vue-router';
import { createRouter, createWebHistory } from 'vue-router';
import type { Router } from 'vue-router';
import routes from './routes';
const router: Router = createRouter({

View File

@ -2,7 +2,7 @@ export const routes = [
{
path: '/',
redirect: '/home',
component: () => import('@/layout/basic/index.vue'),
component: () => import('@/layout/index.vue'),
children: [
{
path: 'home',

View File

@ -4,6 +4,7 @@ import { defineStore } from 'pinia';
const { VITE_TOKEN_KEY } = import.meta.env;
const token = useCookies().get(VITE_TOKEN_KEY as string);
console.log(token);
interface StoreUser {
token: string;
@ -12,7 +13,7 @@ interface StoreUser {
export const useUserStore = defineStore('user', {
state: (): StoreUser => ({
token: token,
token: 'token',
info: {},
}),
getters: {

View File

@ -1,3 +1,16 @@
.abc {
width: 10px;
}
html,
body,
h1,
h2,
h3,
h4,
h5,
h6,
p {
padding: 0;
margin: 0;
}

View File

@ -3,11 +3,13 @@
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}');

View File

@ -1,6 +1,6 @@
:root {
.van-popup {
background: transparent;
max-width: 750px;
background: transparent;
}
}

View File

@ -1,4 +1,5 @@
import axios, { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios';
import axios from 'axios';
import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios';
import { showToast } from 'vant';
const service: AxiosInstance = axios.create({

View File

@ -1,4 +1,4 @@
import { useAxios } from '@vueuse/integrations/useAxios';
import { useAxios } from '@vueuse/integrations';
import 'vant/es/toast/style';

View File

@ -31,49 +31,9 @@
<nut-button type="success">成功按钮</nut-button>
</div>
</section>
<section>
<span class="title">Quark</span>
<div class="demo">
<quark-button>默认按钮</quark-button>
<quark-button type="primary">主要按钮</quark-button>
<quark-button type="success">成功按钮</quark-button>
<quark-button type="danger">危险按钮</quark-button>
<quark-button type="warning">警告按钮</quark-button>
</div>
</section>
<section>
<span class="title">Modal</span>
<div class="demo">
<var-button type="primary" @click="openLargeModal">Open large Modal</var-button>
<var-button type="info" @click="openSmallModal">Open Normal Modal</var-button>
</div>
</section>
</template>
<script setup name="DemoPage" lang="tsx">
import { openFactoryModal } from '@/components/Modal/index';
import 'quarkd/lib/button';
const openLargeModal = () => {
openFactoryModal({
renderComp: function () {
return <div>自定义内容</div>;
},
}).then((res) => {
console.log('确认成功', res);
});
};
const openSmallModal = () => {
openFactoryModal({
size: 'normal',
renderComp: function () {
return <div>自定义内容</div>;
},
}).then((res) => {
console.log('确认成功', res);
});
};
</script>
<script setup lang="ts"></script>
<style lang="scss" scoped>
section {

View File

@ -30,7 +30,7 @@
</div>
</template>
<script lang="ts" setup name="HomePage">
<script setup lang="ts">
import { setLang } from '@/i18n';
import { useI18n } from 'vue-i18n';
import { Github, Check } from '@nutui/icons-vue';
@ -39,10 +39,11 @@
const cellList = ['vue3', 'vite', 'vue-router', 'axios', 'Pinia', 'vue-i18n', 'postcss-px-to-viewport', 'varlet / vant / nutUI', 'eruda'];
const changeLang = (type) => {
const changeLang = (type: string) => {
setLang(type);
};
</script>
<style lang="scss">
@use '@/styles/mixin.scss' as *;

View File

@ -22,7 +22,7 @@
const router = useRouter();
const page = ref(1);
let details = reactive<any>({ data: {} });
const details = reactive<any>({ data: {} });
watch(
() => router,
@ -36,6 +36,7 @@
<style lang="scss" scoped>
.nut-swiper-item {
line-height: 500px;
img {
width: 100%;
height: 100%;
@ -44,10 +45,12 @@
.info {
padding: 20px;
.price {
color: #f2270c;
display: inline-block;
font-size: 32px;
color: #f2270c;
em {
font-size: 56px;
font-style: normal;

View File

@ -9,18 +9,18 @@
:shop-name="item.shopName"
:shopDesc="item.shopDesc"
:delivery="item.delivery"
@click="(_e) => toDetails(index)"
@click="(_e: any) => toDetails(index)"
/>
</template>
<script lang="ts" setup name="ListPage">
<script setup lang="ts">
import { listData } from './data';
const router = useRouter();
let list = ref(listData);
const list = ref(listData);
const toDetails = (index) => {
const toDetails = (index: number) => {
router.push({ path: '/details', query: { id: index } });
};
</script>

View File

@ -13,7 +13,7 @@
</div>
</template>
<script lang="ts" setup name="LoginPage">
<script setup lang="ts">
import router from '@/router';
import { reactive, ref } from 'vue';
import { useUserStore } from '@/store/modules/user';
@ -44,14 +44,14 @@
padding: 20px;
h2 {
letter-spacing: 10px;
text-align: center;
letter-spacing: 10px;
}
.nut-form-item {
margin-bottom: 20px;
border-radius: 20px;
background: #f2f3f5;
border-radius: 20px;
input {
background: transparent;

View File

@ -16,7 +16,7 @@
</nut-grid>
</template>
<script lang="ts" setup name="MemberPage">
<script setup lang="ts">
import { useUserStore } from '@/store/modules/user';
import { useRouter } from 'vue-router';
import { Dongdong } from '@nutui/icons-vue';

View File

@ -1,75 +1,67 @@
module.exports = {
extends: ['stylelint-config-standard', 'stylelint-config-property-sort-order-smacss'],
plugins: ['stylelint-order', 'stylelint-prettier'],
customSyntax: 'postcss-html',
extends: ['stylelint-config-standard', 'stylelint-config-recess-order'],
ignoreFiles: ['**/*.js', '**/*.jsx', '**/*.tsx', '**/*.ts', '**/*.json', '**/*.md'],
overrides: [
{
files: ['**/*.(css|html|vue)'],
customSyntax: 'postcss-html',
files: ['*.(html|vue)', '**/*.(html|vue)'],
rules: {
'selector-pseudo-class-no-unknown': [
true,
{
ignorePseudoClasses: ['global', 'deep'],
},
],
'selector-pseudo-element-no-unknown': [
true,
{
ignorePseudoElements: ['v-deep', 'v-global', 'v-slotted'],
},
],
},
},
{
files: ['*.less', '**/*.less'],
customSyntax: 'postcss-less',
extends: ['stylelint-config-standard', 'stylelint-config-recommended-vue'],
customSyntax: 'postcss-scss',
extends: ['stylelint-config-recommended-scss', 'stylelint-config-recommended-vue/scss'],
files: ['*.scss', '**/*.scss'],
},
],
plugins: ['stylelint-order', '@stylistic/stylelint-plugin', 'stylelint-prettier', 'stylelint-scss'],
rules: {
'selector-not-notation': null,
'import-notation': null,
'function-no-unknown': null,
'selector-class-pattern': null,
'selector-pseudo-class-no-unknown': [
true,
{
ignorePseudoClasses: ['global', 'deep'],
},
],
'selector-pseudo-element-no-unknown': [
true,
{
ignorePseudoElements: ['v-deep'],
},
],
'at-rule-no-deprecated': null,
'at-rule-no-unknown': [
true,
{
ignoreAtRules: [
'extend',
'at-root',
'debug',
'warn',
'error',
'ignores',
'include',
'mixin',
'if',
'else',
'media',
'for',
'each',
'while',
'mixin',
'include',
'content',
'return',
'function',
'at-root',
'tailwind',
'apply',
'responsive',
'variants',
'responsive',
'screen',
'function',
'each',
'use',
'forward',
'return',
],
},
],
'no-empty-source': null,
'string-quotes': null,
'font-family-no-missing-generic-family-keyword': null,
'function-no-unknown': null,
'import-notation': null,
'media-feature-range-notation': null,
'named-grid-areas-no-invalid': null,
'no-descending-specificity': null,
'font-family-no-missing-generic-family-keyword': null,
'rule-empty-line-before': [
'always',
{
ignore: ['after-comment', 'first-nested'],
},
],
'unit-no-unknown': [true, { ignoreUnits: ['rpx'] }],
'no-empty-source': null,
'order/order': [
[
'dollar-variables',
@ -77,17 +69,58 @@ module.exports = {
'at-rules',
'declarations',
{
type: 'at-rule',
name: 'supports',
type: 'at-rule',
},
{
type: 'at-rule',
name: 'media',
type: 'at-rule',
},
{
name: 'include',
type: 'at-rule',
},
'rules',
],
{ severity: 'error' },
],
'prettier/prettier': true,
'rule-empty-line-before': [
'always',
{
ignore: ['after-comment', 'first-nested'],
},
],
'scss/at-rule-no-unknown': [
true,
{
ignoreAtRules: [
'extends',
'ignores',
'include',
'mixin',
'if',
'else',
'media',
'for',
'at-root',
'tailwind',
'apply',
'variants',
'responsive',
'screen',
'function',
'each',
'use',
'forward',
'return',
],
},
],
'scss/operator-no-newline-after': null,
'selector-class-pattern':
'^(?:(?:o|c|u|t|s|is|has|_|js|qa)-)?[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*(?:__[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*)?(?:--[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*)?(?:[.+])?$',
'selector-not-notation': null,
},
ignoreFiles: ['**/*.js', '**/*.jsx', '**/*.tsx', '**/*.ts'],
};

25
tsconfig.app.json Normal file
View File

@ -0,0 +1,25 @@
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"include": [
"tests/**/*.ts",
"src/**/*.ts",
"src/**/*.d.ts",
"src/**/*.tsx",
"src/**/*.vue",
"types/**/*.d.ts",
"types/**/*.ts",
"config/**/*.ts",
"config/**/*.d.ts",
"mock/**/*.ts",
"build/**/*.ts"
],
"exclude": ["src/**/__tests__/*", "node_modules", "tests/server/**/*.ts", "dist", "**/*.js"],
"compilerOptions": {
"composite": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}

View File

@ -1,43 +1,14 @@
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"moduleResolution": "Bundler",
"strict": true,
"noLib": false,
"forceConsistentCasingInFileNames": true,
"allowSyntheticDefaultImports": true,
"strictFunctionTypes": false,
"jsx": "preserve",
"baseUrl": ".",
"allowJs": true,
"sourceMap": true,
"esModuleInterop": true,
"resolveJsonModule": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"experimentalDecorators": true,
"lib": ["dom", "esnext"],
"noImplicitAny": false,
"skipLibCheck": true,
"removeComments": true,
"paths": {
"@/*": ["src/*"],
"#/*": ["types/*"]
"files": [],
"references": [
{
"path": "./tsconfig.node.json"
},
{
"path": "./tsconfig.app.json"
},
{
"path": "./tsconfig.vitest.json"
}
},
"include": [
"tests/**/*.ts",
"src/**/*.ts",
"src/**/*.d.ts",
"src/**/*.tsx",
"src/**/*.vue",
"types/**/*.d.ts",
"types/**/*.ts",
"config/**/*.ts",
"config/**/*.d.ts",
"mock/**/*.ts",
"vite.config.ts"
],
"exclude": ["node_modules", "tests/server/**/*.ts", "dist", "**/*.js"]
]
}

22
tsconfig.node.json Normal file
View File

@ -0,0 +1,22 @@
{
"extends": "@tsconfig/node22/tsconfig.json",
"include": [
"vite.config.*",
"vitest.config.*",
"cypress.config.*",
"nightwatch.conf.*",
"playwright.config.*",
"build/**/*.ts",
"types/**/*.d.ts",
"types/**/*.ts"
],
"compilerOptions": {
"composite": true,
"noEmit": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"module": "ESNext",
"moduleResolution": "Bundler",
"types": ["node"]
}
}

11
tsconfig.vitest.json Normal file
View File

@ -0,0 +1,11 @@
{
"extends": "./tsconfig.app.json",
"exclude": [],
"compilerOptions": {
"composite": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo",
"lib": [],
"types": ["node", "jsdom"]
}
}

View File

@ -19,12 +19,14 @@ declare global {
const getActivePinia: (typeof import('pinia'))['getActivePinia'];
const getCurrentInstance: (typeof import('vue'))['getCurrentInstance'];
const getCurrentScope: (typeof import('vue'))['getCurrentScope'];
const getCurrentWatcher: (typeof import('vue'))['getCurrentWatcher'];
const h: (typeof import('vue'))['h'];
const inject: (typeof import('vue'))['inject'];
const isProxy: (typeof import('vue'))['isProxy'];
const isReactive: (typeof import('vue'))['isReactive'];
const isReadonly: (typeof import('vue'))['isReadonly'];
const isRef: (typeof import('vue'))['isRef'];
const isShallow: (typeof import('vue'))['isShallow'];
const mapActions: (typeof import('pinia'))['mapActions'];
const mapGetters: (typeof import('pinia'))['mapGetters'];
const mapState: (typeof import('pinia'))['mapState'];
@ -85,6 +87,8 @@ declare global {
// @ts-ignore
export type {
Component,
Slot,
Slots,
ComponentPublicInstance,
ComputedRef,
DirectiveBinding,
@ -94,6 +98,7 @@ declare global {
InjectionKey,
PropType,
Ref,
ShallowRef,
MaybeRef,
MaybeRefOrGetter,
VNode,

2
types/env.d.ts vendored Normal file
View File

@ -0,0 +1,2 @@
// env.d.ts
/// <reference types="vite/client" />

10
types/global.d.ts vendored
View File

@ -46,11 +46,11 @@ declare global {
}
declare interface ViteEnv {
VITE_USE_MOCK: Boolean;
VITE_USE_ERUDA: Boolean;
VITE_USE_COMPRESS: Boolean;
VITE_USE_REPORT: Boolean;
VITE_USE_HTTPS: Boolean;
VITE_USE_MOCK: boolean;
VITE_USE_ERUDA: boolean;
VITE_USE_COMPRESS: boolean;
VITE_USE_REPORT: boolean;
VITE_USE_HTTPS: boolean;
}
declare function parseInt(s: string | number, radix?: number): number;

View File

@ -1,11 +1,9 @@
import { createVitePlugins } from './build/vite/plugins';
import { resolve } from 'path';
import { ConfigEnv, loadEnv, UserConfig } from 'vite';
import type { ConfigEnv, UserConfig } from 'vite';
import { loadEnv } from 'vite';
import { wrapperEnv } from './build/utils';
const pathResolve = (dir: string) => {
return resolve(process.cwd(), '.', dir);
};
import { fileURLToPath, URL } from 'node:url';
// https://vitejs.dev/config/
export default function ({ command, mode }: ConfigEnv): UserConfig {
@ -18,22 +16,7 @@ export default function ({ command, mode }: ConfigEnv): UserConfig {
base: '/',
root,
resolve: {
alias: [
{
find: 'vue-i18n',
replacement: 'vue-i18n/dist/vue-i18n.cjs.js',
},
// @/xxxx => src/xxxx
{
find: /@\//,
replacement: pathResolve('src') + '/',
},
// #/xxxx => types/xxxx
{
find: /#\//,
replacement: pathResolve('types') + '/',
},
],
alias: { '@': fileURLToPath(new URL('./src', import.meta.url)), '#': fileURLToPath(new URL('./types', import.meta.url)) },
},
server: {
host: true,
@ -53,7 +36,6 @@ export default function ({ command, mode }: ConfigEnv): UserConfig {
css: {
preprocessorOptions: {
scss: {
api: 'modern-compiler',
quietDeps: true,
silenceDeprecations: ['legacy-js-api'],
// 配置 nutui 全局 scss 变量

7852
yarn.lock

File diff suppressed because it is too large Load Diff