日常整理的一些前端知识点笔记

整理的一些前端知识点

ECMAScript和JavaScript是什么关系

ECMAScript 和 JavaScript 的关系是,前者是后者的规格,后者是前者的一种实现
(另外的 ECMAScript 方言还有 JScript 和 ActionScript)。日常场合,这两个词是可以互换的
参阅:https://es6.ruanyifeng.com/#docs/intro

什么是Babel

Babel 是一个广泛使用的 ES6 转码器,可以将 ES6 代码转为 ES5 代码,
从而在老版本的浏览器执行。这意味着,你可以用 ES6 的方式编写程序,又不用担心现有环境是否支持

什么是Promise

Promise 是异步编程的一种解决方案,比传统的解决方案------回调函数和事件------更合理和更强大。
它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了`Promise`对象。
所谓`Promise`,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。
Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

什么是Node.js

Node.js
Ryan Dahl在2009年创造了Node.js。
它是基于Google的V8 JavaScript解释引擎(在Chrome浏览器里它负责执行客户端的JavaScript代码)。
与其它语言不同的是Node.js内置了处理网络请求和响应的函数库,
所以你不需要单独的服务器(Apache、Ngix)或者其他依赖。
Node.js虽然很新但是很快就获得了极大的追捧。在很多的大公司都有在使用,例如:Microsoft,Yahoo,LinkedIn和PayPal。

有一些工具给 Node.js 些许优势:NPM-包管理器。 NPM 允许你安装和管理依赖,设置配置变量,定义脚本和其他

若干年前,JavaScript 被认为限制很多,有一些边缘技术,但是他的主战场还是浏览器。
Node.js 已经改变了这一感觉并井喷出了很多 JavaScript 项目,你可以在任何地方使用 JavaScript:浏览器,服务器,终端,桌面甚至嵌入式系统,这使得 JavaScript 无处不在

Node.js 还是有如下几条优势的
更少的依赖
更小更快的解释器
应用永久在线Node.js 应用持久运行,只需要启动一次
事件驱动,无阻塞 I/O

参阅:
Node.js 命令行程序开发教程
https://www.runoob.com/w3cnote/node-js-command-develop.html
2015年需要了解的前端框架和语言
https://www.runoob.com/w3cnote/2015-frameworkds-need-to-learn.html

如何让js控制台打印彩色日志

javascript 复制代码
console.log() 这个应该是最常用的
console.error() 输出错误信息 会以红色显示
console.assert(bool,"info") 如果bool为false 打印出info 否则不打印
console.warn() 打印警告信息 会以黄色显示
console.info() 打印一般信息

console.log(
                  `%c lte-admin %c 退出系统ok %c`,
                  'background:blue ; padding: 1px; border-radius: 3px 0 0 3px;  color: #fff',
                  'background:red ; padding: 1px; border-radius: 0 3px 3px 0;  color: #fff',
                  'background:transparent'
          );

/*
参阅:
https://blog.csdn.net/tietth/article/details/68943460
https://blog.csdn.net/kids_calamus/article/details/82719926
*/

什么是npm和yarn

node.js 自带了npm

npm是node.js的包管理器,类似于java世界的maven

npm默认的镜像源访问很慢,一般都使用国内的镜像源
方法1:安装淘宝cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org
方法2: 把npm的默认镜像源改为淘宝的镜像
npm config set registry https://registry.npm.taobao.org

npm常用命令
安装所有依赖 npm install
安装单个依赖法1  npm install 依赖名 --save
安装单个依赖法2  npm -S install 依赖名

运行项目 npm run dev (vue2项目)
运行项目 npm run serve (vue3项目)
打包项目 npm run build

===========================================

Yarn 是一个可以替代npm的node.js包管理器,它比npm/cnpm安装依赖更快
官网https://yarn.bootcss.com/docs/getting-started/

npm全局安装yarn
npm install -g yarn --registry=https://registry.npm.taobao.org

npm命令对应的yarn命令
https://yarn.bootcss.com/docs/migrating-from-npm/

yarn设置淘宝源
yarn config set registry https://registry.npm.taobao.org -g
yarn config set sass_binary_site http://cdn.npm.taobao.org/dist/node-sass -g

