vue3+vite+ts+vueRouter+vuex+axios+element-plus搭建项目框架

本项目框架是基于vue3 + vite + TypeScript, 对vite 快速创建的框架做出的二次封装。

一、创建基础框架

npm init vite@latest

 项目框架初步创建成功,下面是进行二次的封装

二、配置文件引用别名

vite.config.ts:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from "path";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "src"),
    }
  },
})
tsconfig.json:

{
  "compilerOptions": {
   ......
    "baseUrl": ".",
    "paths": {
      "@/*":["src/*"]
    }
  },
}

如果编辑器中 path、__dirname上面显示红色波浪线,说找不到path,那就安装下:

cnpm install --save-dev @types/node

三、安装vue-router并配置路由

1、命令行安装

cnpm install vue-router --save

2、修改文件

在 src 文件下新增 router 文件夹 => index.ts 文件和routes.ts文件,src文件夹下新建pages文件夹,pages文件夹下新建home.vue

 

routes.ts:

import { RouteRecordRaw } from 'vue-router';

//对外暴露配置路由
export const routes: Array<RouteRecordRaw> = [
  {
    path: '/',
    name: 'home',
    component: () => import('@/pages/home.vue'), // 注意这里要带上 文件后缀.vue
    meta: {}
  },
]

 路由这里要注意:

1、引入的文件后缀名 .vue不能省掉,vue2是可以,vue3不行

2、其余找不到的路由去404页面,vue2与vue3写法也有区别:

    //vue2写法:
    {
        path: '*',
        redirect: '/404'
    }


    //vue3写法
    {
      path: '/:catchAll(.*)*',    // 匹配所有路径  vue2使用*   vue3使用/: pathMatch(.*)* 或 /: pathMatch(.*) 或 /: catchAll(.*)
      redirect: '/404',
    },
index.ts:

//通过vue-router插件实现模板路由配置
import { createRouter, createWebHashHistory } from 'vue-router'
import { routes } from './routes'
//创建路由器
const router = createRouter({
  //路由模式根据需求选择
  history: createWebHashHistory(),
  routes: routes,
})
export default router
App.vue:

<script setup lang="ts">
</script>

<template>
  <router-view/>
</template>

<style scoped>
</style>
home.vue:

<script setup lang="ts">

</script>
<template>
  <h1>home</h1>
</template>

<style scoped>
</style>
main.ts:

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './router/index'

const app = createApp(App)
app.use(router)
app.mount('#app')

四、引入sass

1、命令行安装

cnpm install sass --save-dev

2、修改文件

src文件夹下的asstes文件下新建css、img、js三个文件夹,到时候css就作为整体存放样式的文件

两个文件夹,分别作为公共样式和页面样式:公共样式里分为全局变量及全局样式

sass全局变量为方便使用可以在vite.config.ts中做引入:

 

css:{	
		preprocessorOptions: {
			// 全局sass变量引入
			scss:{
				additionalData: '@use "./src/assets/css/commonCss/globalVariate/index.scss" as *;',
			}
		},
},

 main.ts中引入公共样式:

五、安装axios

1、命令行安装

cnpm install axios --save

2、修改文件

src文件夹下新建axios文件,做axios的二次封装

六、安装vuex

1、命令行安装

cnpm install vuex --save

2、修改文件

src文件夹下新建vuex文件

七、引入element-plus组件库

1、命令行安装

cnpm install element-plus @element-plus/icons-vue --save

八、安装初始化样式、页面进度条、时间处理器

1、命令行安装

cnpm install normalize.css  nprogress moment --save

cnpm install qs @vueuse/core --save

九、安装echarts

1、命令行安装

cnpm install echarts --save

十、配置打包变量

分为三个环境:开发、测试、生产

 获取变量

所有安装已经结束啦,看下最终安装的:

