├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .stylelintignore ├── .stylelintrc.js ├── .vscode └── extensions.json ├── README.md ├── index.html ├── package.json ├── public └── favicon.ico ├── src ├── App.vue ├── assets │ └── logo.png ├── components │ └── HelloWorld.vue ├── env.d.ts ├── main.ts ├── router │ └── index.ts ├── stores │ └── counter.ts ├── typings │ └── index.ts ├── utils │ ├── axios.ts │ ├── demand-import.ts │ ├── echarts.ts │ └── mock.ts └── views │ ├── home │ └── index.vue │ ├── test-axios.vue │ └── test.vue ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | 3 | # 表示是最顶层的 EditorConfig 配置文件 4 | root = true 5 | 6 | [*] # 表示所有文件适用 7 | charset = utf-8 # 设置文件字符集为 utf-8 8 | indent_style = space # 缩进风格(tab | space) 9 | indent_size = 4 # 缩进大小 10 | end_of_line = lf # 控制换行类型(lf | cr | crlf) 11 | trim_trailing_whitespace = true # 去除行首的任意空白字符 12 | insert_final_newline = true # 始终在文件末尾插入一个新行 13 | 14 | [*.md] # 表示仅 md 文件适用以下规则 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /dist/ 3 | /node_modules/ 4 | *.js 5 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | browser: true, 5 | es2021: true, 6 | node: true, 7 | }, 8 | extends: [ 9 | 'plugin:vue/vue3-recommended', 10 | 'plugin:@typescript-eslint/recommended' 11 | ], 12 | /* 13 | * 解决引入ts文件import xxx (不带文件后缀) eslint报错问题 14 | * https://stackoverflow.com/questions/55198502/using-eslint-with-typescript-unable-to-resolve-path-to-module 15 | * */ 16 | // settings: { 17 | // "import/resolver": { 18 | // "node": { 19 | // "paths": ["src"], 20 | // "extensions": [".js", ".jsx", ".ts", ".tsx"] 21 | // } 22 | // } 23 | // }, 24 | parser: "vue-eslint-parser", 25 | parserOptions: { 26 | parser: '@typescript-eslint/parser', 27 | ecmaVersion: "latest", 28 | sourceType: 'module' 29 | }, 30 | plugins: [ 31 | '@typescript-eslint' 32 | ], 33 | rules: { 34 | // 使用单引号 35 | /* 示例 36 | // bad code 37 | let str = "hello world" 38 | 39 | // good code 40 | let str = 'hello world' 41 | */ 42 | 'quotes': ['error', 'single'], 43 | 44 | // 三等号 45 | /* 示例 46 | // bad code 47 | if (a == b) {} 48 | 49 | // good code 50 | if (a === b) {} 51 | */ 52 | 'eqeqeq': ['error', 'always'], 53 | 54 | // 禁止出现未使用过的变量 55 | 'no-unused-vars': 'error', 56 | 57 | // 强制在关键字前后使用一致的空格 58 | /* 示例 59 | // bad code 60 | if (foo) { 61 | //... 62 | }else if (bar) { 63 | //... 64 | }else { 65 | //... 66 | } 67 | 68 | // good code 69 | if (foo) { 70 | //... 71 | } else if (bar) { 72 | //... 73 | } else { 74 | //... 75 | } 76 | */ 77 | 'keyword-spacing': [ 78 | 'error', 79 | { 80 | 'overrides': { 81 | 'if': { 82 | 'after': true 83 | }, 84 | 'for': { 85 | 'after': true 86 | }, 87 | 'while': { 88 | 'after': true 89 | }, 90 | 'else': { 91 | 'after': true 92 | } 93 | } 94 | } 95 | ], 96 | 97 | // https://eslint.org/docs/rules/camelcase 98 | 'camelcase': ['error', {'properties': 'never'}], 99 | 100 | // 缩进使用 4 个空格,并且 switch 语句中的 Case 需要缩进 101 | // https://eslint.org/docs/rules/indent 102 | 'indent': ['error', 4, { 103 | 'SwitchCase': 1, 104 | 'flatTernaryExpressions': true 105 | }], 106 | 107 | // 数组的括号内的前后禁止有空格 108 | // https://eslint.org/docs/rules/array-bracket-spacing 109 | /* 示例 110 | // bad code 111 | const foo = [ 'foo' ]; 112 | const foo = [ 'foo']; 113 | const foo = ['foo' ]; 114 | const foo = [ 1 ]; 115 | 116 | // good code 117 | const foo = ['foo']; 118 | const foo = [1]; 119 | */ 120 | 'array-bracket-spacing': ['error', 'never'], 121 | 122 | // 需要在操作符之前放置换行符 123 | // https://eslint.org/docs/rules/operator-linebreak 124 | // 'operator-linebreak': ['error', 'before'], 125 | 126 | // 在开发阶段打开调试 (区分stag prod) 127 | // https://eslint.org/docs/rules/no-debugger 128 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', 129 | 130 | // 只有一个参数时,箭头函数体可以省略圆括号 131 | // https://eslint.org/docs/rules/arrow-parens 132 | 'arrow-parens': 'off', 133 | 134 | // 禁止空语句(可在空语句写注释避免),允许空的 catch 语句 135 | // https://eslint.org/docs/rules/no-empty 136 | /* 示例 137 | // bad code 138 | if (foo) { 139 | } 140 | 141 | while (foo) { 142 | } 143 | 144 | // good code 145 | if (foo) { 146 | // empty 147 | } 148 | */ 149 | 'no-empty': ['error', {'allowEmptyCatch': true}], 150 | 151 | // 禁止在语句末尾使用分号 152 | // https://eslint.org/docs/rules/semi 153 | /* 示例 154 | // bad code 155 | const obj = {}; 156 | 157 | // good code 158 | const obj = {} 159 | */ 160 | 'semi': ['error', 'never'], 161 | 162 | // 函数圆括号之前没有空格(挺有争议的) 163 | // https://eslint.org/docs/rules/space-before-function-paren 164 | /* 示例 165 | // bad code 166 | function foo () { 167 | // ... 168 | } 169 | 170 | const bar = function () { 171 | // ... 172 | } 173 | 174 | // good code 175 | function foo() { 176 | // ... 177 | } 178 | 179 | const bar = function() { 180 | // ... 181 | } 182 | */ 183 | 'space-before-function-paren': ['error', { 184 | 'anonymous': 'never', // 匿名函数表达式 185 | 'named': 'never', // 命名的函数表达式 186 | 'asyncArrow': 'never' // 异步的箭头函数表达式 187 | }], 188 | 189 | // 禁止行尾有空格 190 | // https://eslint.org/docs/rules/no-trailing-spaces 191 | 'no-trailing-spaces': ['error'], 192 | 193 | 194 | // 注释的斜线或 * 后必须有空格 195 | // https://eslint.org/docs/rules/spaced-comment 196 | /* 示例 197 | // bad code 198 | //This is a comment with no whitespace at the beginning 199 | 200 | // good code 201 | // This is a comment with a whitespace at the beginning 202 | */ 203 | 'spaced-comment': ['error', 'always', { 204 | 'line': { 205 | 'markers': ['*package', '!', '/', ',', '='] 206 | }, 207 | 'block': { 208 | // 前后空格是否平衡 209 | 'balanced': false, 210 | 'markers': ['*package', '!', ',', ':', '::', 'flow-include'], 211 | 'exceptions': ['*'] 212 | } 213 | }], 214 | 215 | // https://eslint.org/docs/rules/no-template-curly-in-string 216 | // 禁止在字符串中使用字符串模板。不限制 217 | 'no-template-curly-in-string': 'off', 218 | 219 | // https://eslint.org/docs/rules/no-useless-escape 220 | // 禁止出现没必要的转义。不限制 221 | 'no-useless-escape': 'off', 222 | 223 | // https://eslint.org/docs/rules/no-var 224 | // 禁止使用 var 225 | 'no-var': 'error', 226 | 227 | // https://eslint.org/docs/rules/prefer-const 228 | // 如果一个变量不会被重新赋值,必须使用 `const` 进行声明。 229 | /* 示例 230 | // bad code 231 | let a = 3 232 | console.log(a) 233 | 234 | // good code 235 | const a = 3 236 | console.log(a) 237 | */ 238 | 'prefer-const': 'error', 239 | 240 | // eslint-plugin-vue@7 新增的规则,暂时先全部关闭 241 | 'vue/valid-v-slot': 'error', 242 | 'vue/experimental-script-setup-vars': 'off', 243 | 244 | // 不允许数组括号内有空格 245 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/array-bracket-spacing.md 246 | /** 247 | * 示例 248 | * bad code 249 | * var arr = [ 'foo', 'bar' ]; 250 | * var arr = ['foo', 'bar' ]; 251 | * var [ x, y ] = z; 252 | * 253 | * good code 254 | * var arr = ['foo', 'bar', 'baz']; 255 | * var arr = [['foo'], 'bar', 'baz']; 256 | * var [x, y] = z; 257 | */ 258 | 'vue/array-bracket-spacing': ['error', 'never'], 259 | 260 | // 在箭头函数的箭头之前/之后需要空格 261 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/arrow-spacing.md 262 | /** 263 | * 示例 264 | * bad code 265 | * ()=> {}; 266 | * () =>{}; 267 | * (a)=> {}; 268 | * (a) =>{}; 269 | * 270 | * good code 271 | * () => {}; 272 | * (a) => {}; 273 | * a => a; 274 | * () => {'\n'}; 275 | */ 276 | 'vue/arrow-spacing': ['error', {'before': true, 'after': true}], 277 | 278 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/attribute-hyphenation.md 279 | // vue html 属性小写,连字符 280 | /** 281 | * 示例 282 | * bad code 283 | * 284 | * 285 | * good code 286 | * 287 | */ 288 | 'vue/attribute-hyphenation': ['error', 'always'], 289 | 290 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/attributes-order.md 291 | // 属性顺序,不限制 292 | 'vue/attributes-order': 'off', 293 | 294 | // 在打开块之后和关闭块之前强制块内的空格 295 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/block-spacing.md 296 | /** 297 | * 示例 298 | * bad code 299 | * function foo() {return true;} 300 | * if (foo) { bar = 0;} 301 | * (a) =>{};function baz() {let i = 0; 302 | * return i; 303 | * } 304 | * 305 | * good code 306 | * function foo() { return true; } 307 | * if (foo) { bar = 0; } 308 | */ 309 | 'vue/block-spacing': ['error', 'always'], 310 | 311 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/camelcase.md 312 | // 后端数据字段经常不是驼峰,所以不限制 properties,也不限制解构 313 | /** 314 | * 示例 315 | * bad code 316 | * import { no_camelcased } from "external-module" 317 | * var my_favorite_color = "#112C85"; 318 | * obj.do_something = function() { 319 | * // ... 320 | * }; 321 | * 322 | * good code 323 | * import { no_camelcased as camelCased } from "external-module"; 324 | * var myFavoriteColor = "#112C85"; 325 | * var _myFavoriteColor = "#112C85"; 326 | * var myFavoriteColor_ = "#112C85"; 327 | */ 328 | 'vue/camelcase': ['error', {'properties': 'never'}], 329 | 330 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/comma-dangle.md 331 | // 禁止使用拖尾逗号,如 {demo: 'test',} 332 | /** 333 | * 示例 334 | * bad code 335 | * var foo = { 336 | * bar: "baz", 337 | * qux: "quux", 338 | * var arr = [1,2,]; 339 | * }; 340 | * 341 | * good code 342 | * var foo = { 343 | * bar: "baz", 344 | * qux: "quux" 345 | * var arr = [1,2]; 346 | */ 347 | 'vue/comma-dangle': ['error', 'never'], 348 | 349 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/comment-directive.md 350 | // vue 文件 template 中允许 eslint-disable eslint-enable eslint-disable-line eslint-disable-next-line 351 | // 行内注释启用/禁用某些规则,配置为 1 即允许 352 | /** 353 | * 示例 354 | * bad code 355 | *
356 | * 357 | * good code 358 | *
359 | */ 360 | 'vue/comment-directive': 'error', 361 | 362 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/component-name-in-template-casing.md 363 | // 组件 html 标签的形式,连字符形式,所有 html 标签均会检测,如引入第三方不可避免,可通过 ignores 配置,支持正则,不限制 364 | 'vue/component-name-in-template-casing': 'off', 365 | 366 | // 需要 === 和 !==,不将此规则应用于null 367 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/eqeqeq.md 368 | /** 369 | * 示例 370 | * bad code 371 | * if (x == 42) { } 372 | * if ("" == text) { } 373 | * if (obj.getStuff() != undefined) { } 374 | * var arr = [1,2,]; 375 | * }; 376 | * 377 | * good code 378 | * a === b 379 | * foo === true 380 | * bananas !== 1 381 | * value === undefined 382 | */ 383 | 'vue/eqeqeq': ['error', 'always', {'null': 'ignore'}], 384 | 385 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/html-closing-bracket-newline.md 386 | // 单行写法不需要换行,多行需要,不限制 387 | 'vue/html-closing-bracket-newline': 'off', 388 | 389 | // 自关闭标签需要空格 390 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/html-closing-bracket-spacing.md 391 | /* 示例 392 | 393 |
394 |
395 |
396 |
397 |
398 | 399 | 400 |
401 |
402 |
403 |
404 |
405 | */ 406 | 'vue/html-closing-bracket-spacing': ['error', { 407 | 'startTag': 'never', 408 | 'endTag': 'never', 409 | 'selfClosingTag': 'always' 410 | }], 411 | 412 | // 标签必须有结束标签 413 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/html-end-tags.md 414 | /* 示例 415 | 416 |
417 |