yarn常用命令
安装所有依赖 yarn install
安装某个依赖 yarn add [package]
清除本地缓存 yarn cache clean
删除一个依赖包 yarn remove [package]
运行项目  yarn run serve
打包项目   yarn run build

如何生成npm打包分析报告

npm run build -- --report
生成 dist 文件夹 下面的 report.html 文件
参阅:
https://blog.csdn.net/mrhaoxiaojun/article/details/108519930
https://blog.csdn.net/qq_39523111/article/details/108790661

如何快速预览npm run build生成的dist包

1. npm  install -g serve
2. serve  -s dist  
(-s意思是将其架设在SPA模式下)

如何快速删除npm生成的node_modules

1. 安装 rimraf
npm install rimraf -g 

2. 使用命令删除 
rimraf node_modules // 也可以删除其它文件夹或文件

如何让img等比缩放显示在div里面

css 复制代码
img{
width: auto;
height: auto;
max-width: 100%;
max-height: 100%;
}

什么是REST

REST全称是Representational State Transfer,中文意思是 表述性状态转移

REST原则
资源与URI/统一资源接口/资源的表述/资源的链接/状态的转移


---
资源的表述
客户端获取的只是资源的表述而已。
资源在外界的具体呈现,可以有多种表述(或成为表现、表示)形式,在客户端和服务端之间传送的也是资源的表述,而不是资源本身。
例如文本资源可以采用html、xml、json等格式,图片可以使用PNG或JPG展现出来。
资源的表述包括数据和描述数据的元数据,例如,HTTP头"Content-Type" 就是这样一个元数据属性。
那么客户端如何知道服务端提供哪种表述形式呢?
答案是可以通过HTTP内容协商,客户端可以通过Accept头请求一种特定格式的表述,
服务端则通过Content-Type告诉客户端资源的表述形式

---

GET
安全且幂等
获取表示
变更时获取表示(缓存)
200(OK) - 表示已在响应中发出
204(无内容) - 资源有空表示
301(Moved Permanently) - 资源的URI已被更新
303(See Other) - 其他(如,负载均衡)
304(not modified)- 资源未更改(缓存)
400 (bad request)- 指代坏请求(如,参数错误)
404 (not found)- 资源不存在
406 (not acceptable)- 服务端不支持所需表示
500 (internal server error)- 通用错误响应
503 (Service Unavailable)- 服务端当前无法处理请求

---
POST
不安全且不幂等
使用服务端管理的(自动产生)的实例号创建资源
创建子资源
部分更新资源
如果没有被修改,则不过更新资源(乐观锁)
200(OK)- 如果现有资源已被更改
201(created)- 如果新资源被创建
202(accepted)- 已接受处理请求但尚未完成(异步处理)
301(Moved Permanently)- 资源的URI被更新
303(See Other)- 其他(如,负载均衡)
400(bad request)- 指代坏请求
404 (not found)- 资源不存在
406 (not acceptable)- 服务端不支持所需表示
409 (conflict)- 通用冲突
412 (Precondition Failed)- 前置条件失败(如执行条件更新时的冲突)
415 (unsupported media type)- 接受到的表示不受支持
500 (internal server error)- 通用错误响应
503 (Service Unavailable)- 服务当前无法处理请求

---
PUT
不安全但幂等
用客户端管理的实例号创建一个资源
通过替换的方式更新资源
如果未被修改,则更新资源(乐观锁)
200 (OK)- 如果已存在资源被更改
201 (created)- 如果新资源被创建
301(Moved Permanently)- 资源的URI已更改
303 (See Other)- 其他(如,负载均衡)
400 (bad request)- 指代坏请求
404 (not found)- 资源不存在
406 (not acceptable)- 服务端不支持所需表示
409 (conflict)- 通用冲突
412 (Precondition Failed)- 前置条件失败(如执行条件更新时的冲突)
415 (unsupported media type)- 接受到的表示不受支持
500 (internal server error)- 通用错误响应
503 (Service Unavailable)- 服务当前无法处理请求