"dependencies": {
    "@element-plus/icons-vue": "^2.3.1",
    "@vueuse/core": "^10.9.0",
    "axios": "^1.6.8",
    "echarts": "^5.5.0",
    "element-plus": "^2.7.1",
    "moment": "^2.30.1",
    "normalize.css": "^8.0.1",
    "nprogress": "^0.2.0",
    "qs": "^6.12.1",
    "vue": "^3.4.21",
    "vue-router": "^4.3.2",
    "vuex": "^4.1.0"
  },
  "devDependencies": {
    "@types/node": "^20.12.7",
    "@vitejs/plugin-vue": "^5.0.4",
    "rollup-plugin-visualizer": "^5.12.0",
    "sass": "^1.75.0",
    "terser": "^5.30.4",
    "typescript": "^5.2.2",
    "vite": "^5.2.0",
    "vite-plugin-compression": "^0.5.1",
    "vue-tsc": "^2.0.6"
  }

十一、vite.config.ts配置文件修改,做打包各项优化

1、分析打包后各个的大小体积

1.1、命令行安装

cnpm install rollup-plugin-visualizer --save-dev

1.2、修改代码

import { visualizer } from 'rollup-plugin-visualizer'


export default defineConfig({
  plugins: [
     // 打包体积分析
    visualizer({
      open: true,
      filename: 'visualizer.html' //分析图生成的文件名
    }),
  ],
})

打包完成会生成一个html文件,就可以看到各个包的体积大小

2、配置打包文件分类输出

build: {
    rollupOptions: {
      output: {
        chunkFileNames: 'js/[name]-[hash].js', // 引入文件名的名称
        entryFileNames: 'js/[name]-[hash].js', // 包的入口文件名称
        assetFileNames: '[ext]/[name]-[hash].[ext]', // 资源文件像 字体,图片等
        // 最小化拆分包 node_modules的包逐个打包 将需要分离的包单独的打包出来
        manualChunks(id) {
          if (id.includes('node_modules')) {
            return id.toString().split('node_modules/')[1].split('/')[0].toString();
          }
        }
      }
    }
}

3、开启Gzip文件压缩

3.1命令行安装

cnpm install vite-plugin-compression --save-dev

3.2修改文件

//Gzip文件压缩
import viteCompression from 'vite-plugin-compression'


export default defineConfig({
  plugins: [
     //开启Gzip压缩
    viteCompression({
      verbose: true, // 是否在控制台中输出压缩结果
      disable: false,
      threshold: 1024, // 如果体积大于阈值,将被压缩,单位为b,体积过小时请不要压缩,以免适得其反
      algorithm: 'gzip', // 压缩算法,可选['gzip',' brotliccompress ','deflate ','deflateRaw']
      ext: '.gz',
      deleteOriginFile: true // 源文件压缩后是否删除(我为了看压缩后的效果,先选择了true)
    })
  ],
})

4、开启图片压缩

4.1、命令行安装

cnpm install vite-plugin-imagemin --save-dev

4.2、修改文件

// 图片压缩
import viteImagemin from 'vite-plugin-imagemin'

export default defineConfig({
  plugins: [
     // 图片资源压缩
    viteImagemin({
      gifsicle: {
        // gif图片压缩
        optimizationLevel: 3, // 选择1到3之间的优化级别
        interlaced: false // 隔行扫描gif进行渐进式渲染
      },
      optipng: { // png
        optimizationLevel: 7 // 选择0到7之间的优化级别
      },
      mozjpeg: {// jpeg
        quality: 20 // 压缩质量,范围从0(最差)到100(最佳)。
      },
      pngquant: {// png
        quality: [0.8, 0.9], // Min和max是介于0(最差)到1(最佳)之间的数字,类似于JPEG。达到或超过最高质量所需的最少量的颜色。如果转换导致质量低于最低质量,图像将不会被保存。
        speed: 4 // 压缩速度,1(强力)到11(最快)
      },
      svgo: {
        plugins: [
          // svg压缩
          {
            name: 'removeViewBox'
          },
          {
            name: 'removeEmptyAttrs',
            active: false
          }
        ]
      }
    }),
  ],
})

5、terser 压缩和去除console+debugger

5.1、命令行安装

cnpm install terser --save-dev

5.2、修改文件

export default defineConfig({
   build: {
    minify: 'terser',
    // 清除所有console和debugger
    terserOptions: {
      compress: {
        drop_console: true,
        drop_debugger: true
      }
    }
  }
})

