一、基于前后端配合
这里主要是用后台提供的接口
1.导入(excel)
思路:确认导入 执行方法importFile 调用后台接口
// 车型导入数据
const ImportCarcate = function (data) {
return axios({
method: 'post',
url: `/lzkc/manager/car/typeNos/batch`,
data: data
})
}
// 导入
importFile() {
console.log(this.uploadLoading);
if (this.uploadLoading) { // 是false 初始值 则不继续执行
return;
}
this.uploadLoading = true; // 设置为true 开始执行
this.importInterface(this.dataList) // 传递数据
.then((res) => {
this.uploadLoading = false; // 设置为false
if (res.resultStatus) {
this.step = 3;
this.successNum = res.resultData.successNum;
this.failNum = res.resultData.errorNum;
this.key = res.resultData.errorExcelUrl;
}
})
.catch((err) => {
console.error(err);
this.uploadLoading = false;
});
},
2.导入(批量上传图片)
思路:和导入 同理↑
3.导出(excel)
调用接口,传递参数
//导出
exportFile() {
this.loading = true;
GStoreexport().then((res) => {
const blob = new Blob([res]);
const fileName = "门店列表.xlsx"; // 设置下载的文件名
const elink = document.createElement("a"); // 创建a标签
elink.download = fileName; // 指定a标签的下载名
elink.style.display = "none"; // 隐藏a标签
elink.href = URL.createObjectURL(blob); // 解析 blob格式地址 赋值给a标签
document.body.appendChild(elink); // 添加到页面中
elink.click(); // 实现点击下载
URL.revokeObjectURL(elink.href); // 清除a标签的地址
this.loading = false;
this.$message.success("导出成功");
});
},
// 导出接口
const GStoreexport = function (params) {
return axios({
method: 'get',
responseType: 'blob',
url: '/lzkc/manager/stores/export',
params: params
})
}
二、前端基于插件
README.md:
## 后台管理系统
某个个后台管理系统,包含商品管理 用户管理 订单等等信息。
前端开发内容:
PC端(比如:京东) 移动端(手机预览的网页) 小程序 后台管理界面
后台开发:
服务器: 后台语言 java、 php、 python 、大数据、人工智能
架构师: --- 技术总监
前后端分离:
用户 --- >前端-视图-数据---->后台-提供接口 ---> 数据库
## 技术点
Vue + Vue-router + Vuex + Element-ui + Axios + Echarts + 其他三方库
## 项目搭建
1. vue create vue-ego
2. vue-router vuex
3. axios
4. vue add element --(按需)
## 项目初始化
1. 删除无用的组件 home.vue about.vue hello...
2. css初始化
3. incofont 图标导入
## 后台服务
1. node.js服务
2. express
3. jwt(生成token)jsonwebtoken 解析token: 安装: jwt-decode
4. mysql
5. mockjs -- 模拟数据
1. 安装: cnpm i mockjs -S
2. 引入:
node.js: const Mock = require('mockjs')
前端js: import Mock from 'mockjs'
3. 语法:
Mock.mock()
## 路由大配置
1. 页码布局配置 同级登录界面
## 商品管理界面
### 类目选择
### 上传图片
1. upload 图片上传
2. 后台配置
1. 后台安装 multer 模块 同时引入fs模块
2. router.js入口文件导入模块
const fs=require('fs')
const multer=require('multer')
3. 上传图片 配置upload
### 富文本编辑
1. 百度编译器
2. wangEditor
wangEditor使用步骤:
1. 官网网址:https://www.wangeditor.com/doc/
2. 基本使用
1. 安装:npm i wangeditor --save
2. 引入模块:
import E from "wangeditor"
3. 使用wangeditor
const editor = new E("#div1")
editor.create()
3. 常用配置
1. 清空内容
editor.txt.clear() 清空编辑器内容。
2. 设置内容
editor.txt.html('') 获取 html
3. 配置菜单
1. 配置菜单使用 editor.config.menus 定义显示哪些菜单和菜单的顺序
4. 配置 onchange 回调函数
配置 onchange 函数之后,用户操作(鼠标点击、键盘打字等)导致的内容变化之后,会自动触发 onchange 函数执行
## 国际化
### vuei8n
1. 介绍:
Vue I18n 是 Vue.js 的国际化插件。它可以轻松地将一些本地化功能集成到你的 Vue.js 应用程序中。
2. 安装
1. npm install vue-i18n
2. main.js导入或者是单独的文件
import Vue from 'vue'
import VueI18n from 'vue-i18n'
Vue.use(VueI18n)
3. 使用步骤
1. 如果使用模块系统 (例如通过 vue-cli),则需要导入 Vue 和 VueI18n ,然后调用 Vue.use(VueI18n)。
// import Vue from 'vue'
// import VueI18n from 'vue-i18n'
//
// Vue.use(VueI18n)
2. 准备翻译的语言环境信息
const messages = {
en: {//英文
home: {
hello: 'hello world',
xx:xx,
...
},
goods:{
}
},
zh: {//中文
home: {
hello: '你好 世界',
xx:xx,
...
},
goods:{
}
}
}
3. 通过选项创建 VueI18n 实例
const i18n = new VueI18n({
locale: 'en', // 设置地区
messages, // 设置地区信息
})
4. 通过 `i18n` 选项创建 Vue 实例
new Vue({ i18n }).$mount('#app')
5. 使用语法:
<p>{{ $t("home.hello") }}</p>
### element 国际化
1. 导入
import Element from 'element-ui'
2. 导入语言环境
import enLocale from 'element-ui/lib/locale/lang/en'
import zhLocale from 'element-ui/lib/locale/lang/zh-CN'
目前 Element 内置了以下语言:
简体中文(zh-CN)
英语(en)
德语(de)
葡萄牙语(pt)
西班牙语(es)
丹麦语(da)
法语(fr)
...
3. 配置语言环境
const messages = {
en: {
message: 'hello',
...enLocale // 或者用 Object.assign({ message: 'hello' }, enLocale)
},
zh: {
message: '你好',
...zhLocale // 或者用 Object.assign({ message: '你好' }, zhLocale)
}
}
4. 配置使用
Vue.use(Element, {
i18n: (key, value) => i18n.t(key, value)
})
## 登录--路由拦截
## echarts
1. 安装:npm install echarts -S
2. 使用方式
1. 导入echarts在组件内使用
2. 导入全局 挂载原型上 全局使用
3. 开发成vue插件
3. 使用 -main.js
1. import * as echarts from 'echarts'
Vue.prototype.$echarts = echarts;
2. 直接使用
this.$echarts.xxx
## 规格参数
## 订单列表
## vue-PDF
参考:gitHub: https://github.com/FranckFreiburger/vue-pdf
步骤:
1. npm install --save vue-pdf
2. import pdf from 'vue-pdf'
3. components: {
pdf
}
4. <pdf src="./static/relativity.pdf"></pdf>
问题:
pdf打印的时候 看到视图 乱码的中文
vue-pdf网址:https://github.com/FranckFreiburger/vue-pdf/pull/130/commits/253f6186ff0676abf9277786087dda8d95dd8ea7
## vue-tour
1. npm i vue-tour
2. 使用
import Vue from 'vue'
import App from './App.vue'
import VueTour from 'vue-tour'
require('vue-tour/dist/vue-tour.css')
Vue.use(VueTour)
new Vue({
render: h => h(App)
}).$mount('#app')
1.导出为pdf
插件:vue-pdf
github地址:https://github.com/FranckFreiburger/vue-pdf
npm地址:vue-pdf - npm
解决pdf文件位置:vue中本地pdf文件加载错误,文件不显示_生活的小欢呼的博客-CSDN博客_vue-pdf 不显示
解决pdf乱码:
Fix fonts issue in printing by arioth · Pull Request #130 · FranckFreiburger/vue-pdf · GitHub
1.下载
npm install vue-pdf
2.import 引入, 使用组件注册,并使用
<template> <pdf src="./path/to/static/relativity.pdf"></pdf> </template> <script> import pdf from 'vue-pdf' export default { components: { pdf } }</script>
3.代码写法:
<template>
<el-dialog title="合同内容" :visible.sync="dialogVisible" width="50%">
<!--
属性:
:src='' 文件的路径
:page 显示的页码
:rotate 旋转90的倍数
event:
@num-pages="pageCount = $event" 获取总页码
@page-loaded="currentPage = $event" 获取当前的页码
methods:
print() 打印
-->
<pdf src="./sxt.pdf"></pdf>
<hr />
<!-- <el-button @click="num--">上一页</el-button>
<el-button @click="num++">下一页</el-button> -->
<hr />
<!-- 写法一: -->
<!-- <p>{{ currentPage }} / {{ pageCount }}</p>
<el-button @click="print">打印合同</el-button>
<pdf src="./sxt.pdf" ref='mypdf' :page="num" @num-pages="pageCount = $event"
@page-loaded="currentPage = $event" style="display: inline-block; width: 400px"></pdf> -->
<!-- 写法二:展示所有的pdf文件 -->
<!-- <pdf
v-for="i in numPages"
:key="i"
:src="src"
:page="i"
style="display: inline-block; width: 25%"
></pdf> -->
<!-- <span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogVisible = false">确 定</el-button>
</span> -->
</el-dialog>
</template>
<script>
//1. 安装pdf : npm i vue-pdf -S
//2. 导入pdf 3. 使用组件
import pdf from "vue-pdf";
//获取pdf文件
// const source = pdf.createLoadingTask("./sxt.pdf");
export default {
components: {
pdf,
},
data() {
return {
dialogVisible: false,
num: 1,
currentPage: 0,
pageCount: 0,
numPages: undefined,
src: source,
};
},
mounted() {
// this.src.promise.then((pdf) => {
// this.numPages = pdf.numPages;
// });
},
methods: {
//打印合同
// print() {
// this.$refs.mypdf.print();
// }
}
};
</script>
<style>
</style>
2.图片下载
得到图片的base64编码
3.导出为excel
1.下载
npm install file-saver xlsx -S
npm install script-loader - D
2.在src目录下新建一个excel文件夹,存入Blob.js和Export2Excel.js文件
js文件存放位置:
https://gitee.com/wei-shuai-lei/vuetwo
3.在common文件夹里新建js文件夹再新建util.js
/***
* export2Excel(columns,list) 导出excel表格
* columns Arrary=[{},{}] 表头 =[{title:'',key:''}]
* list =[] table的数据 [{},{}]
*/
export function export2Excel(columns,list,name){
require.ensure([], () => {
const { export_json_to_excel } = require('../../excel/Export2Excel');
let tHeader = []
let filterVal = []
console.log(columns)
if(!columns){
return;
}
columns.forEach(item =>{
tHeader.push(item.title)
filterVal.push(item.key)
})
const data = list.map(v => filterVal.map(j => v[j]))
export_json_to_excel(tHeader, data,name);
})
}
4.国际化
1.vue-i18n:
通过原型上的 vuei18n.locale
1. 介绍:
Vue I18n 是 Vue.js 的国际化插件。它可以轻松地将一些本地化功能集成到你的 Vue.js 应用程序中。
2. 安装
1. npm install vue-i18n
2. main.js导入或者是单独的文件
import Vue from 'vue'
import VueI18n from 'vue-i18n'
Vue.use(VueI18n)
3. 使用步骤
1. 如果使用模块系统 (例如通过 vue-cli),则需要导入 Vue 和 VueI18n ,然后调用 Vue.use(VueI18n)。
// import Vue from 'vue'
// import VueI18n from 'vue-i18n'
//
// Vue.use(VueI18n)
2. 准备翻译的语言环境信息
const messages = {
en: {//英文
home: {
hello: 'hello world',
xx:xx,
...
},
goods:{
}
},
zh: {//中文
home: {
hello: '你好 世界',
xx:xx,
...
},
goods:{
}
}
}
3. 通过选项创建 VueI18n 实例
const i18n = new VueI18n({
locale: 'en', // 设置地区
messages, // 设置地区信息
})
4. 通过 `i18n` 选项创建 Vue 实例
new Vue({ i18n }).$mount('#app')
5. 使用语法:
<p>{{ $t("home.hello") }}</p>
2.element中的国际化
### element 国际化
1. 导入
import Element from 'element-ui'
2. 导入语言环境
import enLocale from 'element-ui/lib/locale/lang/en'
import zhLocale from 'element-ui/lib/locale/lang/zh-CN'
目前 Element 内置了以下语言:
简体中文(zh-CN)
英语(en)
德语(de)
葡萄牙语(pt)
西班牙语(es)
丹麦语(da)
法语(fr)
...
3. 配置语言环境
const messages = {
en: {
message: 'hello',
...enLocale // 或者用 Object.assign({ message: 'hello' }, enLocale)
},
zh: {
message: '你好',
...zhLocale // 或者用 Object.assign({ message: '你好' }, zhLocale)
}
}
4. 配置使用
Vue.use(Element, {
i18n: (key, value) => i18n.t(key, value)
})
5.富文本编辑
### 富文本编辑
1. 百度编译器
2. wangEditor
wangEditor使用步骤:
1. 官网网址:wangEditor
2. 基本使用
1. 安装:npm i wangeditor --save
2. 引入模块:
import E from "wangeditor"
3. 使用wangeditor
const editor = new E("#div1")
editor.create()
3. 常用配置
1. 清空内容
editor.txt.clear() 清空编辑器内容。
2. 设置内容
editor.txt.html('') 获取 html
3. 配置菜单
1. 配置菜单使用 editor.config.menus 定义显示哪些菜单和菜单的顺序
4. 配置 onchange 回调函数
配置 onchange 函数之后,用户操作(鼠标点击、键盘打字等)导致的内容变化之后,会自动触发 onchange 函数执行
6. a标签下载
<a href="https://img9.51tietu.net/pic/20190918/p0iwg2kzx13p0iwg2kzx13.jpg" download="123456.jpg">下载图片</a>
a标签主要是用download这个属性去下载的,download指定下载的文件名,href为下载路径
- download 有跨域的问题,非同源会相当于导航
- 再服务端设置
Content-Disposition ,使用 http 响应头 Content-Disposition Content-Disposition
先下载源数据文件,生成blog对象,再使用 URL.creatObjectURL() 创建一个非跨域的数据源 然后再页面写入a标签支持下载
这里使用element UI里提供的上传, 再上传成功拿到file (再file.raw 中) 转换成非跨域的数据源 <el-upload class="avatar-uploader" action="http://localhost:8888/upload" :show-file-list="false" :on-success="handleAvatarSuccess" name="file" > <img v-if="imageUrl" :src="imageUrl" class="avatar" /> <i v-else class="el-icon-plus avatar-uploader-icon"></i> </el-upload> handleAvatarSuccess(res, file) { console.log(res); console.log(file); console.log(URL.createObjectURL(file.raw)); this.imageUrl = URL.createObjectURL(file.raw); },
7. URL.createObjectURL、Blob 实现保存文件
- 生成blob对象再使用 URL.createobjectURL() 创建一个非跨域的数据源,然后在页面写入a标签支持下载
- Blob 表示二进制类型的大对象。通常是影像、声音或多媒体文件
- 通过URL.createobjectURL(blobVal),获取要保存的文件的一个URL,这个ur1带hash,保存在内存中
- 用URL.revokeObjectURL()来释放这个object URL,通知浏览器可以不必继续引用这个文件了
后台:
// 上传视频 app.post('/uploadVideo', upload.single('file'), (req, res) => { if (req.file) { // console.log("上传成功"); res.send({ message: '上传成功啦' }) } else { console.log("失败...."); res.send("失败了.....") } })
前台:
这里使用element ui的上传 ,上传成功后,点击按钮下载视频
<el-upload class="avatar-uploader" action="http://localhost:8888/uploadVideo" :show-file-list="false" :on-success="videosSuccess" name="file" > <video v-if="videoUrl" :src="videoUrl" :autoplay="videoUrl ? true : false" controls :crossorigin="false" /> <i v-else class="el-icon-plus avatar-uploader-icon"></i> </el-upload> <button v-if="videoUrl" id="btn" @click="btnClick">下载视频</button> // ------------------------------------------------------------------ videosSuccess(res, file) { console.log(res); console.log(file); console.log(URL.createObjectURL(file.raw)); this.videoUrl = URL.createObjectURL(file.raw); }, btnClick() { if (this.videoUrl) { // 创建a标签 const a = document.createElement("a"); // 设置 下载地址 和文件名 并隐藏 a.href = this.videoUrl; a.download = "宣传视频.mp4"; a.style.display = "none"; // 添加到body document.body.appendChild(a); // 点击下载 a.click(); // 清除URL URL.revokeObjectURL(this.videoUrl); // 删除a标签 document.body.removeChild(a); } else { this.$message.error("要下载的视频有问题, 请找管理员"); } },
8.file、Blob、FormData
- File对象的初始化 (new File )
- 第一个参数是一个字符串数组,你可以理解为就是文件内容
- 第二个参数就是文件名字符串。
- new File(["First Line Text","Second Line Text"],FileName);
- repeat(n) 返回一个新字符串,表示将原字符串重复n次
- abc'.repeat(10)
- File继承了所有Blob的属性
- File对象可以看作一种特殊的Blob对象,
- oldBlob.slice([start [, end [, contentType]]])
- blob 对象可以通过 .slice() 得到一个新的 blob对象
- FormData为序列化表单
- let data = new FormData();
- data . append("key","alue")
- 把data作为传给服务器的数据
- 测试接口网站, https://httpbin.org/
- 实际工作中加入id 和 计数
// 创建 file对象 file: new File(["aaabbbccc"], "test"), // 分片大小 size: 3, // 上传地址 url: "https://httpbin.org/post", ---------------------------------------------------------------- // 分片上传 async fileSize() { for (let i = 0; i < this.file.size; i += this.size) { const chunk = this.file.slice(i, i + this.size); // console.log(chunk); let updata = new FormData(); updata.append("chunkData", chunk); const res = await fetch(this.url, { method: "post", body: updata }); // res.json().then(res=>console.log(res.files.chunkData)) } },