---
DELETE
不安全但幂等
删除资源
200 (OK)- 资源已被删除
301 (Moved Permanently)- 资源的URI已更改
303 (See Other)- 其他,如负载均衡
400 (bad request)- 指代坏请求
404 (not found)- 资源不存在
409 (conflict)- 通用冲突
500 (internal server error)- 通用错误响应
503 (Service Unavailable)- 服务端当前无法处理请求

vue前端如何对接基于stompjs的websocket通信

可以使用stompjs 或者 socketjs-client来发送或订阅消息
npm install sockjs-client
npm install stompjs

参阅:
   git地址:
     前端vue:https://gitee.com/lddjava/vue-socket-demo.git
     后端服务:https://gitee.com/lddjava/vue-service-websocket.git

SPA单页应用实现浏览器跳转时的顶部进度条效果

可以使用NProgress组件实现页面跳转时出现在浏览器页面顶部的进度条
安装nprogress依赖
$ npm install --save nprogress 或者
$ yarn add nprogress

//用法
NProgress.start();
NProgress.done();

//导入
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'

router.beforeEach((to, from, next) => {
  NProgress.start()
  next()
})

router.afterEach(() => {
  NProgress.done()
})

参阅:
https://blog.csdn.net/wn1245343496/article/details/82151273

vue项目中如何使用cookie存取数据

可以使用js-cookie组件
安装依赖
 npm install  js-cookie --save

vue项目中如何使用MD5摘要

可以使用js-md5组件
安装依赖
 npm install  js-md5 --save

vue项目中如何使用JSX

vue 复制代码
JSX = Javascript + XML,即在 Javascript 里面写 XML
在 Vue 中使用 JSX,需要使用 Babel 插件

安装依赖
 npm install @vue/babel-preset-jsx @vue/babel-helper-vue-jsx-merge-props

配置 babel.config.js

 module.exports = {
   presets: [
     '@vue/cli-plugin-babel/preset',
     ['@vue/babel-preset-jsx',
       {
         'injectH': false
       }]
   ]
 }

这里展示在 Vue 中用jsx的render渲染一些基础内容,包括纯文本、动态内容、标签使用、自定义组件的使用,
这些跟我们平时使用单文件组件类似
render() {
  return (
    <div>
      <h3>内容</h3>
      {/* 纯文本 */}
      <p>hello, I am Gopal</p>
      {/* 动态内容 */}
      <p>hello { this.msg }</p>
      {/* 输入框 */}
      <input />
      {/* 自定义组件 */}
      <myComponent></myComponent>
    </div>
  );
}

参阅:
https://www.jianshu.com/p/9616745a8d0a

在vue中如何监听浏览器窗口大小变化

vue 复制代码
首先,页面初始化mounted的时候,
通过 document.body.clientWidth 和 document.body.clientHeight 
来获取到浏览器的宽和高,
然后通过 window.onresize 来监听浏览器窗口的变化,
在这里来改变我们的变量宽和高即可。
(注意:created()的时候不行,因为此时document还没有生成)

<template>
  <section class="p-10">
    <h1> {{ screenWidth }} × {{ screenHeight }} </h1>
  </section>
</template>
<script>
  export default {
    data() {
      return {
        screenWidth: '',
        screenHeight: ''
      };
    },
    mounted() {
      this.screenWidth = document.body.clientWidth;
      this.screenHeight = document.body.clientHeight;
      window.onresize = () => {
        return (() => {
          this.screenWidth = document.body.clientWidth;
          this.screenHeight = document.body.clientHeight;
        })();
      };
    }
  }
</script>

<style lang="scss">
</style>

参阅:
https://blog.csdn.net/ju__ju/article/details/103389208
https://www.cnblogs.com/jin-zhe/p/10506238.html

SPA项目如何实现全屏和退出全屏效果

vue 复制代码
可以使用screenfull组件

安装依赖
npm install --save screenfull

在需要的页面引用
import screenfull from 'screenfull'

核心方法
screenfull.toggle()

具体代码

<template>
  <span @click='clickFullscreen'>全屏</span>
</template>

