vue中使用echarts图表库、excel导出、tinymc富文本框、百度地图

0 阅读5分钟

一、echarts图表库(一个基于javascript的开源的可视化图表库)

官网:echarts.apache.org

npm i echarts@5.3.3安装

Index.vue柱状图、折线图、饼状图

<!-- eslint-disable prettier/prettier -->

<template>

    <!-- <div>主界面</div> -->

    <el-row :gutter="20">

        <el-col :span="12">

            <div id="main" style="width: 600px;height:400px;"></div>

        </el-col>

        <el-col :span="12">

            <div id="category" style="width: 600px;height:400px;"></div>

        </el-col>

    </el-row>

</template>

<!-- eslint-disable prettier/prettier -->

<script>

// * 表示导入所有,as 别名

import * as echarts from 'echarts'//全局导入

import {RequestCategoryListfrom '@/api/index.js'

export default {

    data(){

        return{

            categoryList:[]//产品分类

        }

    },

     /**

     * vue组件 生命周期函数执行规则:

     *    vue生命周期created中启动异步任务,不会等待异步任务结果,再执行mounted生命周期函数,

     *    如果要在mounted生命周期使用数据,在mounted启动异步任务,接收数据处理后续操作

     */

    // created(){

    //     this.getCategoryList()

    // },

    mounted() {

        // this.drawCategoryBar()

        this.getCategoryList()

        this.drawBar()

    },

    methods: {

        //获取产品列表

        async getCategoryList() {

            const data = await RequestCategoryList()

            const { resultCode,resultInfo } = data

            if (resultCode === 1) {

                this.categoryList =resultInfo.list

                this.drawCategoryBar()

            }

        },

        drawCategoryBar() {

            const categoryX = this.categoryList.map(item=>item.name)

            const categoryData = this.categoryList.map(item=>item.id)

            // 初始化echarts实例

            const echart = echarts.init(document.getElementById('category'));

            // 指定图表的配置项和数据

            const option ={

                title: {//标题

                    text'产品分类数量统计',

                },

                tooltip: {},

                legend: {//多个柱状图切换

                    data: ['分类'],//多个柱状图切换,要跟series里面的name对应起来

                },

 

                xAxis: {

                    data:categoryX,

                },

                yAxis: {},

                series: [

                    {

                        name'分类',

                        type'bar',//柱状图,line折线图

                        data: categoryData,

                    }

                ]

            }

            // 设置配置

            echart.setOption(option)

        },

        drawBar() {

            const echart = echarts.init(document.getElementById('main'));// 初始化echarts实例

            // 指定图表的配置项和数据

            echart.setOption({

                title: {

                    text'标题'

                },

                tooltip: {},

                legend: {

                    data: ['销量', '价格']//多个柱状图切换

                },

                xAxis: {

                    data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']

                },

                yAxis: {},

                series: [

                    {

                        name'销量',

                        type'bar',//柱状图,line折线图

                        data: [5, 20, 36, 10, 10, 20]

                    },

                    {

                        name'价格',

                        type'bar',//柱状图,line折线图

                        data: [10, 9.9, 36, 10, 10, 20]

                    }

                ]

            });

        }

    }

}

</script>

<!-- eslint-disable prettier/prettier -->
<style lang="scss" scoped></style>

二、excel导出

安装:

npm i xlsx@0.17.0 -S

npm i file-saver@2.0.5 -S 文件处理

npm i lodash-es -S深克隆工具

utils→xlsxutil.js

/* eslint-disable prettier/prettier */
/* eslint-disable no-redeclare */

import XLSX from 'xlsx'
import fs from 'file-saver'
import { cloneDeep } from 'lodash-es'
import { ElMessagefrom 'element-plus'

const s2ab = s => {

    var buf

    if (typeof ArrayBuffer !== 'undefined') {

        buf = new ArrayBuffer(s.length)

        var view = new Uint8Array(buf)

        for (var i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xff

        return buf

    } else {

        buf = new Array(s.length)

        for (var i = 0; i !== s.length; ++i) buf[i] = s.charCodeAt(i) & 0xff

        return buf

    }

}

 

// 自动分析dom元素导出excel

export function excelExport(table, filename) {

    // workbook,

    const wb = XLSX.utils.table_to_book(table)

    /* Export to file (start a download) */

    const defaultCellStyle = {

        font: { name'Verdana', sz13, color'FF00FF88' },

        fill: { fgColor: { rgb'FFFFAA00' } },

    }

    const wopts = {

        bookType'xlsx',

        bookSSTfalse,

        type'binary',

        cellStyletrue,

        defaultCellStyle: defaultCellStyle,

        showGridLinesfalse,

    }

    const wbout = XLSX.write(wb, wopts)

    const blob = new Blob([s2ab(wbout)], { type'application/octet-stream' })

    fs.saveAs(blob, filename + '.xlsx')

}

// 使用数据导出excel

export function excelExport2(data, headers, filename) {

    const json = cloneDeep(data)

    json.forEach(item => {

        for (let key in item) {

            // eslint-disable-next-line no-prototype-builtins

            if (headers.hasOwnProperty(key)) {

                item[headers[key]] = item[key]

            }

            delete item[key]

        }

    })

    // excel 对象

    const wb = XLSX.utils.book_new()

    const ws = XLSX.utils.json_to_sheet(json, {

        headerObject.values(headers),

    })

    wb.SheetNames.push(filename)

    wb.Sheets[filename] = ws

    const defaultCellStyle = {

        font: { name'Verdana', sz13, color'FF00FF88' },

        fill: { fgColor: { rgb'FFFFAA00' } },

    }

    const wopts = {

        bookType'xlsx',

        bookSSTfalse,

        type'binary',

        cellStyletrue,

        defaultCellStyle: defaultCellStyle,

        showGridLinesfalse,

    }

    const wbout = XLSX.write(wb, wopts)

    const blob = new Blob([s2ab(wbout)], { type'application/octet-stream' })

    fs.saveAs(blob, filename + '.xlsx')

}

// excel导入

export function excelImport(file, output) {

    const type = file.name.split('.')[1]

    const fileType = ['xlsx', 'xlc', 'xlm', 'xls', 'xlt'].some(

        item => item === type

    )

    if (!fileType) {

        ElMessage.error('格式错误!请重新选择')

        return

    }

    const reader = new FileReader(file)

    reader.readAsArrayBuffer(file, 'utf-8')

    reader.onloadend = function (e) {

        const data = e.target.result

        /* Parse file */

        // workbook

        const wb = XLSX.read(data, {

            type'buffer',

        })

        // worksheet

        const ws = wb.Sheets[wb.SheetNames[0]]

        const htmlstr = XLSX.utils.sheet_to_html(ws)

        /* Generate HTML */

        output.innerHTML = htmlstr

    }

}

list.vue


<!-- eslint-disable prettier/prettier -->

<template>

    <div> 

         <!-- 搜索 -->

        <el-row :gutter="20" style="margin-bottom: 10px">

            <el-col :span="4" :offset="0">

                <el-input v-model="product.name" placeholder="名称搜索" clearable></el-input>

            </el-col>

            <el-col :span="4" :offset="0">

                <el-input v-model="product.shop" placeholder="店铺名称搜索" clearable></el-input>

            </el-col>

            <el-col :span="4" :offset="0">

                <el-input v-model="product.startPrice" placeholder="开始价格搜索" clearable></el-input>

            </el-col>

            <el-col :span="4" :offset="0">

                <el-input v-model="product.endPrice" placeholder="结束价格搜索" clearable></el-input>

            </el-col>

            <el-col :span="4" :offset="0">

                <el-button type="primary" @click="bindSearch">搜索产品</el-button>

            </el-col>

        </el-row>

 

        <el-button-group>

            <el-button type="success" size="small" @click="bindAddGood">添加</el-button>

            <el-button type="success" size="small" @click="bindRefresh">刷新</el-button>

            <el-button type="success" size="small" @click="bindBatchDelete">批量删除</el-button>

            <el-button type="success" size="small" @click="bindExcelExport">导出excel</el-button>

        </el-button-group>

        <!-- 表格 -->

        <el-table :data="goodsList" style="width: 100%" @selection-change="handleSelectionChange">

            <el-table-column type="selection" ></el-table-column>

            <el-table-column label="序列号" prop="id" width="100"></el-table-column>

            <el-table-column label="名称" prop="product"></el-table-column>

            <el-table-column label="店铺名称" prop="shop"></el-table-column>

            <el-table-column label="图片">

                <template #default="scope">

                    <!-- <el-image

                        :src="scope.row.picture?.indexOf('http') === -1 ? 'http://10.7.163.142:8089/' + scope.row.picture : scope.row.picture"

                        style="width: 100px; height: 100px"></el-image> -->

                    <el-image :src="filterUrl(scope.row.picture)" style="width: 100px; height: 100px"></el-image>

                </template>

            </el-table-column>

            <el-table-column label="价格" prop="price"></el-table-column>

            <el-table-column label="类型" prop="categoryname"></el-table-column>

            <el-table-column label="操作">

                <template #default="scope">

                    <el-button type="success" size="small" @click="bindEdit(scope.row)">编辑</el-button>

                    <!-- <el-button type="primary" size="small" @click="bindDelete(scope.row.id)">删除</el-button> -->

                    <el-popconfirm title="确认要删除此记录吗?" @confirm="bindDelete(scope.row.id)" confirm-button-text="Yes"

                        cancel-button-text="No">

                        <template #reference>

                            <el-button type="primary" size="small">删除</el-button>

                        </template>

                    </el-popconfirm>

                </template>

            </el-table-column>

        </el-table>

        <!-- 分页 -->

        <el-pagination background layout="total, sizes, prev, pager, next,jumper" :total="total"

            :page-sizes="[5, 10, 20]" @size-change="handleSizeChange" @current-change="handleCurrentChange" />

        <!-- total-总记录条数

        sizes-选择每页几条

        :page-sizes="[5,10,20]"

        jumper-跳转

        @size-change="handleSizeChange"//page-size 改变时触发

         -->

        <!-- 弹出对话框 -->

        <el-dialog :title="type === 'ADD' ? '添加产品' : '编辑产品'" v-model="dialogGoodsFormVisible" width="40%">

            <GoodsDialog v-if="dialogGoodsFormVisible" @close="bindClose" :goods="goods" :type="type"></GoodsDialog>

        </el-dialog>

    </div>

</template>

<!-- eslint-disable prettier/prettier -->

<script>

import { RequestShopList, RequestDeleteGoods, RequestBatchDeletefrom '@/api/index.js'

import GoodsDialog from '@/components/GoodsDialog.vue'

import { ElMessagefrom 'element-plus'

import { excelExport2 } from '@/utils/xlsxutil.js'

export default {

    components: {

        GoodsDialog,

    },

    data() {

        return {

            // tableData: [

            //     { id:1,name: '回锅肉', price: 30, category: '荤', url: 'https://image5.suning.cn/uimg/b2c/newcatentries/0000000000-000000000834870991_1_800x800.jpg' },

            //     { id:2,name: '土豆丝', price: 20, category: '素', url: 'https://image5.suning.cn/uimg/b2c/newcatentries/0000000000-000000000834870991_1_800x800.jpg' },

            // ]

            goodsList: [],

            dialogGoodsFormVisiblefalse,

            total'',//总记录条数

            pageSize5,//每页记录条数

            pageNo1,//当前页号

            type'ADD',//EDIT 编辑 ADD 添加

            goodsnull,

            product: {

                name'',//搜索产品名称

                shop'',//搜索店铺名称

                price'',//搜索价格

                startPrice'',

                endPrice'',

            },

            ids'',//删除商品id集合

        }

    },

    created() {

        this.getShopList()

    },

    methods: {

        filterUrl(url) {

            return url?.indexOf('http') === -1 ? 'http://10.7.163.142:8089/' + url : url

        },

        /**

         * 产品列表

         */

        async getShopList() {

            const data = await RequestShopList(this.pageSize, this.pageNo, this.product.name, this.product.shop, this.product.startPrice, this.product.endPrice)

            const { resultCode, resultInfo } = data

            if (resultCode === 1) {

                this.goodsList = resultInfo.list

                this.total = resultInfo.total// 总记录条数

            }

        },

        /**

         * 编辑产品

         */

        async bindEdit(row) {

            // console.log('row ', row)

            this.goods = row

            this.type'EDIT'

            this.dialogGoodsFormVisibletrue

        },

        /**

         * 删除商品

         */

        async bindDelete(id) {

            const data = await RequestDeleteGoods(id)

            const { resultCode } = data

            if (resultCode === 1) {

                ElMessage({

                    message'删除成功',

                    type'success',

                })

                this.getShopList()

            }

        },

        /**

         * 添加-弹出添加表单对话框

         */

        bindAddGood() {

            this.type'ADD'

            this.dialogGoodsFormVisibletrue

        },

        /**

        * 页大小改变事件

        */

        handleSizeChange(value) {

            this.pageSize = value

            this.getShopList()

        },

        /**

         * 页号改变事件

         */

        handleCurrentChange(value) {

            this.pageNo = value

            this.getShopList()

        },

        /**

         * 刷新

         */

        bindRefresh() {

            this.product = {}//重置搜索数据

            this.getShopList()

        },

        bindClose() {

            this.dialogGoodsFormVisiblefalse

            this.getShopList()

        },

        /**

         * 搜索产品

         */

        bindSearch() {

            this.getShopList()

        },

        /*

        多选

         */

        handleSelectionChange(value) {

            // console.log('value ', value) // [{id:10,name:''}] => [10,12,34] => '10,12,34'

            const list = value.map(item => item.id)

            const ids = list.join(',')

            this.ids = ids

        },

        /*

        批量删除

         */

        async bindBatchDelete() {

            if (this.ids?.split(',').length <= 0) {

                ElMessage({

                    message'请选择删除产品',

                    type'info',

                })

                return

            }

            const data = await RequestBatchDelete(this.ids)

            const { resultCode } = data

            if (resultCode === 1) {

                ElMessage({

                    message'批量删除成功',

                    type'success',

                })

                this.getShopList()

            }

        },

        /**

         * 导出excel

         */

         bindExcelExport() {

            excelExport2(

                this.goodsList,

                {

                    id'序列号',

                    product'产品名称',

                    shop'店铺名称',

                    picture'图片',

                    price'价格',

                    oldprice'原价',

                    categoryname'类型名称',

                },

                '产品列表'

            )

        },

    }

}

</script>

<!-- eslint-disable prettier/prettier -->

<style lang="scss" scoped>

</style>

三、tinymc富文本框

官网:www.tiny.cloud/docs-4x/

1.下载依赖

www.tiny.cloud/get-tiny/cu…

2.下载汉化包

htps//download.tiny.cloud/tinymce/community/anguagepacks/6/zh-Hans.zip?. _ga=2.37613731.2030153498.1660544987-1887555869.1660544987

3.拷贝到项目public目录中

image.png

4. 组件中使用

Index.html中引入tinymc

<!DOCTYPE html>
<html lang="en">

  <head>

    <meta charset="UTF-8">

    <link rel="icon" href="/favicon.ico">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Vite App</title>

  <script src="/tinymce/tinymce.min.js"></script>

  <script src="/tinymce/langs/zh-Hans.js"></script>

  </head>

  <body>

    <div id="app"></div>

    <script type="module" src="/src/main.js"></script>

  </body>

</html>

Add.vue


<!-- eslint-disable prettier/prettier -->

<template>

    <div>

        <!-- 富文本框的容器 -->

        <textarea id="default-editor"></textarea>

        <el-button type="primary" size="default" @click="bindConfirm"

            >确定</el-button

        >

    </div>

</template>

<!-- eslint-disable prettier/prettier -->

<script>

import { ElMessagefrom 'element-plus'

 

export default {

    methods: {

        bindConfirm() {

            console.log(tinymce.activeEditor.getContent())//获取内容,用v-html解析标签

            ElMessage.info('添加日志成功!')

        },

    },

    mounted() {

        this.$nextTick(() => {

            // eslint-disable-next-line no-undef

            tinymce.init({//初始化

                selector'textarea#default-editor',//容器

                brandingfalse,//取消右下角默认提示

                height600,

                plugins'advlist link image lists paste',//使用插件

                paste_data_imagestrue, //支持图片粘贴

            })

        })

    },

}

</script>

<!-- eslint-disable prettier/prettier -->

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

 

四、百度地图

1. 百度地图使用前要申请密钥(ak)才可使用(需要下载百度app)

lbsyun.baidu.com/index.php?t…

2.可以查找适合的示例直接使用lbsyun.baidu.com/index.php?t…

Index.html中引入百度地图API文件

<!DOCTYPE html>
<html lang="en">

  <head>

    <meta charset="UTF-8">

    <link rel="icon" href="/favicon.ico">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Vite App</title>

    <script type="text/javascript"

    src="https://api.map.baidu.com/api?v=1.0&type=webgl&ak=你的密钥"></script>

  </head>

  <body>

    <div id="app"></div>

    <script type="module" src="/src/main.js"></script>

  </body>

</html>

map.vue

<!-- eslint-disable prettier/prettier -->
<template>

    <!-- 创建地图容器元素 -->

    <div id="container"></div>

</template>

<!-- eslint-disable prettier/prettier -->

<script>

export default {

    mounted() {

        this.initMap()

    },

    methods: {

        initMap() {

            // 创建地图实例

            // eslint-disable-next-line no-undef

            var map = new BMapGL.Map('container')

            // 设置中心点坐标

            // eslint-disable-next-line no-undef

            var point = new BMapGL.Point(104.047736, 30.636993)

            // 地图初始化,同时设置地图展示级别

            map.centerAndZoom(point, 15)

            // eslint-disable-next-line no-undef

            var point1 = new BMapGL.Point(104.044215, 30.634507)

            // eslint-disable-next-line no-undef

            var marker = new BMapGL.Marker(point1) // 创建标注

            map.addOverlay(marker) // 将标注添加到地图中

        },

    },

}

</script>

<!-- eslint-disable prettier/prettier -->

<style lang="scss" scoped>

#container {

    height: 90%;

    width: 100%;

}

</style>