打包优化借鉴于此处,大家可以去看看:基于vite对vue3项目打包优化经验 【前端性能优化】 - 掘金

最终,图片压缩安装时报错了,后面再看看原因吧,呜呜呜~~~

十二、安装 eslint+Prettier做代码校验和代码格式化

1、安装

//安装
cnpm install eslint eslint-plugin-vue prettier eslint-plugin-prettier eslint-config-prettier -D

 这里注意个问题:安装最新的可能导致与nodejs版本不兼容报错,所以我直接写进package.json,安装固定版本的

"devDependencies": {
// typescript eslint 解析相关的包
"@typescript-eslint/eslint-plugin": "^7.9.0",
"@typescript-eslint/parser": "^7.9.0",
// eslint相关的包
"eslint": "^8.17.0",
"eslint-plugin-vue": "^9.1.0",
"vue-eslint-parser": "^9.0.2",
// prettier相关的包
"prettier": "^2.6.2",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "4.1.0",
}


 2、安装Prettier插件

找到扩展程序,安装一下:

 点设置图标-扩展设置-输入 .prettierrc.json 路径

 点设置-扩展-输入框输入 Default Formatter  ,选择 prettier 设置为默认的格式化程序

 输入框再输入  Format On Save, 勾选 在保存时格式化文件

 3、根目录下创建.prettierrc.json

{
  "printWidth": 80,
  "tabWidth": 2,
  "useTabs": false,
  "semi": true,
  "singleQuote": true,
  "quoteProps": "as-needed",
  "jsxSingleQuote": true,
  "trailingComma": "all",
  "bracketSpacing": true,
  "jsxBracketSameLine": true,
  "arrowParens": "avoid",
  "vueIndentScriptAndStyle": false,
  "embeddedLanguageFormatting": "off",
  "endOfLine": "auto"
}


printWidth: 80, //(默认值)单行代码超出 80 个字符自动换行
tabWidth: 2, //(默认值)一个 tab 键缩进相当于 2 个空格
useTabs: true, // 行缩进使用 tab 键代替空格
semi: false, //(默认值)语句的末尾加上分号
singleQuote: true, // 使用单引号
quoteProps: 'as-needed', //(默认值)仅仅当必须的时候才会加上双引号
jsxSingleQuote: true, // 在 JSX 中使用单引号
trailingComma: 'all', // 不用在多行的逗号分隔的句法结构的最后一行的末尾加上逗号
bracketSpacing: true, //(默认值)在括号和对象的文字之间加上一个空格
jsxBracketSameLine: true, // 把 > 符号放在多行的 JSX 元素的最后一行
arrowParens: 'avoid', // 当箭头函数中只有一个参数的时候可以忽略括弧
vueIndentScriptAndStyle: false, //(默认值)对于 .vue 文件,不缩进 <script> 和 <style> 里的内容
embeddedLanguageFormatting: 'off', // 不允许格式化内嵌的代码块,比如 markdown 文件里的代码块

4、根目录下创建.eslintrc.js

// `eslint`: EsLint的核心代码
// `eslint-plugin-vue`:[为Vue使用Eslint的插件](https://eslint.vuejs.org/)
// `@typescript-eslint/parser`:ESLint的解析器,用于解析typescript,从而检查和规范Typescript代码
// `@typescript-eslint/eslint-plugin`:这是一个ESLint插件,包含了各类定义好的检测Typescript代码的规范