<script>
  import screenfull from 'screenfull'
  export default{
    name: 'screenfull',
    data(){
      return {
        isFullscreen: false
      }
    },
    methods:{
      clickFullscreen(){
        if (!screenfull.isEnabled) {
          this.$message({
            message: 'you browser can not work',
            type: 'warning'
          })
          return false
        }
        screenfull.toggle()
      }
    }
  }
</script>

参阅:
https://www.cnblogs.com/wjw-/p/11550617.html

常用的前端图表开发库有哪些

Viser是Alibaba开发的图表工具-基于AntV-G2可视化引擎,
可以参阅:
https://www.cnblogs.com/wurijie/p/11775303.html
 https://blog.csdn.net/m0_37903882/article/details/106105047

echarts是百度开发的图表工具,已被Apache收录,开发者用的较多,,因为教程多,素材多
可以参阅:
http://echarts.apache.org/zh/index.html  官网
https://echarts.apache.org/zh/tutorial.html#5%20%E5%88%86%E9%92%9F%E4%B8%8A%E6%89%8B%20ECharts

SPA项目实现视频播放的组件有哪些

一般浏览器在线视频播放的媒体格式有 m3u8 / mp4 /ts /flv 等多种格式

一般情况下,1个.m3u8 = n个.ts视频文件;当然也可以直接播放一个大.ts视频文件。
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:8
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:7.040000,
5801dba1122000000.ts
#EXTINF:3.760000,
5801dba1122000001.ts
#EXTINF:4.800000,
5801dba1122000002.ts
#EXTINF:4.000000,
5801dba1122000003.ts
#EXTINF:3.080000,
...
5801dba1122000118.ts
#EXT-X-ENDLIST

m3u8本质是一个txt,这个txt规定了1个视频的 哪一段是哪一个ts播放的;

TS(Transport Stream,传输流)是一种封装的格式,它的全称为MPEG2-TS。是一种视频格式,一般用于实时流媒体和广播电视领域

mp4,一种支持本地和在线播放的视频格式,不用过多介绍,大家电脑上应该都有不少。

flv格式的视频文件:一般用迅雷等工具从一些视频网站上下载出来的都是flv文件,flv文件需要转码后才能在本地播放,浏览器中则可以直接用相关的js组件播放flv文件,如flv.js

使用jsmpeg-player组件

react 复制代码
可以使用jsmpeg-player组件来控制播放.ts视频
组件官网 https://www.npmjs.com/package/@cycjimmy/jsmpeg-player

安装依赖
npm install --save  @cycjimmy/jsmpeg-player

使用案例
   import React, { useEffect, useState, useRef } from 'react';
                import './index.less';
                import JSMpeg from '@cycjimmy/jsmpeg-player';

                export default function VideoTs(props) {
                  //封面
                  const cover ='https://img11.360buyimg.com/imagetools/jfs/t1/105707/30/17596/32160/5e8c8ae6Ee2bfd8db/1ef4084de9ec103f.jpg'
                  const tsSrc='https://storage.360buyimg.com/xingdianzhang/%E6%B5%8B%E8%AF%95ts.ts'
                  const hdVideo = useRef(null);
                  var [isCover, setIsCover] = useState(true);//是否用封面覆盖
                  useEffect(() => {
                    initTs()
                  }, [])

                  function initTs() {
                    let canvas = hdVideo.current.querySelector('.hdVideo-ts');
                    canvas.style.width = '0px'
                    new JSMpeg.VideoElement(canvas, tsSrc, {
                      canvas,
                      autoplay: true,
                      loop: true,
                      progressive: false,//是否为chunk
                      control: false,
                      poster: cover,
                      preserveDrawingBuffer: true,
                      decodeFirstFrame: true,
                      disableGl: true,
                    }, {
                      audio: false, //静音
                      onPlay: () => {
                        canvas.style.width = hdVideo.current.clientWidth + 'px'
                        setIsCover(false)
                      }
                    })
                  }

                  return (
                    <div ref={hdVideo} className='hdVideo'>
                      {isCover ? <img className="hdVideo-image" src={cover} /> : null}
                      <canvas className="hdVideo-ts"></canvas>
                    </div>
                  );
                }


                <!--index.less-->
                .hdVideo{
                    width: 750px;
                    height: 400px;
                    .hdVideo-image{
                        width: 100%;
                        height: 100%;
                    }
                    .hdVideo-ts{
                        width: 100%;
                        height: 100%;
                    }
                }