418 | 419 | 420 |

421 |

422 | */ 423 | 'vue/html-end-tags': 'error', 424 | 425 | // html的缩进.在多行情况下,属性不与第一个属性垂直对齐 426 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/html-indent.md 427 | /* 示例 428 | 429 |
433 | 434 | 435 |
439 | */ 440 | 'vue/html-indent': ['error', 4, { 441 | 'attribute': 1, 442 | 'baseIndent': 1, 443 | 'closeBracket': 0, 444 | 'alignAttributesVertically': false, // 在多行情况下,属性是否应与第一个属性垂直对齐 445 | 'ignores': [] 446 | }], 447 | 448 | // html属性引用采用双引号 449 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/html-quotes.md 450 | /* 示例 451 | 452 | 453 | 454 | 455 | 456 | */ 457 | 'vue/html-quotes': ['error', 'double'], 458 | 459 | 460 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/html-self-closing.md 461 | // html tag 是否自闭和,不限制 462 | 'vue/html-self-closing': 'off', 463 | 464 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/jsx-uses-vars.md 465 | // 当变量在 `JSX` 中被使用了,那么 eslint 就不会报出 `no-unused-vars` 的错误。需要开启 eslint no-unused-vars 规则才适用 466 | /* 467 | import HelloWorld from './HelloWorld'; 468 | 469 | export default { 470 | render () { 471 | return ( 472 | 473 | ) 474 | }, 475 | } 476 | 此时不会报 `no-unused-vars` 的错误,仅警告 477 | */ 478 | 'vue/jsx-uses-vars': 'warn', 479 | 480 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/key-spacing.md 481 | // 属性定义,冒号前没有空格,后面有空格 482 | /* 示例 483 | // bad code 484 | const obj = { a:1 } 485 | 486 | // good code 487 | const obj = { a: 1 } 488 | */ 489 | 'vue/key-spacing': ['error', {'beforeColon': false, 'afterColon': true}], 490 | 491 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/match-component-file-name.md 492 | // 组件名称属性与其文件名匹配,不限制 493 | 'vue/match-component-file-name': 'off', 494 | 495 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/max-attributes-per-line.md 496 | // 每行属性的最大个数,不限制 497 | 'vue/max-attributes-per-line': 'off', 498 | 499 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/multiline-html-element-content-newline.md 500 | // 在多行元素的内容前后需要换行符,不限制 501 | 'vue/multiline-html-element-content-newline': 'off', 502 | 503 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/mustache-interpolation-spacing.md 504 | // template 中 {{var}},不限制 505 | 'vue/mustache-interpolation-spacing': 'off', 506 | 507 | // name属性强制使用连字符形式 508 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/name-property-casing.md 509 | /* 示例 510 | // bad code 511 | export default { 512 | name: 'MyComponent' 513 | } 514 | 515 | // good code 516 | export default { 517 | name: 'my-component' 518 | } 519 | */ 520 | 'vue/name-property-casing': ['error', 'kebab-case'], 521 | 522 | // 禁止在计算属性中执行异步操作 523 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/no-async-in-computed-properties.md 524 | /* 示例 525 | computed: { 526 | // bad code 527 | pro () { 528 | return Promise.all([new Promise((resolve, reject) => {})]) 529 | }, 530 | foo1: async function () { 531 | return await someFunc() 532 | }, 533 | bar () { 534 | return fetch(url).then(response => {}) 535 | }, 536 | tim () { 537 | setTimeout(() => { }, 0) 538 | }, 539 | inter () { 540 | setInterval(() => { }, 0) 541 | }, 542 | anim () { 543 | requestAnimationFrame(() => {}) 544 | }, 545 | 546 | // good code 547 | foo () { 548 | var bar = 0 549 | try { 550 | bar = bar / this.a 551 | } catch (e) { 552 | return 0 553 | } finally { 554 | return bar 555 | } 556 | }, 557 | } 558 | */ 559 | 'vue/no-async-in-computed-properties': 'error', 560 | 561 | // 禁止布尔默认值,不限制 562 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/no-boolean-default.md 563 | 'vue/no-boolean-default': 'off', 564 | 565 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/no-confusing-v-for-v-if.md 566 | 'vue/no-confusing-v-for-v-if': 'off', 567 | 568 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/no-dupe-keys.md 569 | // 属性名禁止重复 570 | /* 示例 571 | // bad code 572 | person: { 573 | age: '', 574 | age: '' 575 | } 576 | 577 | // good code 578 | person: { 579 | age: '', 580 | name: '' 581 | } 582 | */ 583 | 'vue/no-dupe-keys': 'error', 584 | 585 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/no-duplicate-attributes.md 586 | // 禁止 html 元素中出现重复的属性 587 | /* 示例 588 | // bad code 589 |
590 | 591 | // good code 592 |
593 | */ 594 | 'vue/no-duplicate-attributes': 'error', 595 | 596 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/no-multi-spaces.md 597 | // 删除 html 标签中连续多个不用于缩进的空格 598 | /* 示例 599 | // bad code 600 |
601 | 602 | // good code 603 |
604 | */ 605 | 'vue/no-multi-spaces': 'error', 606 | 607 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/no-parsing-error.md 608 | // 禁止语法错误 609 | /* 示例 610 | // bad code 611 |
612 | 613 |
614 | 615 | // good code 616 |
617 | 618 |
619 | */ 620 | 'vue/no-parsing-error': 'error', 621 | 622 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/no-reserved-keys.md 623 | // 禁止使用保留字,包括Vue 624 | /* 示例 625 | // bad code 626 | props: { 627 | $nextTick () {} 628 | } 629 | 630 | // good code 631 | props: { 632 | next () {} 633 | } 634 | */ 635 | 'vue/no-reserved-keys': 'error', 636 | 637 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/no-restricted-syntax.md 638 | // 禁止使用特定的语法,不限制 639 | 'vue/no-restricted-syntax': 'off', 640 | 641 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/no-shared-component-data.md 642 | // data 属性必须是函数 643 | /* 示例 644 | // bad code 645 | data: { 646 | } 647 | 648 | // good code 649 | data() { 650 | return {} 651 | } 652 | */ 653 | 'vue/no-shared-component-data': 'error', 654 | 655 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/no-side-effects-in-computed-properties.md 656 | // 禁止在计算属性对属性进行修改,不限制 657 | 'vue/no-side-effects-in-computed-properties': 'off', 658 | 659 | // 不允许在属性中的等号周围有空格 660 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/no-spaces-around-equal-signs-in-attribute.md 661 | /* 示例 662 | // bad code 663 |
664 | 665 | // good code 666 |
667 | */ 668 | 'vue/no-spaces-around-equal-signs-in-attribute': 'error', 669 | 670 | 671 | // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/no-template-key.md 672 | // 禁止在