// "eslint": "^8.17.0",
// "eslint-plugin-vue": "^9.1.0",
// "vue-eslint-parser": "^9.0.2",
// "@typescript-eslint/eslint-plugin": "7.9.0",
// "@typescript-eslint/parser": "7.9.0",
module.exports = {
  env: {
    browser: true,
    es2021: true,
    node: true,
  },
  parser: 'vue-eslint-parser', //这个不能少,要不然检测无效
  //优先级低于parse的语法解析配置
  parserOptions: {
    parser: '@typescript-eslint/parser',
    sourceType: 'module',
    ecmaVersion: 2020,
    ecmaFeatures: {
      jsx: true,
    },
  },
  // 继承已有的规则
  extends: [
    'eslint:recommended', // 使用推荐的eslint
    'plugin:vue/vue3-recommended', // 使用插件支持vue3
    //使用ts eslint
    'plugin:@typescript-eslint/recommended',
    //
    'prettier', // 必须放最后,依据 rules 生效的优先级,所以它会覆盖前面起冲突的规则
  ],
  // eslint-plugin-vue
  plugins: [
    'vue', // 引入vue的插件 vue <==> eslint-plugin-vue
    // 这个包需要安装了第7步的三个包再引入
    'prettier', // 引入规范插件  prettier
    '@typescript-eslint',
  ],
  overrides: [
    {
      files: [
        '*.js',
        '*.jsx',
        '*.vue',
        'src/**/*.js',
        'src/**/*.vue',
        'src/*.js',
        'src/*.vue',
      ],
      rules: {
        'no-undef': 'off',
      },
    },
  ],
  globals: {
    defineProps: 'readonly',
    defineEmits: 'readonly',
    defineExpose: 'readonly',
    withDefaults: 'readonly',
  },
  // 这里时配置规则的,自己看情况配置
  rules: {
    // js/ts
    // camelcase: ["error", { properties: "never" }], // 要求使用骆驼拼写法命名约定,不检查属性名称
    // camelcase: "warn", // 要求使用骆驼拼写法命名约定
    // "no-console": "warn", // 禁止出现console
    'no-debugger': 'warn', // 禁止出现debugger
    'no-unused-vars': 'off', //不能有声明后未被使用的变量或参数
    'no-duplicate-case': 'warn', // 禁止出现重复case
    // "no-empty": "warn", // 禁止出现空语句块
    // "no-extra-parens": "warn", // 禁止不必要的括号
    'no-func-assign': 'warn', // 禁止对Function声明重新赋值
    'no-unreachable': 'warn', // 禁止出现[return|throw]之后的代码块
    // "no-else-return": "warn", // 禁止if语句中return语句之后有else块
    // "no-empty-function": "warn", // 禁止出现空的函数块
    'no-lone-blocks': 'warn', // 禁用不必要的嵌套块
    // "no-multi-spaces": "warn", // 禁止使用多个空格
    'no-redeclare': 'warn', // 禁止多次声明同一变量
    'no-return-assign': 'warn', // 禁止在return语句中使用赋值语句
    'no-return-await': 'warn', // 禁用不必要的[return/await]
    'no-self-compare': 'warn', // 禁止自身比较表达式
    // "no-useless-catch": "warn", // 禁止不必要的catch子句
    // "no-useless-return": "warn", // 禁止不必要的return语句
    'no-multiple-empty-lines': 'warn', // 禁止出现多行空行
    'no-useless-call': 'warn', // 禁止不必要的.call()和.apply()
    'no-var': 'warn', // 禁止出现var用let和const代替
    'no-delete-var': 'off', // 允许出现delete变量的使用
    'no-shadow': 'off', // 允许变量声明与外层作用域的变量同名
    'dot-notation': 'warn', // 要求尽可能地使用点号
    'default-case': 'warn', // 要求switch语句中有default分支
    'no-useless-escape': 'off', //关闭正则里面的转义  禁止不必要的转义字符
    // eqeqeq: "warn", // 要求使用 === 和 !==
    // curly: "warn", // 要求所有控制语句使用一致的括号风格
    // "space-before-blocks": "warn", // 要求在块之前使用一致的空格
    // "space-in-parens": "warn", // 要求在圆括号内使用一致的空格
    // "space-infix-ops": "warn", // 要求操作符周围有空格
    // "space-unary-ops": "warn", // 要求在一元操作符前后使用一致的空格
    // "switch-colon-spacing": "warn", // 要求在switch的冒号左右有空格
    // "arrow-spacing": "warn", // 要求箭头函数的箭头前后使用一致的空格
    // "array-bracket-spacing": "warn", // 要求数组方括号中使用一致的空格
    // "brace-style": "warn", // 要求在代码块中使用一致的大括号风格
    // indent: ["warn", 2], // 要求使用JS一致缩进2个空格
    // "max-depth": ["warn", 4], // 要求可嵌套的块的最大深度4
    // "max-statements": ["warn", 100], // 要求函数块最多允许的的语句数量20
    // "max-nested-callbacks": ["warn", 3], // 要求回调函数最大嵌套深度3
    // "max-statements-per-line": ["warn", { max: 1 }], // 要求每一行中所允许的最大语句数量
    quotes: ['warn', 'single', 'avoid-escape'], // 要求统一使用单引号符号

    //prettier
    //代码校验会以下面这个为标准做校验
    // .prettierrc.json 生效是在做保存时会自动按照这个标准做格式化
    // 所以要注意:下面这个要跟 .prettierrc.json里面保持一致,这样才能保证你写的代码与要校验代码的工具标准一致,不然你保存时自动格式化与你的校验工具标准不一样,会冲突
    'prettier/prettier': [
      'error',
      {
        printWidth: 80,
        tabWidth: 2,
        useTabs: false,
        semi: true,
        singleQuote: true,
        quoteProps: 'as-needed',
        jsxSingleQuote: true,
        trailingComma: 'all',
        bracketSpacing: true,
        jsxBracketSameLine: true,
        arrowParens: 'avoid',
        vueIndentScriptAndStyle: false,
        embeddedLanguageFormatting: 'off',
        endOfLine: 'auto',
      },
    ],

    // vue
    'vue/no-v-html': 'off',
    'vue/require-default-prop': 'off',
    'vue/require-explicit-emits': 'off',
    'vue/multi-word-component-names': 'off',
    'vue/prefer-import-from-vue': 'off',
    'vue/no-v-text-v-html-on-component': 'off',
    // 取消关闭标签不能自闭合的限制设置
    'vue/html-self-closing': ['off'],
    // 取消标签的第一个属性独占一行
    'vue/first-attribute-linebreak': [
      'error',
      {
        singleline: 'ignore',
        multiline: 'ignore',
      },
    ],
    // "vue/require-default-prop": 0, // 关闭属性参数必须默认值
    // "vue/singleline-html-element-content-newline": 0, // 关闭单行元素必须换行符
    // "vue/multiline-html-element-content-newline": 0, // 关闭多行元素必须换行符
    // 要求每一行标签的最大属性不超五个
    // "vue/max-attributes-per-line": ["warn", { singleline: 5 }],
    // 要求html标签的缩进为需要2个空格
    // "vue/html-indent": [
    //   "warn",
    //   2,
    //   {
    //     attribute: 1,
    //     baseIndent: 1,
    //     closeBracket: 0,
    //     alignAttributesVertically: true,
    //     ignores: [],
    //   },
    // ],

    // ts
    '@typescript-eslint/no-explicit-any': 'off', // 关闭定义any的错误
    '@typescript-eslint/explicit-module-boundary-types': 'off',
    '@typescript-eslint/no-non-null-assertion': 'off',
    '@typescript-eslint/no-non-null-asserted-optional-chain': 'off',
    '@typescript-eslint/consistent-type-imports': [
      'error',
      { disallowTypeAnnotations: false },
    ],
    '@typescript-eslint/ban-ts-comment': ['off', { 'ts-ignore': false }],
    '@typescript-eslint/no-empty-function': 'off',
    '@typescript-eslint/no-this-alias': ['off'], //关闭 let that = this报错问题
    '@typescript-eslint/no-unused-vars': ['error', { args: 'after-used' }], //声明但没有用的变量会报错,但是用 after-used,函数参数里面只要最后一个变量被用到了,也就不会报错
  },
};