//------------------------------------- 
参阅:
https://www.jianshu.com/p/b6d08be5fcc3
https://www.reneelab.com.cn/what-is-ts-file-and-how-to-play-ts-video.html

使用dplayer组件

vue 复制代码
dplayer官网文档表示可以播放 m3u8 / mp4 /flv 这3种格式
官网:http://dplayer.js.org/zh/guide.html#hls

安装依赖
npm install --save dplayer

使用案例
<template>
    <div id="dplayer_m3u8"></div>
</template>

<script>
    import DPlayer from 'dplayer';
    export default {
        name: "M3U8Player",
        data(){
            return{
 /* playUrl可以是 m3u8 / mp4 /flv 这3种后缀格式的url地址 */               playUrl:"https://www.nmgxwhz.com:65/20201121/1UwOkSqv/1200kb/hls/index.m3u8"
            }
        },
        methods: {
            play() {
                console.log('play callback')
            }
        },
        mounted() {
            const dp = new DPlayer({
                container: document.getElementById('dplayer_m3u8'),
                video: {
                    url: this.playUrl,
                    type: 'hls'
                },
                autoplay: false,
                theme: '#FADFA3',
                loop: false,
                lang: 'zh-cn',
                screenshot: true,
                hotkey: true,
                preload: 'auto',
                volume: 0.7,
                mutex: true,
            });
        }
    }
</script>

<style scoped>
</style>

----------------------------------------------------
后台推送视频流的方法:
Java后台将视频文件以流的形式传给前端,
不同文件ContentType不同 
application/vnd.apple.mpegurl   对应 m3u8
video/mp4  对应mp4

	@ResponseBody
    @RequestMapping("/getVideoSrc")
    public OutputStream getVideoSrc(HttpServletRequest httpServletRequest,
                                    HttpServletResponse httpServletResponse){
        //1.创建文件对象
        File f = new File("E:/test/1.mp4");
        //2.获取文件名称
        String fileName = f.getName();
        //3.导出文件
        String agent = httpServletRequest.getHeader("User-Agent").toUpperCase();
        InputStream fis = null;
        OutputStream os = null;
        try {
            //4.获取输入流
            fis = new BufferedInputStream(new FileInputStream(f.getPath()));
            byte[] buffer;
            buffer = new byte[fis.available()];
            fis.read(buffer);
            httpServletResponse.reset();
            //5.由于火狐和其他浏览器显示名称的方式不相同,需要进行不同的编码处理
            if(agent.indexOf("FIREFOX") != -1){//火狐浏览器
                httpServletResponse.addHeader("Content-Disposition", "attachment;filename="+ new String(fileName.getBytes("GB2312"),"ISO-8859-1"));
            }else{//其他浏览器
                httpServletResponse.addHeader("Content-Disposition", "attachment;filename="+ URLEncoder.encode(fileName, "UTF-8"));
            }
            //6.设置response编码
            httpServletResponse.setCharacterEncoding("UTF-8");
            httpServletResponse.addHeader("Content-Length", "" + f.length());
            //设置输出文件类型
            httpServletResponse.setContentType("video/mpeg4");
            //7.获取response输出流
            os = httpServletResponse.getOutputStream();
            os.flush();
            //8.输出文件
            os.write(buffer);
        }catch(Exception e){
            System.out.println(e.getMessage());
        } finally{
            //关闭流
            try {
                if(fis != null){ fis.close(); }

                if(os != null){ os.flush(); }

                if(os != null){os.close(); }

            } catch (IOException e) {
                System.out.println(e.getMessage());
            }
        }

        return os;
    }

参阅:
https://blog.csdn.net/weixin_42490316/article/details/106884802

什么是JSONP跨域

jsonp跨域,是一种利用h5中的<script src="xxx" />来接收不同域名下的url返回数据的一种方法。
因为script标签天然支持跨域,
而其他的ajax ,jq等request组件在同一个页面访问多个域名下的url时会遇到跨域问题需要解决,要么通过前端proxy代理解决,要么通过后端设置接口支持跨域请求。

