# vue-project-master **Repository Path**: qinqiaoling/vue-project-master ## Basic Information - **Project Name**: vue-project-master - **Description**: vue-elementUI本项目的定位是后台管理系统,已经完成模块有用户管理、菜单管理、角色管理、公司管理、权限管理、支付配置,新增3d饼图展示,流媒体播放,百度地图上标点、绘制多边形、添加覆盖物、移除覆盖物、测距、切换地图类型、判断点是否在绘制区域内,利用象形图绘制仿真3d柱状图和自定义图形绘制仿真3d柱形图 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 1 - **Created**: 2024-05-15 - **Last Updated**: 2025-10-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: Vue, JavaScript, HTML, CSS, Sass ## README # vue搭建后台管理界面模版(PC端) ------------------------ #### 技术栈 vue2 + vuex + vue-router + webpack + ES6/7 + axios + elementUI + 阿里图标iconfont #### 说明 > 本项目主要用于熟悉如何用 vue2 架构一个后端管理平台项目 > 为了方便后期修改使用,模拟数据在页面中,具体修改看下面【强调】 > 如果对您有帮助,您可以点右上角 "Star" 支持一下 谢谢! ^_^ > 或者您可以 "follow" 一下,我会不断开源更多的有趣的项目 > 开发环境 w7 Chrome 61 > 如有问题请直接在 Issues 中提,或者您发现问题并有非常好的解决方案,欢迎 PR 👍 #### 环境配置 ```bash "vue": "^2.5.2", "node": "14.x.x" ``` #### 目录结构 ------------------------ ```bash ├── /build/ # 项目构建(webpack)相关配置 ├── /config/ # 项目开发环境配置 ├── /src/ # 源码目录 │ ├── /api/ # 请求 │ ├── /assets/ # 组件静态资源(图片) │ ├── /components/ # 公共组件 | ├── /api/ # 请求接口 │ ├── /router/ # 路由配置 │ ├── /vuex/ # vuex状态管理 │ ├── /views/ # 路由组件(页面维度) │ ├── /config/ # 接口配置文件(请求地址) │ ├── App.vue # 组件入口 │ └── main.js # 程序入口 ├── /static/ # 非组件静态资源 ├── .babelrc # ES6语法编译配置 ├── .editorconfig # 定义代码格式 ├── .eslintignore # ES6规范忽略文件 ├── .eslintrc.js # ES6语法规范配置 ├── .gitignore # git忽略文件 ├── index.html # 页面入口 ├── package.json # 项目依赖 └── README.md # 项目文档 ``` #### 强调 项目请求已经改为假数据,例如: ``` bash // 模拟数据开始 let res = { code: 0, msg: null, count: 12, data: [ { addUser: '1', editUser: '1', addTime: null, editTime: 1527411068000, userId: 1, systemNo: 'pmd', userName: 'root', userPassword: 'e10adc3949ba59abbe56e057f20f883e', userRealName: '超级管理员', userSex: '女', userMobile: '138123456789', userEmail: '111@qq.com', isLock: 'N', deptId: 1, deptName: 'xxxx', roleId: 1 } ] } this.loading = false this.userData = res.data // 分页赋值 this.pageparm.currentPage = this.formInline.page this.pageparm.pageSize = this.formInline.limit this.pageparm.total = res.count // 模拟数据结束 /*** * 调用接口,注释上面模拟数据 取消下面注释 */ // 获取用户列表 // userList(parameter).then(res => { // this.loading = false // if (res.success == false) { // this.$message({ // type: 'info', // message: res.msg // }) // } else { // this.userData = res.data // // 分页赋值 // this.pageparm.currentPage = this.formInline.page // this.pageparm.pageSize = this.formInline.limit // this.pageparm.total = res.count // } // }) ``` 把模拟数据开始到结束注释掉,下面解除注释即可, 接口地址需要修改config/index.js文件 dev ``` bash proxyTable: { '/api': { target: 'http://xxx.xxx.xxx.xxx:xxx', // 你请求的第三方接口 changeOrigin: true, // 在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题 pathRewrite: { // 路径重写, '^/api': '/api' // 替换target中的请求地址,也就是说以后你在请求http://api.jisuapi.com/XXXXX这个地址的时候直接写成/api即可。 } } }, ``` #### 完成功能 - [x] 登录 -- 完成 - [x] 路由拦截 -- 完成 - [x] 商品管理(增加、编辑、搜索、删除) -- 完成 - [x] 角色管理(增加、编辑、搜索、删除、权限管理) -- 完成 - [x] 交易订单(增加、编辑、搜索、删除) -- 完成 - [x] 用户管理(增加、编辑、搜索、删除、数据权限、刷新缓存) -- 完成 - [x] 支付配置(增加、编辑、搜索、删除) -- 完成 - [x] 系统环境变量(增加、编辑、搜索、删除) -- 完成 - [x] 权限管理(增加、编辑、搜索、删除、配置权限) -- 完成 - [x] 菜单管理(增加、编辑、搜索、删除) -- 完成 - [x] 公司管理(增加、编辑、搜索、删除) -- 完成 ##### 新加功能 - [x] 百度地图绘制多边形区域,判断点是否在区域内并标出该点;切换地图类型;测距;在地图上添加覆盖物和移除覆盖物。注意:项目中的百度地图的key不可商用,否则后果自负,如有需求请自己到百度地图官网申请key来替换项目中的key。 - [x] 绘制3d饼图 - [x] 在浏览器上添加流媒体的播放,目前已支持WebRTC、FLV、WS_FLV、HLS格式播放,rtmp和rtsp暂不支持 - [x] 绘制平面仿真3d柱状图。其原理1利用象形图,通过图形的堆积、位置的偏移、颜色的渐变,来达到仿真3d效果,其中弊端就是中间柱体不能实现两个面的自定义颜色渐变;其原理2利用自定义图形custom,通过绘制矩形面拼接成柱形图,好处是各个面都可以自定义渐变。多主体的位置偏移原理:假设主体宽度是40, ``` bash 当只有一个柱形图时,偏移位置为[0]; 当有两个柱形图时,偏移位置[-20,20]; 当有三个柱形图时,偏移位置[-40,0,40]; 当有四个柱形图时,偏移位置[-60,-20,20,60]; 当有五个柱形图时,偏移位置[-80,40,0,40,80]; 当有六个柱形图时,偏移位置[-100,-60,-20,20,60,100]; 当有七个柱形图时,偏移位置[-120,-80,-40,0,40,80,120]; 当有八个柱形图时,偏移位置[-140,-100,-60,-20,20,60,100,140]; ...... 这时候你应该找到规律了吧~![alt text](1F2E627A.png)偏移规律代码我会贴出来 ``` - [x] fetch请求模拟GPT-ai请求返回数据,实现打字效果,代码封装将在下面展示,使用highlight.js实现markdown显示数据。 #### 柱形图位置偏移规律代码 ``` bash // 对称数据 calc(group) { const len = Math.floor(group / 2), gap = 40; const result = []; let index = 0; if (group % 2 == 0) { let start = -20; for (let i = len; i >= 1; i--) { result[index++] = start + gap * -(i - 1); } start = 20; for (let i = 1; i <= len; i++) { result[index++] = start + gap * (i - 1); } } else { let start = 0; for (let i = len; i >= 1; i--) { result[index++] = start + gap * -i; } result[index++] = 0; start = 0; for (let i = 1; i <= len; i++) { result[index++] = start + gap * i; } } // console.log('对等数据', result) return result } ``` #### 封装fetch模拟GPT-ai请求返回数据代码 ```bash // chat-ai请求封装 async chatCompletionsstream(url, body){ // this.htmlStr 是用来请求后拼接的字符串 const bodystr = JSON.stringify(body); // console.log("%s\n%s\n%s", "*".repeat(100), bodystr, "*".repeat(100)); // 想在fetch请求发送前终止它,可以使用AbortController接口。这个接口允许你创建一个信号(signal),你可以将这个信号传递给fetch请求,然后在任何时候通过调用abortController.abort()来触发信号,从而终止请求。 // 当你调用controller.abort()方法时,如果fetch请求还没有完成,它会立即被终止,并且对应的Promise会被拒绝,你可以通过捕获Promise的catch方法来处理这种情况。 // 定义一个全局controllerList是用来装controller容器,因为每次请求一个就会实例新的一个controller if (controllerList.length > 0) { // 每次生成前终止上一个请求 console.log('controllerList', controllerList) // controllerList.shift() 删除前面的对象永远留最后一条 controllerList.shift().abort() } // 创建一个新的AbortController let controller = new AbortController(); const signal = controller.signal; controllerList.push(controller) let response = null try{ console.log(111) response = await fetch(url, { method: "POST", headers: { 'Content-Type': 'application/json' }, body: bodystr, signal }) // console.log(response.status, response.statusText); if (response.status !== 200) { const text = await response.text(); this.htmlStr = '' throw text; } const textDecoder = new TextDecoder("utf-8"); const reader = response.body.getReader(); do { const { done, value } = await reader.read(); const message = textDecoder.decode(value); // console.log('do-while', message) if (message.startsWith('event: data')) { let matchers = message.match(/data: (.*)/g); // 可能多条event: data 一起返回 // console.log('process', process, process.stdout) try { if (matchers) { for (let matcher of matchers) { // process.stdout.write(eval(matcher));//node控制台输出 // console.log('matcher', eval(matcher)) this.htmlStr += eval(matcher) } } } catch (e) { // process.stdout.write(message);//node控制台输出 console.log('catch-message', message) } } else if (message.startsWith('event: end')) { } if (done) { break; } }while (true); }catch(err){ console.log(222, 'request abort is not network', err) controller = null this.htmlStr = '' }finally{ // 请求完之后将controller置为空 controller = null console.log(333) } }, ``` #### 部分截图 ------------------------ 商品管理 ![商品管理](./static/商品管理.png "商品管理") 角色管理 ![角色管理](./static/角色管理.png "角色管理") 交易订单 ![交易订单](./static/交易订单.png "交易订单") 编辑 ![编辑](./static/编辑.png "编辑") 用户管理 ![用户管理](./static/用户管理.png "用户管理") 支付配置 ![支付配置](./static/支付配置.png "支付配置") 展开与压缩 ![展开与压缩](./static/展开与压缩.png "展开与压缩") ##### 新加截图 百度地图绘制多边形区域并判断点是否在区域内 ![百度地图绘制多边形区域并判断点是否在区域内](./static/百度地图绘制多边形区域并判断点是否在区域内.png "百度地图绘制多边形区域并判断点是否在区域内") 3d饼图 ![3d饼图](./static/3d饼图.png "3d饼图") 流媒体 ![流媒体](./static/流媒体.png "流媒体") 象形图-3d柱形图 ![象形图-3d柱形图](./static/象形图-3d柱形图.png "象形图-3d柱形图") 象形图-3d柱形图2 ![象形图-3d柱形图2](./static/象形图-3d柱形图2.png "象形图-3d柱形图2") 自定义3d柱形图 ![自定义3d柱形图](./static/自定义3d柱形图.png "自定义3d柱形图") gpt-ai请求返回数据 ![gpt-ai请求返回数据](./static/gpt-ai.gif "gpt-ai请求返回数据") #### 运行项目 ------------------------ ``` bash # install dependencies npm install # serve with hot reload at localhost:8080 npm run dev # build for production with minification npm run build # build for production and view the bundle analyzer report npm run build --report # run unit tests npm run unit # run e2e tests npm run e2e # run all tests npm test ``` #### markdown-it + highlight.js简易实现 ``` bash ![参考地址](https://www.cnblogs.com/wtfPro/p/11282887.html) ``` #### css动画库 ```bash # 1,Animate.css只需在想要设置动画的元素中包含类名 文档地址:https://animate.style/ ![Animate.css动画](./static/Animate.css.gif "Animate.css动画") # 2,Animista一个CSS动画平台,Animista上可用的动画类型与animate.css上提供的动画类型非常相似,但是,如果深入研究,你会发现Animista提供了更多有用的动画类别,特别是在动画文字和背景元素方面。而且,在你准备导出动画代码时,还可以选择标准下载或压缩代码。无需下载任何软件包,也无需在网站中包含任何CDN链接,即可使用Animista:只需访问主页,选择喜欢的动画,根据需要自定义动画序列,就会立即产生代码。 官方地址:https://animista.net/ ![animista动画](./static/animista动画.gif "animista动画") # 3,Animation library,你可以把Animation library当作是Animate.css的替代方案,因为它们提供类似的动画类别。但是,与Animate.css不同点在于,Animation library不提供允许设置首选动画持续时间、速度和计时的其他自定义选项. 文档地址:https://animation.kaustubhmenon.com/ ![Animation_library动画](./static/Animation_library.gif "Animation_library动画") # 4,Magic CSS也是一个很有趣的动画库,与之前介绍的动画库相比,它提供的的动画更具吸引力。软件包提供的动画对于页面过渡非常方便。但是,magic CSS的一个缺点是它不支持Opera迷你浏览器。 文档地址:https://www.minimamente.com/project/magic/ ![magic动画](./static/magic.gif "magic动画") # 5,lightGallery,lightGallery与我们之前提到的其他动画库不同,它是专门为制作焦点图动画而设计的。焦点图动画(如上图所示)是单击时以模态形式覆盖当前网站的图像。lightGallery是一个多功能库,因为它支持视频文件,允许你以轮播格式渲染媒体资源,允许你创建自定义插件来扩展或修改功能。同样值得注意的是,lightGallery并不完全是一个纯粹的CSS动画库,它的功能依赖于JavaScript。 文档地址:https://www.lightgalleryjs.com/ v1.x地址:https://sachinchoolur.github.io/lightgallery.js/ ![lightgallery.js预览图片](./static/lightgallery.js.jpg "lightgallery.js预览图片") # 6,Loaders.css 是一个性能出色的 web 前端代码库,或者叫 CSS 库,因为它完全没有用到一行 js 代码或者图片,仅仅利用纯 CSS 就实现多种样式的 loading 动画,运行流畅丝滑,轻量小巧,性能优秀。 官网:https://connoratherton.com/loaders ![Loaders.css的loading动画](./static/Loaders.css的loading动画.gif "Loaders.css的loading动画") # 7,跟Loaders.css有异曲同工之妙的css-loaders,动画效果更多 官网:https://css-loaders.com/ ![css-loaders动画](./static/css-loaders.gif "css-loaders动画") # 8,uiverse.io利用div和css制作各种效果图动画 官网:https://uiverse.io/ ![uiverse.io效果图动画](./static/uiverse.io.jpg "uiverse.io效果图动画") ``` #### 注意在使用lightgallery.js时要根据自己的项目是v2还是v3,v2的项目配置如下,v3请去官网看。 ```bash # 安装 npm install lightgallery.js # 引用 // vue2版本 import 'lightgallery.js'; import 'lightgallery.js/dist/css/lightgallery.css'; // lightgallery plugins import '@/assets/js/lg-autoplay.min.js' import '@/assets/js/lg-fullscreen.min.js' import '@/assets/js/lg-hash.min.js' import '@/assets/js/lg-pager.min.js' import '@/assets/js/lg-rotate.min.js' import '@/assets/js/lg-share.min.js' import '@/assets/js/lg-thumbnail.min.js' import '@/assets/js/lg-video.min.js' import '@/assets/js/lg-zoom.min.js' # 方法 const el = document.getElementById('lightgallery') window.lightGallery(el,{}) ```