打开vscode   找到setting.json:

{
  "workbench.colorTheme": "Default Dark Modern",
  "editor.fontSize": 19,
  "security.workspace.trust.untrustedFiles": "open",
  //prettier
  "editor.formatOnSave": true, // 开启保存文件自动格式化代码
  "prettier.requireConfig": true, // 需要Prettier的配置文件
  "prettier.configPath": ".prettierrc.json", //配置路径文件名
  //以下两个 editor.defaultFormatter 二选一就好
  // 有.prettierrc.json的话,开启自己prettier规则的自动格式化保存
  "editor.defaultFormatter": "esbenp.prettier-vscode", // 默认的代码格式化工具
  //没有.prettierrc.json的话就开启下面这个格式化标准
  // "[vue]": {
  //   "editor.defaultFormatter": "Vue.volar"
  // },
  //
  // 添加vue支持
  "eslint.validate": ["javascript", "javascriptreact", "vue", "html"],
  // #让prettier使用eslint的代码格式进行校验
  // "prettier.eslintIntegration": true,
  "editor.codeActionsOnSave": {},
  "fileheader.Author": "linxinze",
  "fileheader.LastModifiedBy": "linxinze",
  "prettier.endOfLine": "auto"
}

这样可做到保存时自动格式化代码啦~