而jsonp跨域,是一种轻量的简便的做法,它只需要后台接口按照jsonp的规范返回字符串数据,
然后前端通过<script src="xxx" />来接收后,会自动解出字符串中数据,再进行前端业务代码。

jsonp跨域,不需要后端改API接口,也不需要前端搞nginx代理,是一种规避 跨域资源访问 的方法,因为W3C规范里允许了<script src="xxx" /> 是允许跨域获取数据的。

vue项目中如何使用jsonp跨域

javascript 复制代码
场景:一个上线多年的vue项目,要增加一个xx组件,需要跨域访问其他服务器的url

可以使用npm提供的jsonp组件

安装依赖
npm i  jsonp -S

使用案例
    import originJSONP from 'jsonp'

   let url02 = 'http://whois.pconline.com.cn/ipJson.jsp';
            originJSONP(url02, {}, (err, data) => {
                console.log('????????????????===')
                if (!err) {
                    console.log(data)
                      this.addr = data;

                } else {
                    console.log(err)
                }
            });

做一个VUE-SPA项目可以参考的东西

开源UI库

https://www.antdv.com/docs/vue/introduce-cn/
Ant Design of Vue UI库
是 Ant Design 的 Vue 实现,开发和服务于企业级后台产品


https://pro.antdv.com/docs/getting-started
Ant Design Pro 是一个企业级中后台前端/设计解决方案
只有前端Admin,没有后端--官方提供

https://element.eleme.cn/#/zh-CN
Element UI 官方地址
Element,一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的桌面端组件库

开源npm组件库

vue-uuid
一种spa项目里使用uuid的工具类组件,可以生成uuid,一般在需要前端来生成唯一键时使用。
安装依赖方法:  npm install vue-uuid --save

vxe表格
一种专业的符合企业级需要的前端表格组件,其中实现了多种表格方案,要比antdvue和elemtui丰富
安装依赖方法: npm install vxe-table xe-utils --save

lodash库
lodash是一种包含了多种js操作的库,里边封装了对数组、json等对象的快速操作,可以当js工具类用,比jquery功能不弱
安装依赖方法: npm install lodash --save

开源Admin项目/博客文章

https://iczer.gitee.io/vue-antd-admin-docs/
开箱即用的Antdv 中台前端/设计解决方案--非官方
https://iczer.gitee.io/vue-antd-admin
只有前端Admin,没有后端


http://www.jeecg.com/
http://boot.jeecg.com/
https://gitee.com/jeecg/jeecg-boot
前后端分离架构SpringBoot 2.x,SpringCloud,Ant Design&Vue,Mybatis-plus,Shiro,JWT。强大的代码生成器让前后端代码一键生成,

https://chu1204505056.gitee.io/vue-admin-beautiful/#/index
https://gitee.com/chu1204505056/vue-admin-beautiful
开箱即用的ElementUI 中台前端/设计解决方案--非官方
只有前端Admin,没有后端


https://gitee.com/y_project/RuoYi-Vue
前端采用Vue、Element UI。
后端采用Spring Boot、Spring Security、Redis & Jwt

https://gitee.com/renrenio/renren-fast-vue
renren-fast-vue基于vue、element-ui构建开发,实现renren-fast后台管理前端功能,提供一套更优的前端解决方案

https://qqdie.com/cssjs/
https://blog.csdn.net/weixin_42490316/article/details/106884802
https://www.qt86.com/
相关推荐
迷雾漫步者1 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-2 小时前
验证码机制
前端·后端
燃先生._.3 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖4 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
m0_748235244 小时前
前端实现获取后端返回的文件流并下载
前端·状态模式
冷眼看人间恩怨4 小时前
【Qt笔记】QDockWidget控件详解
c++·笔记·qt·qdockwidget
m0_748240255 小时前
前端如何检测用户登录状态是否过期
前端
black^sugar5 小时前
纯前端实现更新检测
开发语言·前端·javascript
落魄实习生5 小时前
AI应用-本地模型实现AI生成PPT(简易版)
python·ai·vue·ppt