十三、项目中遇到的问题

1、无法找到模块“xxxxxx”的声明文件

找到vite-env.d.ts 文件,添加声明:

// 解决引入模块的报错提示
declare module "nprogress";

2、无法找到模块“xxx.vue”的声明文件

找到vite-env.d.ts 文件,添加声明:

// 解决引入.vue模块的报错提示
declare module "*.vue" {
    import { DefineComponent } from "vue";
    const component: DefineComponent<{}, {}, any>;
    export default component;
}

3、无法找到模块“xxx.js”的声明文件

找到vite-env.d.ts 文件,添加声明:

// 解决引入.js模块的报错提示
declare module '*.js'

4、无法找到模块“vuex”的声明文件

找到tsconfig.json 文件,添加:

{
  "compilerOptions": {
  	...
    "paths": {
      "vuex": ["./node_modules/vuex/types"] 
    }
    ...
  }
}

使用 “paths” 映射,在找不到模块的默认路径时,将其映射到类型定义文件

好了,后面再更新吧,有用的点个赞啦~~~

关于vue2升级vue3也有一篇,都没有很全,后面再学习补充,这里放个链接:

vue2项目升级至vue3(vue3+vite+ts)_vue2项目升级为vue3项目-CSDN博客

Vite是一个用于快速构建现代化的Web项目的构建工具,它专注于开发阶段的快速热重载,并使用ES模块作为原生的开发模式。Vue3是Vue.js的最新版本,它在性能、开发体验和可维护性上都有所提升。 针对你提到的具体的库和框架: - Vue RouterVue.js官方的路由管理器,用于实现页面之间的导航和路由控制。你可以通过npm安装vue-router,并在项目中进行配置和使用。 - Pinia是Vue.js的状态管理库,它提供了一种简单而强大的方式来管理应用程序的状态。你可以集成Pinia到你的Vue项目中,以便更好地组织和共享你的应用程序状态。 - Axios是一个基于Promise的HTTP客户端,用于通过网络发送异步请求。你可以使用Axios来处理与服务器的通信,并获取数据来更新你的Vue应用程序。 - Element Plus是一套基于Vue3的组件库,包含了丰富的UI组件,可以帮助你快速搭建漂亮的用户界面。你可以在项目中安装和使用Element Plus来实现各种交互效果和用户界面。 如果你想使用ViteVue3和以上提到的库和框架来创建一个项目,你可以按照以下步骤进行: 1. 安装Vite:通过npm全局安装Vite,然后使用Vite命令初始化一个新的项目。 2. 配置Vite:根据你的项目需求,在Vite的配置文件中添加Vue Router、Pinia、AxiosElement Plus的相关配置。 3. 安装和配置Vue Router:通过npm安装Vue Router,并在项目中配置和使用Vue Router来管理应用程序的路由。 4. 集成Pinia:通过npm安装Pinia,并在项目中引入和配置Pinia,以便在应用程序中使用Pinia来管理状态。 5. 使用Axios:通过npm安装Axios,并在项目中引入和配置Axios,以便进行网络请求和数据获取。 6. 引入Element Plus:通过npm安装Element Plus,并在项目中按需引入和使用Element Plus的组件,以搭建漂亮的用户界面。 希望以上信息对你有帮助,祝你在使用ViteVue3和这些库和框架时取得成功!<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [vite-vue-ts精简模版集成pinia+svg+router+@src](https://download.csdn.net/download/ldy889/85018930)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [vite+vue3+ts+vue-router+pinia+axios+element-plus](https://blog.csdn.net/zy_080400/article/details/127125359)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

仰望半月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值