This commit is contained in:
weicw
2021-07-29 16:17:26 +08:00
commit a6eb6f83d1
127 changed files with 60792 additions and 0 deletions

View File

@@ -0,0 +1,214 @@
<template>
<div class="ele-body ele-body-card">
<a-row :gutter="16">
<a-col :lg="8" :md="24" :sm="24" :xs="24">
<a-card title="列表拖拽排序" :bordered="false">
<div class="demo-drag-list">
<draggable
v-model="list"
item-key="id"
:animation="300"
handle=".sort-handle">
<template #item="{element}">
<div class="demo-drag-list-item ele-cell">
<menu-outlined class="sort-handle"/>
<div class="ele-cell-content">{{ element.name }}</div>
</div>
</template>
</draggable>
</div>
</a-card>
</a-col>
<a-col :lg="16" :md="24" :sm="24" :xs="24">
<a-card title="列表相互拖拽" :bordered="false">
<a-row :gutter="16">
<a-col :span="12">
<div class="demo-drag-list">
<draggable
:list="list1"
item-key="id"
:animation="300"
handle=".sort-handle"
group="demoDragList">
<template #item="{element}">
<div class="demo-drag-list-item ele-cell">
<menu-outlined class="sort-handle"/>
<div class="ele-cell-content">{{ element.name }}</div>
</div>
</template>
</draggable>
</div>
</a-col>
<a-col :span="12">
<div class="demo-drag-list">
<draggable
:list="list2"
item-key="id"
:animation="300"
handle=".sort-handle"
group="demoDragList">
<template #item="{element}">
<div class="demo-drag-list-item ele-cell">
<menu-outlined class="sort-handle"/>
<div class="ele-cell-content">{{ element.name }}</div>
</div>
</template>
</draggable>
</div>
</a-col>
</a-row>
</a-card>
</a-col>
</a-row>
<a-row :gutter="16">
<a-col :lg="8" :md="24" :sm="24" :xs="24">
<a-card title="宫格拖拽排序" :bordered="false">
<div class="demo-drag-grid">
<draggable
v-model="grid"
item-key="id"
:animation="300">
<template #item="{element}">
<div class="demo-drag-grid-item">{{ element.name }}</div>
</template>
</draggable>
</div>
</a-card>
</a-col>
<a-col :lg="16" :md="24" :sm="24" :xs="24">
<a-card title="宫格相互拖拽" :bordered="false">
<a-row :gutter="16">
<a-col :span="12">
<div class="demo-drag-grid">
<draggable
:list="grid1"
item-key="id"
:animation="300"
group="demoDragGrid">
<template #item="{element}">
<div class="demo-drag-grid-item">{{ element.name }}</div>
</template>
</draggable>
</div>
</a-col>
<a-col :span="12">
<div class="demo-drag-grid">
<draggable
:list="grid2"
item-key="id"
:animation="300"
group="demoDragGrid">
<template #item="{element}">
<div class="demo-drag-grid-item">{{ element.name }}</div>
</template>
</draggable>
</div>
</a-col>
</a-row>
</a-card>
</a-col>
</a-row>
</div>
</template>
<script>
import draggable from 'vuedraggable';
import {MenuOutlined} from '@ant-design/icons-vue';
export default {
name: 'ExtensionDragSort',
components: {
draggable,
MenuOutlined
},
data() {
return {
list: [
{id: 1, name: '项目0000001'},
{id: 2, name: '项目0000002'},
{id: 3, name: '项目0000003'},
{id: 4, name: '项目0000004'},
{id: 5, name: '项目0000005'}
],
list1: [
{id: 1, name: '项目0000001'},
{id: 2, name: '项目0000002'},
{id: 3, name: '项目0000003'},
{id: 4, name: '项目0000004'},
{id: 5, name: '项目0000005'}
],
list2: [
{id: 6, name: '项目0000006'},
{id: 7, name: '项目0000007'},
{id: 8, name: '项目0000008'},
{id: 9, name: '项目0000009'},
{id: 10, name: '项目0000010'}
],
grid: [
{id: 1, name: '项目0000001'},
{id: 2, name: '项目0000002'},
{id: 3, name: '项目0000003'},
{id: 4, name: '项目0000004'},
{id: 5, name: '项目0000005'}
],
grid1: [
{id: 1, name: '项目0000001'},
{id: 2, name: '项目0000002'},
{id: 3, name: '项目0000003'},
{id: 4, name: '项目0000004'},
{id: 5, name: '项目0000005'}
],
grid2: [
{id: 6, name: '项目0000006'},
{id: 7, name: '项目0000007'},
{id: 8, name: '项目0000008'},
{id: 9, name: '项目0000009'},
{id: 10, name: '项目0000010'}
]
};
}
}
</script>
<style scoped>
/** 列表样式 */
.demo-drag-list {
border: 1px solid hsla(0, 0%, 60%, .2);
}
.demo-drag-list-item {
line-height: 1;
padding: 12px 16px;
}
.demo-drag-list-item + .demo-drag-list-item {
border-top: 1px solid hsla(0, 0%, 60%, .2);
}
.demo-drag-list-item.sortable-chosen {
background: hsla(0, 0%, 60%, .1);
}
.demo-drag-list-item .sort-handle {
cursor: move;
font-size: 16px;
}
/** 宫格样式 */
.demo-drag-grid {
border: 1px solid hsla(0, 0%, 60%, .2);
padding: 16px 0 0 16px;
}
.demo-drag-grid-item {
padding: 16px;
margin: 0 16px 16px 0;
display: inline-block;
border: 1px solid hsla(0, 0%, 60%, .2);
cursor: move;
}
.demo-drag-grid-item.sortable-chosen {
background: hsla(0, 0%, 60%, .1);
}
</style>

View File

@@ -0,0 +1,68 @@
<template>
<div class="ele-body">
<a-card :bordered="false">
<!-- 按钮 -->
<a-space class="ele-table-tool">
<a-button
type="primary"
@click="showHtml">获取html
</a-button>
<a-button
type="primary"
@click="showText">获取文本
</a-button>
<a-button
type="primary"
@click="setContent">修改内容
</a-button>
</a-space>
<!-- 编辑器 -->
<tinymce-editor
v-model:value="value"
:init="{height: 525}"/>
</a-card>
</div>
</template>
<script>
import TinymceEditor from '@/components/TinymceEditor';
import {Modal} from 'ant-design-vue';
export default {
name: 'ExtensionEditor',
components: {TinymceEditor},
data() {
return {
value: ''
};
},
methods: {
/* 获取编辑器内容 */
showHtml() {
Modal.info({
maskClosable: true,
content: this.value
});
},
/* 获取编辑器纯文本内容 */
showText() {
Modal.info({
maskClosable: true,
content: this.$util.htmlToText(this.value)
});
},
/* 修改编辑器内容 */
setContent() {
this.value = [
'<div style="text-align:center;color:#fff;background-image:linear-gradient(-90deg,rgb(62,119,255),rgb(159,98,212),rgb(255,78,170));padding:32px 0;">',
' <div style="font-size:28px;margin-bottom:16px;">EleAdminPro后台管理模板</div>',
' <div style="font-size:18px">通用型后台管理模板,界面美观、开箱即用,拥有丰富的组件和模板</div>',
'</div><br/>'
].join('');
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,418 @@
<template>
<div class="ele-body ele-body-card">
<a-card title="导出excel" :bordered="false">
<!-- 表格 -->
<ele-pro-table
bordered
row-key="key"
:datasource="data"
:columns="columns"
:need-page="false"
tools-theme="default"
v-model:selection="selection"
:toolkit="['size', 'columns', 'fullscreen']"
:scroll="{x: 'max-content'}">
<template #toolbar>
<a-space>
<a-button
type="primary"
@click="exportBas">导出excel
</a-button>
<a-button
type="primary"
@click="exportAdv">导出带合并
</a-button>
<a-button
type="primary"
@click="exportSel">导出选中
</a-button>
</a-space>
</template>
</ele-pro-table>
</a-card>
<a-card title="导入excel" :bordered="false">
<!-- 操作按钮 -->
<ele-toolbar :tools="[]">
<a-space>
<a-upload
:before-upload="importFile"
:show-upload-list="false"
accept=".xls,.xlsx,.csv">
<a-button type="primary">导入excel</a-button>
</a-upload>
<a-upload
:before-upload="importFile2"
:show-upload-list="false"
accept=".xls,.xlsx,.csv">
<a-button type="primary">导入拆分合并</a-button>
</a-upload>
<a-upload
:before-upload="importFile3"
:show-upload-list="false"
accept=".xls,.xlsx,.csv">
<a-button type="primary">导入保持合并</a-button>
</a-upload>
</a-space>
</ele-toolbar>
<div class="ant-table ant-table-middle ant-table-bordered">
<div class="ant-table-content">
<div class="ant-table-body">
<table>
<thead class="ant-table-thead">
<tr>
<th></th>
<th
v-for="item in importTitle"
:key="item"
style="text-align: center;">
{{ item }}
</th>
</tr>
</thead>
<tbody class="ant-table-tbody">
<tr v-for="(item,index) in importData" :key="index">
<td style="text-align: center;">{{ index + 1 }}</td>
<template v-for="key in importTitle">
<td
v-if="item['__colspan__'+key]!==0&&item['__rowspan__'+key]!==0"
:key="key"
:colspan="item['__colspan__'+key]"
:rowspan="item['__rowspan__'+key]"
style="text-align: center;">
{{ item[key] }}
</td>
</template>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<a-row :gutter="32">
<a-col :md="12" :xs="24">
<div style="margin:16px 0;">二维数组格式数据</div>
<pre
style="max-height: 300px;padding: 16px;overflow: auto;"
class="ele-bg-base">{{ JSON.stringify(importDataAoa, null, 4) }}
</pre>
</a-col>
<a-col :md="12" :xs="24">
<div style="margin: 16px 0;">JSON格式数据</div>
<pre
style="max-height: 300px;padding: 16px;overflow: auto;"
class="ele-bg-base">{{ JSON.stringify(importData, null, 4) }}
</pre>
</a-col>
</a-row>
</a-card>
</div>
</template>
<script>
import XLSX from 'xlsx';
export default {
name: 'ExtensionExcel',
data() {
return {
// 表格数据
data: [
{
key: 1,
username: '张小三',
amount: 18,
province: '浙江',
city: '杭州',
zone: '西湖区',
street: '西溪街道',
address: '西溪花园30栋1单元',
},
{
key: 2,
username: '李小四',
amount: 39,
province: '江苏',
city: '苏州',
zone: '姑苏区',
street: '丝绸路',
address: '天墅之城9幢2单元',
},
{
key: 3,
username: '王小五',
amount: 8,
province: '江西',
city: '南昌',
zone: '青山湖区',
street: '艾溪湖办事处',
address: '中兴和园1幢3单元',
},
{
key: 4,
username: '赵小六',
amount: 16,
province: '福建',
city: '泉州',
zone: '丰泽区',
street: '南洋街道',
address: '南洋村6幢1单元',
},
{
key: 5,
username: '孙小七',
amount: 12,
province: '湖北',
city: '武汉',
zone: '武昌区',
street: '武昌大道',
address: '两湖花园16幢2单元',
},
{
key: 6,
username: '周小八',
amount: 11,
province: '安徽',
city: '黄山',
zone: '黄山区',
street: '汤口镇',
address: '温泉村21号',
}
],
// 表格列配置
columns: [
{
key: 'index',
customRender: ({index}) => `${index + 1}`,
align: 'center'
},
{
title: '用户名',
dataIndex: 'username',
align: 'center'
},
{
title: '地址',
key: 'cityAddress',
children: [
{
title: '省',
dataIndex: 'province',
align: 'center'
},
{
title: '市',
dataIndex: 'city',
align: 'center'
},
{
title: '区',
dataIndex: 'zone',
align: 'center'
},
{
title: '街道',
dataIndex: 'street',
align: 'center'
},
{
title: '详细地址',
dataIndex: 'address',
align: 'center'
}
]
},
{
title: '金额',
dataIndex: 'amount',
align: 'center'
}
],
// 选中数据
selection: [],
// 导入的数据
importData: [],
// 导入数据的列
importTitle: ['A', 'B', 'C', 'D', 'E', 'F', 'G'],
// 导入数据二维数组形式
importDataAoa: []
};
},
methods: {
/* 导出excel */
exportBas() {
let array = [['用户名', '省', '市', '区', '街道', '详细地址', '金额']];
this.data.forEach(d => {
array.push([d.username, d.province, d.city, d.zone, d.street, d.address, d.amount]);
});
this.$util.exportSheet(XLSX, array, '用户数据');
},
/* 导出带单元格合并 */
exportAdv() {
let array = [
['用户名', '地址', null, null, null, null, '金额'],
[null, '省', '市', '区', '街道', '详细地址', null]
];
this.data.forEach(d => {
array.push([d.username, d.province, d.city, d.zone, d.street, d.address, d.amount]);
});
let sheet = XLSX.utils.aoa_to_sheet(array);
sheet['!merges'] = [
{s: {r: 0, c: 1}, e: {r: 0, c: 5}}, // 合并第0行第1列到第0行第5列
{s: {r: 0, c: 0}, e: {r: 1, c: 0}}, // 合并第0行第0列到第1行第0列
{s: {r: 0, c: 6}, e: {r: 1, c: 6}} // 合并第0行第6列到第1行第6列
];
this.$util.exportSheet(XLSX, sheet, '用户数据');
},
/* 导出选中数据 */
exportSel() {
if (this.selection.length === 0) {
this.$message.error('请至少选择一条数据');
return;
}
let array = [['用户名', '省', '市', '区', '街道', '详细地址', '金额']];
this.selection.forEach(d => {
array.push([d.username, d.province, d.city, d.zone, d.street, d.address, d.amount]);
});
this.$util.exportSheet(XLSX, array, '用户数据');
},
/* 导入本地excel文件 */
importFile(file) {
let reader = new FileReader();
reader.onload = (e) => {
let data = new Uint8Array(e.target.result);
let workbook = XLSX.read(data, {type: 'array'});
let sheetNames = workbook.SheetNames;
let worksheet = workbook.Sheets[sheetNames[0]];
// 解析成二维数组
let aoa = XLSX.utils.sheet_to_json(worksheet, {header: 1});
// 生成表格需要的数据
let list = [], maxCols = 0, title = [];
aoa.forEach(d => {
if (d.length > maxCols) {
maxCols = d.length;
}
let row = {};
for (let i = 0; i < d.length; i++) {
let key = this.getCharByIndex(i);
row[key] = d[i];
row['__colspan__' + key] = 1;
row['__rowspan__' + key] = 1;
}
list.push(row);
});
for (let i = 0; i < maxCols; i++) {
title.push(this.getCharByIndex(i));
}
this.importTitle = title;
this.importData = list;
this.importDataAoa = aoa;
};
reader.readAsArrayBuffer(file);
return false;
},
/* 导入excel拆分合并单元格 */
importFile2(file) {
let reader = new FileReader();
reader.onload = (e) => {
let data = new Uint8Array(e.target.result);
let workbook = XLSX.read(data, {type: 'array'});
let sheetNames = workbook.SheetNames;
let worksheet = workbook.Sheets[sheetNames[0]];
// 解析成二维数组
let aoa = XLSX.utils.sheet_to_json(worksheet, {header: 1});
// 拆分合并单元格
if (worksheet['!merges']) {
worksheet['!merges'].forEach(m => {
for (let r = m.s.r; r <= m.e.r; r++) {
for (let c = m.s.c; c <= m.e.c; c++) {
aoa[r][c] = aoa[m.s.r][m.s.c];
}
}
});
}
// 生成表格需要的数据
let list = [], maxCols = 0, title = [];
aoa.forEach(d => {
if (d.length > maxCols) {
maxCols = d.length;
}
let row = {};
for (let i = 0; i < d.length; i++) {
row[this.getCharByIndex(i)] = d[i];
}
list.push(row);
});
for (let i = 0; i < maxCols; i++) {
title.push(this.getCharByIndex(i));
}
this.importTitle = title;
this.importData = list;
this.importDataAoa = aoa;
};
reader.readAsArrayBuffer(file);
return false;
},
/* 导入excel读取合并信息 */
importFile3(file) {
let reader = new FileReader();
reader.onload = (e) => {
let data = new Uint8Array(e.target.result);
let workbook = XLSX.read(data, {type: 'array'});
let sheetNames = workbook.SheetNames;
let worksheet = workbook.Sheets[sheetNames[0]];
// 解析成二维数组
let aoa = XLSX.utils.sheet_to_json(worksheet, {header: 1});
// 生成表格需要的数据
let list = [], maxCols = 0, title = [];
aoa.forEach(d => {
if (d.length > maxCols) {
maxCols = d.length;
}
let row = {};
for (let i = 0; i < d.length; i++) {
row[this.getCharByIndex(i)] = d[i];
}
list.push(row);
});
for (let i = 0; i < maxCols; i++) {
title.push(this.getCharByIndex(i));
}
// 记录合并单元格
if (worksheet['!merges']) {
worksheet['!merges'].forEach(m => {
for (let r = m.s.r; r <= m.e.r; r++) {
for (let c = m.s.c; c <= m.e.c; c++) {
let cc = this.getCharByIndex(c);
list[r]['__colspan__' + cc] = 0;
list[r]['__rowspan__' + cc] = 0;
}
}
let char = this.getCharByIndex(m.s.c);
list[m.s.r]['__colspan__' + char] = m.e.c - m.s.c + 1;
list[m.s.r]['__rowspan__' + char] = m.e.r - m.s.r + 1;
});
}
this.importTitle = title;
this.importData = list;
this.importDataAoa = aoa;
};
reader.readAsArrayBuffer(file);
return false;
},
/* 生成Excel列字母序号 */
getCharByIndex(index) {
let chars = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
if (index < chars.length) {
return chars[index];
}
let n = parseInt(index / chars.length),
m = index % chars.length;
return chars[n] + chars[m];
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,289 @@
<template>
<div class="ele-body">
<a-card
:bordered="false"
:body-style="{padding: 0, minHeight: '520px'}">
<div style="padding: 16px 16px 0 16px;">
<!-- 工具栏 -->
<div class="ele-table-tool">
<div class="ele-table-tool-title">
<a-space>
<a-upload
:showUploadList="false"
:customRequest="doUpload">
<a-button type="primary">上传</a-button>
</a-upload>
<a-button type="primary">新建文件夹</a-button>
<a-button danger type="primary">删除</a-button>
</a-space>
</div>
<!-- 搜索框 -->
<div style="max-width: 240px;">
<a-input-search
v-model:value="search"
placeholder="搜索您的文件"/>
</div>
<!-- 显示方式切换 -->
<menu-outlined
v-if="grid"
class="ele-file-tool-btn"
@click="grid=!grid"/>
<appstore-outlined
v-else
class="ele-file-tool-btn"
@click="grid=!grid"/>
</div>
<!-- 文件目录面包屑 -->
<div class="ele-file-breadcrumb-group ele-cell">
<div class="ele-cell-content ele-cell">
<div
v-if="directory.length"
class="ele-file-breadcrumb-back ele-text-primary"
@click="back">返回上一级
</div>
<div class="ele-file-breadcrumb-list ele-cell-content ele-cell">
<div
:class="['ele-file-breadcrumb-item ele-cell', {'ele-text-primary': directory.length}]"
@click="listAll">
<div class="ele-file-breadcrumb-item-title">全部文件</div>
<right-outlined v-if="directory.length"/>
</div>
<div
v-for="(item,index) in directory"
:key="index"
@click="listDir(index)"
:class="['ele-file-breadcrumb-item ele-cell', {'ele-text-primary': index!==directory.length-1}]">
<div class="ele-file-breadcrumb-item-title">{{ item }}</div>
<right-outlined v-if="index!==directory.length-1"/>
</div>
</div>
</div>
<div>已全部加载 {{ data.length }} </div>
</div>
</div>
<a-spin :spinning="loading">
<!-- 文件展示列表 -->
<ele-file-list
:data="data"
v-model:checked="checked"
:grid="grid"
:sort="sort"
:order="order"
@item-click="onItemClick"
@sort-change="onSortChange">
</ele-file-list>
</a-spin>
</a-card>
</div>
</template>
<script>
import EleFileList from 'ele-admin-pro/packages/ele-file-list';
import {
MenuOutlined,
AppstoreOutlined,
RightOutlined
} from '@ant-design/icons-vue';
export default {
name: 'ExtensionFile',
components: {
EleFileList,
MenuOutlined,
AppstoreOutlined,
RightOutlined
},
data() {
return {
// 加载状态
loading: true,
// 是否网格展示
grid: true,
// 文件列表数据
data: [],
// 选中数据
checked: [],
// 文件目录面包屑数据
directory: [],
// 搜索
search: '',
// 排序字段
sort: '',
// 排序方式
order: '',
// 图片预览文件
currentImage: '',
};
},
computed: {
// 图片预览列表
previewList() {
return this.data.filter(d => d.thumbnail).map(d => d.url);
}
},
mounted() {
this.query();
},
methods: {
/* 查询文件列表 */
query() {
this.checked = [];
this.loading = true;
this.$http.get('/file/list', {
params: {
directory: this.directory.join('/'),
sort: this.sort,
order: this.order
}
}).then(res => {
this.loading = false;
if (res.data.code === 0) {
res.data.data.forEach(d => {
// 文件地址加baseURL
if (d.url) {
d.url = this.$http.defaults.baseURL + '/' + d.url;
}
if (d.thumbnail) {
d.thumbnail = this.$http.defaults.baseURL + '/' + d.thumbnail;
}
// 文件大小格式化
if (d.isDirectory) {
d.length = '-';
} else {
d.length = this.getFileSize(d.length);
}
// 修改时间格式化
if (d.updateTime) {
d.updateTime = this.$util.toDateString(d.updateTime);
}
});
this.data = res.data.data;
} else {
this.$message.error(res.data.msg);
}
}).catch(e => {
this.loading = false;
this.$message.error(e.message);
});
},
/* item点击事件 */
onItemClick(item) {
if (item.isDirectory) { // 文件夹
this.directory.push(item.name);
this.query();
} /*else if (item.thumbnail) {
this.currentImage = item.url;
}*/ else if (this.checked.indexOf(item) !== -1) {
this.checked.splice(this.checked.indexOf(item), 1);
} else {
this.checked.push(item);
}
},
/* 返回上级 */
back() {
this.directory.splice(this.directory.length - 1, 1);
this.query();
},
/* 全部文件 */
listAll() {
if (!this.directory.length) {
return;
}
this.directory = [];
this.query();
},
/* 回到指定目录 */
listDir(index) {
if (index === this.directory.length - 1) {
return;
}
this.directory.splice(index, this.directory.length - index);
this.query();
},
/* 文件大小格式化 */
getFileSize(value) {
if (value < 1024) {
return value + 'B';
} else if (value < 1024 * 1024) {
return (value / 1024).toFixed(1) + 'KB';
} else if (value < 1024 * 1024 * 1024) {
return (value / 1024 / 1024).toFixed(1) + 'M';
} else {
return (value / 1024 / 1024 / 1024).toFixed(1) + 'G';
}
},
/* 文件列表排序方式改变 */
onSortChange(obj) {
this.order = obj.order;
this.sort = obj.sort;
this.query();
},
/* 查看文件 */
view(item) {
if (item.isDirectory) {
this.onItemClick(item);
} else if (item.url) {
window.open(item.url);
}
},
/* 上传 */
doUpload({file}) {
let formData = new FormData();
formData.append('file', file);
const hide = this.$message.loading('上传中..', 0);
this.$http.post('/file/upload', formData).then(res => {
hide();
if (res.data.code === 0) {
this.$message.success(res.data.msg);
this.directory = [res.data.dir.replace(/\//, '')];
this.query();
} else {
this.$message.error(res.data.msg);
}
}).catch(e => {
hide();
this.$message.error(e.message);
});
return false;
}
}
}
</script>
<style scoped>
/* 图标按钮 */
.ele-file-tool-btn {
font-size: 20px;
margin-left: 16px;
cursor: pointer;
}
/* 文件目录面包屑 */
.ele-file-breadcrumb-group {
margin-bottom: 12px;
line-height: 1;
}
.ele-file-breadcrumb-back {
padding-right: 12px;
border-right: 1px solid hsla(0, 0%, 60%, .3);
}
.ele-file-breadcrumb-back:hover,
.ele-file-breadcrumb-item.ele-text-primary:hover > .ele-file-breadcrumb-item-title {
text-decoration: underline;
cursor: pointer;
}
.ele-file-breadcrumb-item .anticon {
margin: 0 4px;
font-size: 12px;
}
@media screen and (max-width: 768px) {
.ele-table-tool > .ele-table-tool-title + div,
.ele-file-breadcrumb-group > .ele-cell-content + div {
display: none;
}
}
</style>

261
src/views/extension/map.vue Normal file
View File

@@ -0,0 +1,261 @@
<template>
<div class="ele-body ele-body-card">
<!-- 地图位置选择弹窗 -->
<ele-map-picker
v-model:visible="showPicker"
:need-city="true"
@done="onChoose"/>
<ele-map-picker
v-model:visible="showPicker2"
:need-city="true"
:search-type="1"
@done="onChoose"/>
<!-- 弹窗选择位置 -->
<a-card title="弹窗选择位置" :bordered="false">
<a-space>
<a-button
type="primary"
@click="showPicker=true">地图选择位置(POI)
</a-button>
<a-button
type="primary"
@click="showPicker2=true">关键字检索模式
</a-button>
</a-space>
<div v-if="form.location">
<div style="margin-top: 12px;">选择位置: {{ form.location }}</div>
<div style="margin-top: 12px;">详细地址: {{ form.address }}</div>
<div style="margin-top: 12px;"> : {{ form.jinweidu }}</div>
</div>
</a-card>
<!-- 官网底部地图 -->
<a-card title="官网底部地图" :bordered="false">
<div ref="locationMap" style="height: 360px;max-width: 1000px;"></div>
</a-card>
<!-- 轨迹展示及轨迹回放 -->
<a-card title="轨迹展示及轨迹回放" :bordered="false">
<div ref="trackMap" style="height: 360px;margin-bottom: 16px;max-width: 1000px;"></div>
<a-space>
<a-button
type="primary"
@click="startTrackAnim">开始动画
</a-button>
<a-button
type="primary"
@click="pauseTrackAnim">暂停动画
</a-button>
<a-button
type="primary"
@click="resumeTrackAnim">继续动画
</a-button>
</a-space>
</a-card>
</div>
</template>
<script>
import EleMapPicker from 'ele-admin-pro/packages/ele-map-picker';
import AMapLoader from '@amap/amap-jsapi-loader';
export default {
name: 'ExtensionMap',
components: {EleMapPicker},
data() {
return {
// 是否显示地图选择弹窗
showPicker: false,
// 是否显示地图选择弹窗2
showPicker2: false,
// 表单
form: {},
// 小车的marker
carMarker: null,
// 轨迹路线
lineData: [
[116.478935, 39.997761],
[116.478939, 39.997825],
[116.478912, 39.998549],
[116.478912, 39.998549],
[116.478998, 39.998555],
[116.478998, 39.998555],
[116.479282, 39.99856],
[116.479658, 39.998528],
[116.480151, 39.998453],
[116.480784, 39.998302],
[116.480784, 39.998302],
[116.481149, 39.998184],
[116.481573, 39.997997],
[116.481863, 39.997846],
[116.482072, 39.997718],
[116.482362, 39.997718],
[116.483633, 39.998935],
[116.48367, 39.998968],
[116.484648, 39.999861]
],
// 官网底部地图的实例
mapInsLocation: null,
// 小车轨迹地图的实例
mapInsTrack: null
};
},
computed: {
// 是否是暗黑模式
darkMode() {
return this.$store.state.theme.darkMode;
}
},
mounted() {
this.renderLocationMap();
this.renderTrackMap();
},
methods: {
/* 地图选择后回调 */
onChoose(location) {
console.log(location);
this.form = {
location: location.city.province + '/' + location.city.city + '/' + location.city.district,
address: location.name + ' ' + location.address,
jinweidu: location.lng + ',' + location.lat
};
this.showPicker = false;
this.showPicker2 = false;
},
/* 渲染官网底部地图 */
renderLocationMap() {
AMapLoader.load({
'key': '006d995d433058322319fa797f2876f5',
'version': '2.0',
'plugins': ['AMap.InfoWindow', 'AMap.Marker']
}).then((AMap) => {
// 渲染地图
let option = {
zoom: 13, // 初缩放级别
center: [114.346084, 30.511215 + 0.005] // 初始中心点
};
if (this.darkMode) {
option.mapStyle = 'amap://styles/dark';
}
this.mapInsLocation = new AMap.Map(this.$refs.locationMap, option);
// 创建信息窗体
let infoWindow = new AMap.InfoWindow({
content: `
<div style="color: #333;">
<div style="padding: 5px;font-size: 16px;">武汉易云智科技有限公司</div>
<div style="padding: 0 5px;">地址湖北省武汉市洪山区雄楚大道222号</div>
<div style="padding: 0 5px;">电话020-123456789</div>
</div>
<a style="padding: 8px 5px 0;text-decoration: none;display: inline-block;" class="ele-text-primary"
href="//uri.amap.com/marker?position=114.346084,30.511215&name=武汉易云智科技有限公司"
target="_blank">到这里去→</a>
`
});
infoWindow.open(this.mapInsLocation, [114.346084, 30.511215]);
let icon = new AMap.Icon({
size: new AMap.Size(25, 34),
image: '//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-red.png',
imageSize: new AMap.Size(25, 34)
});
let marker = new AMap.Marker({
icon: icon,
position: [114.346084, 30.511215],
offset: new AMap.Pixel(-12, -28)
});
marker.setMap(this.mapInsLocation);
marker.on('click', () => {
infoWindow.open(this.mapInsLocation);
});
}).catch(e => {
console.error(e);
});
},
/* 渲染轨迹回放地图 */
renderTrackMap() {
AMapLoader.load({
'key': '006d995d433058322319fa797f2876f5',
'version': '2.0',
'plugins': ['AMap.MoveAnimation', 'AMap.Marker', 'AMap.Polyline']
}).then((AMap) => {
// 渲染地图
let option = {
zoom: 17,
center: [116.478935, 39.997761],
};
if (this.darkMode) {
option.mapStyle = 'amap://styles/dark';
}
this.mapInsTrack = new AMap.Map(this.$refs.trackMap, option);
// 创建小车marker
this.carMarker = new AMap.Marker({
map: this.mapInsTrack,
position: [116.478935, 39.997761],
icon: 'https://a.amap.com/jsapi_demos/static/demo-center-v2/car.png',
offset: new AMap.Pixel(-13, -26),
});
// 绘制轨迹
new AMap.Polyline({
map: this.mapInsTrack,
path: this.lineData,
showDir: true,
strokeColor: '#28F', // 线颜色
strokeOpacity: 1, // 线透明度
strokeWeight: 6, // 线宽
//strokeStyle: 'solid' // 线样式
});
// 通过的轨迹
let passedPolyline = new AMap.Polyline({
map: this.mapInsTrack,
showDir: true,
strokeColor: '#4B5', // 线颜色
strokeOpacity: 1, // 线透明度
strokeWeight: 6, // 线宽
});
// 小车移动回调
this.carMarker.on('moving', function (e) {
passedPolyline.setPath(e.passedPath);
});
// 地图自适应
this.mapInsTrack.setFitView();
}).catch(e => {
console.error(e);
});
},
/* 开始轨迹回放动画 */
startTrackAnim() {
this.carMarker.stopMove();
this.carMarker.moveAlong(this.lineData, {
duration: 200,
autoRotation: true,
});
},
/* 暂停轨迹回放动画 */
pauseTrackAnim() {
this.carMarker.pauseMove();
},
/* 继续开始轨迹回放动画 */
resumeTrackAnim() {
this.carMarker.resumeMove();
}
},
watch: {
darkMode() {
if (this.mapInsLocation) {
if (this.darkMode) {
this.mapInsLocation.setMapStyle('amap://styles/dark');
} else {
this.mapInsLocation.setMapStyle('amap://styles/normal');
}
}
if (this.mapInsTrack) {
if (this.darkMode) {
this.mapInsTrack.setMapStyle('amap://styles/dark');
} else {
this.mapInsTrack.setMapStyle('amap://styles/normal');
}
}
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,34 @@
<template>
<div class="ele-body ele-body-card">
<more-tag/>
<more-city-select/>
<more-modal/>
<more-color-picker/>
<more-cropper/>
<more-count-up/>
</div>
</template>
<script>
import MoreModal from './more-modal';
import MoreTag from './more-tag';
import MoreCitySelect from './more-city-select';
import MoreColorPicker from './more-color-picker';
import MoreCropper from './more-cropper';
import MoreCountUp from './more-count-up';
export default {
name: 'ExtensionMore',
components: {
MoreTag,
MoreCitySelect,
MoreColorPicker,
MoreCropper,
MoreCountUp,
MoreModal
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,44 @@
<template>
<a-card title="省市区级联选择" :bordered="false">
<a-space>
<a-cascader
v-model:value="city"
:options="cityData.cityData"
placeholder="请选择省市区"
popup-class-name="ele-pop-wrap-higher"/>
<a-cascader
v-model:value="provinceCity"
:options="cityData.provinceCityData"
placeholder="请选择省市"
popup-class-name="ele-pop-wrap-higher"/>
<a-cascader
v-model:value="province"
:options="cityData.provinceData"
placeholder="请选择省"
popup-class-name="ele-pop-wrap-higher"/>
</a-space>
</a-card>
</template>
<script>
import regions from 'ele-admin-pro/packages/regions.js';
export default {
name: 'MoreCitySelect',
data() {
return {
// 省市区数据
cityData: regions,
// 选中的省市区
city: [],
// 选中的省市
provinceCity: [],
// 选中的省
province: [],
};
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,53 @@
<template>
<a-card title="颜色选择器" :bordered="false">
<a-space>
<ele-color-picker
size="large"
:show-alpha="true"
v-model:value="color"
:predefine="predefineColors"/>
<ele-color-picker
:show-alpha="true"
v-model:value="color"
:predefine="predefineColors"/>
<ele-color-picker
size="small"
:show-alpha="true"
v-model:value="color"
:predefine="predefineColors"/>
</a-space>
</a-card>
</template>
<script>
import EleColorPicker from 'ele-admin-pro/packages/ele-color-picker';
export default {
name: 'MoreColorPicker',
components: {EleColorPicker},
data() {
return {
color: 'rgba(255, 69, 0, 0.68)',
predefineColors: [
'#ff4500',
'#ff8c00',
'#ffd700',
'#90ee90',
'#00ced1',
'#1e90ff',
'#c71585',
'rgba(255, 69, 0, 0.68)',
'rgb(255, 120, 0)',
'hsv(51, 100, 98)',
'hsva(120, 40, 94, 0.5)',
'hsl(181, 100%, 37%)',
'hsla(209, 100%, 56%, 0.73)',
'#c7158577'
]
};
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,71 @@
<template>
<a-card title="数字滚动" :bordered="false">
<h1 style="margin-bottom: 12px;">
<ele-count-up
:delay="0"
:end-val="countUpVal"
:options="countUpOptions"
@ready="onCountUpReady"/>
</h1>
<a-space>
<a-button
type="primary"
@click="startCountUp">重新开始
</a-button>
<a-button
type="primary"
@click="updateCountUp">更新数字
</a-button>
</a-space>
</a-card>
</template>
<script>
import EleCountUp from 'ele-admin-pro/packages/ele-count-up';
export default {
name: 'MoreCountUp',
components: {EleCountUp},
data() {
return {
// countUp值
countUpVal: 6317,
// countUp配置
countUpOptions: {
useEasing: true,
useGrouping: true,
separator: ',',
decimal: '.',
prefix: '',
suffix: ''
},
// countUp实例
countUpIns: null
};
},
methods: {
/* countUp渲染完成 */
onCountUpReady(instance) {
this.countUpIns = instance;
},
/* countUp重新开始 */
startCountUp() {
if (!this.countUpIns) {
return;
}
this.countUpIns.reset();
this.countUpIns.start();
},
/* countUp更新 */
updateCountUp() {
if (!this.countUpIns) {
return;
}
this.countUpIns.update(1000 + Math.round(Math.random() * 9000));
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,54 @@
<template>
<a-card title="图片裁剪" :bordered="false">
<a-space size="middle">
<a-button
type="primary"
@click="visible1=true">1 : 1 裁剪
</a-button>
<a-button
type="primary"
@click="visible2=true">16 : 9 裁剪
</a-button>
</a-space>
<div v-if="result" style="margin-top: 16px;">
<img :src="result" style="height: 120px;width: auto;"/>
</div>
<!-- 图片裁剪 -->
<ele-cropper-modal
:src="src"
v-model:visible="visible1"
@done="onDone"/>
<ele-cropper-modal
:src="src"
:aspect-ratio="16/9"
v-model:visible="visible2"
@done="onDone"/>
</a-card>
</template>
<script>
import EleCropperModal from 'ele-admin-pro/packages/ele-cropper-modal';
export default {
name: 'MoreCropper',
components: {EleCropperModal},
data() {
return {
visible1: false,
visible2: false,
src: 'https://cdn.eleadmin.com/20200610/LrCTN2j94lo9N7wEql7cBr1Ux4rHMvmZ.jpg',
result: null
};
},
methods: {
onDone(result) {
this.result = result;
this.visible1 = false;
this.visible2 = false;
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,207 @@
<template>
<a-card title="可拖拽、拉伸、全屏弹窗" :bordered="false">
<div>
<a-space>
<a-button type="primary" @click="openDialog">可拖拽弹窗</a-button>
<a-button type="primary" @click="openMoveOutDialog">允许拖出边界</a-button>
<a-button type="primary" @click="openHideModalDialog">不要遮罩层</a-button>
</a-space>
</div>
<div style="margin-top: 16px;">
<a-space>
<a-button type="primary" @click="openFullDialog">默认全屏打开</a-button>
<a-button type="primary" @click="openMoreDialog">默认左下角打开</a-button>
</a-space>
</div>
</a-card>
<!-- 弹窗1 -->
<a-modal
:mask="mask"
:width="400"
v-model:visible="visible"
:wrap-class-name="wrapClassName"
:body-style="{paddingBottom: '16px'}"
@cancel="cancel"
@ok="save">
<template #title>
<div class="ele-cell">
<div class="ele-cell-content">拖拽弹窗</div>
<compress-outlined class="ele-modal-icon-compress"/>
<expand-outlined class="ele-modal-icon-expand"/>
</div>
</template>
<a-form
ref="form"
:model="form"
:rules="rules"
:label-col="{flex: '70px'}"
:wrapper-col="{flex: 'auto'}">
<a-form-item label="用户名" name="nickname" style="flex-wrap: nowrap;">
<a-input
allow-clear
placeholder="请输入用户名"
v-model:value="form.nickname"/>
</a-form-item>
<a-form-item label="性别" name="sex">
<a-select
allow-clear
placeholder="请选择性别"
v-model:value="form.sex">
<a-select-option value="男"></a-select-option>
<a-select-option value="女"></a-select-option>
</a-select>
</a-form-item>
<a-form-item label="手机号" name="phone" style="flex-wrap: nowrap;">
<a-input
allow-clear
placeholder="请输入手机号"
v-model:value="form.phone"/>
</a-form-item>
<a-form-item label="邮箱" name="email" style="flex-wrap: nowrap;">
<a-input
allow-clear
placeholder="请输入邮箱"
v-model:value="form.email"/>
</a-form-item>
<a-form-item label="个人简介" style="flex-wrap: nowrap;">
<a-textarea
:rows="4"
placeholder="请输入个人简介"
v-model:value="form.introduction"/>
</a-form-item>
</a-form>
</a-modal>
<!-- 弹窗2 -->
<a-modal
:width="400"
:mask="false"
v-model:visible="visible2"
wrap-class-name="ele-modal-movable ele-modal-resizable ele-modal-multiple ele-modal-wrap-fullscreen">
<template #title>
<div class="ele-cell">
<div class="ele-cell-content">默认全屏打开</div>
<compress-outlined class="ele-modal-icon-compress"/>
<expand-outlined class="ele-modal-icon-expand"/>
</div>
</template>
<div style="min-height: 66px;">我是弹窗2</div>
</a-modal>
<!-- 弹窗3 -->
<a-modal
:width="400"
:mask="false"
title="默认左下角打开"
class="demo-modal-eg3"
v-model:visible="visible3"
wrap-class-name="ele-modal-movable ele-modal-resizable ele-modal-multiple">
<div style="min-height: 66px;">我是弹窗3</div>
</a-modal>
</template>
<script>
import {ExpandOutlined, CompressOutlined} from '@ant-design/icons-vue';
export default {
name: 'MoreModal',
components: {ExpandOutlined, CompressOutlined},
data() {
return {
// 弹窗是否打开
visible: false,
visible2: false,
visible3: false,
// 表单数据
form: {},
// 是否显示遮罩层
mask: true,
// 是否允许拖出边界
moveOut: false,
// 表单验证规则
rules: {
nickname: [
{required: true, message: '请输入用户名', type: 'string', trigger: 'blur'}
],
sex: [
{required: true, message: '请选择性别', type: 'string', trigger: 'blur'}
],
phone: [
{required: true, message: '请输入手机号', type: 'string', trigger: 'blur'}
],
email: [
{required: true, message: '请输入邮箱', type: 'string', trigger: 'blur'}
]
}
};
},
computed: {
// 弹窗一的wrap-class
wrapClassName() {
return [
this.moveOut ? 'ele-modal-move-out' : 'ele-modal-movable',
this.mask ? '' : 'ele-modal-multiple',
'ele-modal-resizable'
].join(' ');
}
},
methods: {
/* 打开弹窗 */
openDialog() {
if (!this.visible) {
this.mask = true;
this.moveOut = false;
this.visible = true;
}
},
/* 打开允许拖出边界弹窗 */
openMoveOutDialog() {
this.moveOut = true;
if (!this.visible) {
this.mask = true;
this.visible = true;
}
},
/* 打开无遮罩层弹窗 */
openHideModalDialog() {
this.moveOut = false;
if (!this.visible) {
this.mask = false;
this.visible = true;
}
},
/* 弹窗关闭回调 */
cancel() {
this.$refs.form.clearValidate();
},
/* 保存编辑 */
save() {
this.$refs.form.validate().then(() => {
this.$message.success('保存成功');
}).catch(() => {
});
},
/* 打开默认全屏弹窗 */
openFullDialog() {
if (!this.visible2) {
this.visible2 = true;
}
},
/* 打开弹窗3 */
openMoreDialog() {
if (!this.visible3) {
this.visible3 = true;
}
}
}
}
</script>
<style>
.demo-modal-eg3 {
position: absolute;
right: 0;
bottom: 0;
top: auto;
left: auto;
margin: 0;
}
</style>

View File

@@ -0,0 +1,161 @@
<template>
<a-card title="标签" :bordered="false">
<div class="demo-tag-item">
<div class="demo-tag-label">预设颜色:</div>
<div class="demo-tag-content">
<ele-tag
:color="colors[type][0]"
:size="size">标签一
</ele-tag>
<ele-tag
:color="colors[type][1]"
:size="size">标签二
</ele-tag>
<ele-tag
:color="colors[type][2]"
:size="size">标签三
</ele-tag>
<ele-tag
:color="colors[type][3]"
:size="size">标签四
</ele-tag>
<ele-tag
:color="colors[type][4]"
:size="size">标签五
</ele-tag>
</div>
</div>
<div class="demo-tag-item">
<div class="demo-tag-label">圆角样式:</div>
<div class="demo-tag-content">
<ele-tag
:color="colors[type][0]"
:size="size"
shape="round">标签一
</ele-tag>
<ele-tag
:color="colors[type][1]"
:size="size"
shape="round">标签二
</ele-tag>
<ele-tag
:color="colors[type][2]"
:size="size"
shape="round">标签三
</ele-tag>
<ele-tag
:color="colors[type][3]"
:size="size"
shape="round">标签四
</ele-tag>
<ele-tag
:color="colors[type][4]"
:size="size"
shape="round">标签五
</ele-tag>
</div>
</div>
<div class="demo-tag-item">
<div class="demo-tag-label">圆形样式:</div>
<div class="demo-tag-content">
<ele-tag
:color="colors[type][0]"
:size="size"
shape="circle">1
</ele-tag>
<ele-tag
:color="colors[type][1]"
:size="size"
shape="circle">2
</ele-tag>
<ele-tag
:color="colors[type][2]"
:size="size"
shape="circle">3
</ele-tag>
<ele-tag
:color="colors[type][3]"
:size="size"
shape="circle">4
</ele-tag>
<ele-tag
:color="colors[type][4]"
:size="size"
shape="circle">5
</ele-tag>
</div>
</div>
<div class="demo-tag-item" style="align-items: flex-start;">
<div class="demo-tag-label">标签输入:</div>
<div class="demo-tag-content">
<ele-edit-tag
v-model:data="tags"
:color="colors[type][0]"
:size="size"/>
<div>{{ JSON.stringify(tags) }}</div>
</div>
</div>
<div class="demo-tag-item">
<div class="demo-tag-label">尺寸选择:</div>
<div class="demo-tag-content">
<a-radio-group
:options="sizes"
v-model:value="size"/>
</div>
</div>
<div class="demo-tag-item">
<div class="demo-tag-label">主题选择:</div>
<div class="demo-tag-content">
<a-radio-group
:options="types"
v-model:value="type"/>
</div>
</div>
</a-card>
</template>
<script>
export default {
name: 'MoreTag',
data() {
return {
size: 'mini',
sizes: [
{label: 'mini', value: 'mini'},
{label: 'small', value: 'small'},
{label: 'middle', value: 'middle'},
{label: 'large', value: 'large'}
],
colors: [
['', 'blue', 'green', 'orange', 'red'],
['#909399', '#1890ff', '#52c41a', '#fa8c16', '#f5222d']
],
types: [
{label: 'presets', value: 0},
{label: 'custom', value: 1},
],
type: 0,
tags: ['标签一', '标签二', '标签三']
};
}
}
</script>
<style scoped>
.demo-tag-item {
display: flex;
align-items: center;
}
.demo-tag-item .demo-tag-label {
padding-right: 16px;
}
.demo-tag-item .demo-tag-content {
flex: 1;
}
.demo-tag-item + .demo-tag-item {
margin-top: 22px;
}
</style>

View File

@@ -0,0 +1,334 @@
<template>
<div class="ele-body ele-body-card">
<a-row :gutter="16">
<a-col :lg="12" :md="24" :sm="24" :xs="24">
<a-card title="基础演示" :bordered="false">
<!-- 操作按钮 -->
<a-space style="margin-bottom: 16px;">
<a-button
type="primary"
:disabled="!ready1"
@click="play">播放
</a-button>
<a-button
type="primary"
:disabled="!ready1"
@click="pause">暂停
</a-button>
<a-button
type="primary"
:disabled="!ready1"
@click="replay">重新播放
</a-button>
<a-button
type="primary"
:disabled="!ready1"
@click="changeSrc">切换视频源
</a-button>
</a-space>
<!-- 播放器 -->
<xgplayer
:config="config1"
@player="onPlayer1"/>
</a-card>
</a-col>
<a-col :lg="12" :md="24" :sm="24" :xs="24">
<a-card title="显示弹幕" :bordered="false">
<!-- 操作按钮 -->
<a-space style="margin-bottom: 16px;">
<a-input
style="width: 160px;"
v-model:value="dmText"
placeholder="请输入弹幕内容"
:disabled="!ready2"/>
<a-button
type="primary"
:disabled="!ready2"
@click="shoot">发射
</a-button>
</a-space>
<!-- 播放器 -->
<xgplayer
:config="config2"
@player="onPlayer2"/>
</a-card>
</a-col>
</a-row>
</div>
</template>
<script>
import Xgplayer from 'xgplayer-vue';
export default {
name: 'ExtensionPlayer',
components: {Xgplayer},
data() {
return {
// 视频播放器一配置
config1: {
id: 'demoPlayer1',
lang: 'zh-cn',
fluid: true,
// 视频地址
url: 'https://s1.pstatp.com/cdn/expire-1-M/byted-player-videos/1.0.0/xgplayer-demo.mp4',
// 封面
poster: 'https://imgcache.qq.com/open_proj/proj_qcloud_v2/gateway/solution/general-video/css/img/scene/1.png',
// 开启倍速播放
playbackRate: [0.5, 1, 1.5, 2],
// 开启画中画
pip: true
},
// 视频播放器一实例
player1: null,
// 视频播放器一是否实例化完成
ready1: false,
// 视频播放器二配置
config2: {
id: 'demoPlayer2',
lang: 'zh-cn',
fluid: true,
url: 'https://blz-videos.nosdn.127.net/1/OverWatch/AnimatedShots/Overwatch_TheatricalTeaser_WeAreOverwatch_zhCN.mp4',
poster: 'https://imgcache.qq.com/open_proj/proj_qcloud_v2/gateway/solution/general-video/css/img/scene/1.png',
danmu: {
comments: [
{
id: '1',
start: 0,
txt: '空降',
duration: 15000,
color: true,
style: {
color: '#ffcd08',
fontSize: '20px'
}
},
{
id: '2',
start: 1500,
txt: '前方高能',
duration: 15000,
color: true,
style: {
color: '#ffcd08',
fontSize: '20px'
}
},
{
id: '3',
start: 3500,
txt: '弹幕护体',
duration: 15000,
color: true,
style: {
color: '#ffcd08',
fontSize: '20px'
}
},
{
id: '4',
start: 4500,
txt: '弹幕护体',
duration: 15000,
color: true,
style: {
color: '#ffcd08',
fontSize: '20px'
}
},
{
id: '5',
start: 6000,
txt: '前方高能',
duration: 15000,
color: true,
style: {
color: '#ffcd08',
fontSize: '20px'
}
},
{
id: '6',
start: 8500,
txt: '弹幕护体',
duration: 15000,
color: true,
style: {
color: '#ffcd08',
fontSize: '20px'
}
},
{
id: '7',
start: 10000,
txt: '666666666',
duration: 15000,
color: true,
style: {
color: '#ffcd08',
fontSize: '20px'
}
},
{
id: '8',
start: 12500,
txt: '前方高能',
duration: 15000,
color: true,
style: {
color: '#ffcd08',
fontSize: '20px'
}
},
{
id: '9',
start: 15500,
txt: '666666666',
duration: 15000,
color: true,
style: {
color: '#ffcd08',
fontSize: '20px'
}
},
{
id: '10',
start: 16500,
txt: '666666666',
duration: 15000,
color: true,
style: {
color: '#ffcd08',
fontSize: '20px'
}
},
{
id: '11',
start: 18000,
txt: '关弹幕,保智商',
duration: 15000,
color: true,
style: {
color: '#ffcd08',
fontSize: '20px'
}
},
{
id: '12',
start: 20500,
txt: '关弹幕,保智商',
duration: 15000,
color: true,
style: {
color: '#ffcd08',
fontSize: '20px'
}
},
{
id: '13',
start: 22000,
txt: '666666666',
duration: 15000,
color: true,
style: {
color: '#ffcd08',
fontSize: '20px'
}
},
{
id: '14',
start: 25500,
txt: '666666666',
duration: 15000,
color: true,
style: {
color: '#ffcd08',
fontSize: '20px'
}
},
{
id: '15',
start: 26000,
txt: '前方高能',
duration: 15000,
color: true,
style: {
color: '#ffcd08',
fontSize: '20px'
}
}
]
}
},
// 视频播放器二实例
player2: null,
// 视频播放器二是否实例化完成
ready2: false,
// 弹幕输入内容
dmText: ''
};
},
methods: {
/* 播放器一渲染完成 */
onPlayer1(e) {
this.player1 = e;
this.player1.on('play', () => {
this.ready1 = true;
});
},
/* 播放 */
play() {
if (this.player1.paused) {
this.player1.play();
}
},
/* 暂停 */
pause() {
if (!this.player1.paused) {
this.player1.pause();
}
},
/* 重新播放 */
replay() {
this.player1.replay();
},
/* 切换视频源 */
changeSrc() {
this.player1.src = 'https://blz-videos.nosdn.127.net/1/OverWatch/AnimatedShots/Overwatch_TheatricalTeaser_WeAreOverwatch_zhCN.mp4';
if (this.player1.paused) {
this.player1.play();
}
},
/* 播放器二渲染完成 */
onPlayer2(e) {
this.player2 = e;
this.player2.on('play', () => {
this.ready2 = true;
});
},
/* 发射弹幕 */
shoot() {
if (!this.dmText) {
this.$message.error('请输入弹幕内容');
return;
}
this.player2.danmu.sendComment({
id: new Date().getTime(),
duration: 15000,
color: true,
start: this.player2.currentTime * 1000,
txt: this.dmText,
style: {
color: '#fa1f41',
fontSize: '20px',
border: 'solid 1px #fa1f41'
}
});
this.dmText = '';
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,366 @@
<template>
<div class="ele-body ele-body-card">
<a-card title="打印当前页面" :bordered="false">
<div style="margin-bottom: 16px;">支持IE浏览器打印预览</div>
<a-space>
<a-button @click="print({})">打印当前页面</a-button>
<a-button @click="print({horizontal:true})">横屏打印</a-button>
<!--<a-button @click="print({blank:true})">新窗口打印</a-button>-->
<a-button @click="print({hide:['.demo-hide-1']})">打印时隐藏指定内容</a-button>
</a-space>
<div style="margin-top: 16px;">
<span class="ele-text-danger ele-printer-hide">此段内容会在所有打印时自动隐藏打印完自动复原</span>
<span class="ele-text-primary demo-hide-1">此段内容在指定打印时才隐藏</span>
</div>
</a-card>
<a-card title="打印任意内容" :bordered="false">
<a-space>
<a-button @click="printHtml()">打印任意内容</a-button>
<!--<a-button @click="printHtml(true)">新窗口打印</a-button>-->
<a-button @click="printAddHeader">设置页眉页脚</a-button>
<a-button @click="printImage">打印图片</a-button>
</a-space>
</a-card>
<a-card title="分页打印" :bordered="false">
<a-space>
<a-button @click="printPage()">分页打印</a-button>
<!--<a-button @click="printPage(true)">新窗口分页打印</a-button>-->
<a-button @click="printPageAddHeader">分页打印设置页眉页脚</a-button>
</a-space>
</a-card>
<a-card title="进阶示例" :bordered="false">
<a-space>
<a-button @click="printDataTable">打印数据表格</a-button>
<a-tooltip title="对于复杂的打印需求可以后端生成pdf给前端打印">
<a-button @click="printPdf">打印pdf</a-button>
</a-tooltip>
<a-button @click="printQrCode">打印条码</a-button>
<a-button @click="printTable">打印自定义表格</a-button>
</a-space>
</a-card>
</div>
</template>
<script>
import printer from 'ele-admin-pro/packages/printer.js';
export default {
name: 'ExtensionPrinter',
data() {
return {
users: [
{
key: 1,
username: '张小三',
amount: 18,
province: '浙江',
city: '杭州',
zone: '西湖区',
street: '西溪街道',
address: '西溪花园30栋1单元',
},
{
key: 2,
username: '李小四',
amount: 39,
province: '江苏',
city: '苏州',
zone: '姑苏区',
street: '丝绸路',
address: '天墅之城9幢2单元',
},
{
key: 3,
username: '王小五',
amount: 8,
province: '江西',
city: '南昌',
zone: '青山湖区',
street: '艾溪湖办事处',
address: '中兴和园1幢3单元',
},
{
key: 4,
username: '赵小六',
amount: 16,
province: '福建',
city: '泉州',
zone: '丰泽区',
street: '南洋街道',
address: '南洋村6幢1单元',
},
{
key: 5,
username: '孙小七',
amount: 12,
province: '湖北',
city: '武汉',
zone: '武昌区',
street: '武昌大道',
address: '两湖花园16幢2单元',
},
{
key: 6,
username: '周小八',
amount: 11,
province: '安徽',
city: '黄山',
zone: '黄山区',
street: '汤口镇',
address: '温泉村21号',
}
]
};
},
methods: {
/* 打印当前页面 */
print(options) {
printer.print(options);
},
/* 打印任意内容 */
printHtml(blank) {
printer.printHtml({
html: '<h1>Hello! Welcome To EleAdminPro!</h1>',
blank: blank
});
},
/* 打印设置页眉页脚 */
printAddHeader() {
printer.printHtml({
html: `
<div style="padding: 0 60px;">
<h1>Hello</h1><h1>Hello</h1><h1>Hello</h1><h1>Hello</h1><h1>Hello</h1><h1>Hello</h1><h1>Hello</h1>
<h1>Hello</h1><h1>Hello</h1><h1>Hello</h1><h1>Hello</h1><h1>Hello</h1><h1>Hello</h1><h1>Hello</h1>
<h1>Hello</h1><h1>Hello</h1><h1>Hello</h1><h1>Hello</h1><h1>Hello</h1><h1>Hello</h1><h1>Hello</h1>
<h1>Hello</h1><h1>Hello</h1><h1>Hello</h1><h1>Hello</h1><h1>Hello</h1><h1>Hello</h1><h1>Hello</h1>
<h1>Hello</h1><h1>Hello</h1><h1>Hello</h1><h1>Hello</h1><h1>Hello</h1><h1>Hello</h1><h1>Hello</h1>
<h1>Hello</h1><h1>Hello</h1><h1>Hello</h1><h1>Hello</h1><h1>Hello</h1><h1>Hello</h1><h1>Hello</h1>
</div>
`,
margin: 0,
header: `
<div style="text-align: center;font-size: 12px;padding: 15px 30px 25px;">
<span style="float: left;">我是页眉左侧</span>
<span>我是页眉</span>
<span style="float: right;">我是页眉右侧</span>
</div>`,
footer: `
<div style="text-align: center;font-size: 12px;padding: 15px 30px 25px;">
<span style="float: left;">我是页脚左侧</span>
<span>我是页脚</span>
<span style="float: right;">我是页脚右侧</span>
</div>`
});
},
/* 打印图片 */
printImage() {
printer.printHtml({
html: '<img src="https://cdn.eleadmin.com/20200610/LrCTN2j94lo9N7wEql7cBr1Ux4rHMvmZ.jpg" style="width: 100%;"/>'
});
},
/* 分页打印 */
printPage(blank) {
printer.printPage({
htmls: [
'<div>我是第一页</div>',
'<div>我是第二页</div>',
'<div>我是第三页</div>',
'<div>我是第四页</div>',
'<div>我是第五页</div>'
],
style: '<style>div{color: red;}</style>',
blank: blank
});
},
/* 分页打印设置页眉页脚 */
printPageAddHeader() {
printer.printPage({
htmls: [
'<span class="ele-printer-num">1/5</span><div>我是第一页</div>',
'<span class="ele-printer-num">2/5</span><div>我是第二页</div>',
'<span class="ele-printer-num">3/5</span><div>我是第三页</div>',
'<span class="ele-printer-num">4/5</span><div>我是第四页</div>',
'<span class="ele-printer-num">5/5</span><div>我是第五页</div>'
],
margin: 0,
padding: '30px 60px',
header: `
<div style="text-align: center;font-size: 12px;padding: 15px 30px;">
<span style="float: left;">我是页眉左侧</span>
<span>我是页眉</span>
<span style="float: right;">我是页眉右侧</span>
</div>`,
footer: `
<div style="text-align: center;font-size: 12px;padding: 15px 30px;">
<span style="float: left;">我是页脚左侧</span>
<span>我是页脚</span>
<span style="float: right;">我是页脚右侧</span>
</div>`,
style: `
<style>
.ele-printer-page-item > div { color: red; }
.ele-printer-num {
position: absolute;
top: -35px;
right: 10px;
font-size: 12px;
}
</style>`
});
},
/* 打印数据表格 */
printDataTable() {
let html = printer.makeTable(this.users, [
[
{field: 'username', width: 150, rowspan: 2, title: '联系人'},
{align: 'center', colspan: 3, title: '地址'},
{field: 'amount', width: 120, rowspan: 2, title: '金额', align: 'center'}
],
[
{field: 'province', width: 120, title: '省'},
{field: 'city', width: 120, title: '市'},
{
width: 200, title: '区', templet: (d) => {
return `<span style="color:red;">${d.zone}</span>`;
}
}
]
]);
printer.printHtml({html: '<p>提供数据和cols配置自动生成复杂表格非常的方便</p>' + html});
},
/* 打印pdf */
printPdf() {
printer.printPdf({url: 'https://cdn.eleadmin.com/20200610/20200708224450.pdf'});
},
/* 打印条码 */
printQrCode() {
let html = `
<div class="code-group">
<div class="code-group-title">EasyWeb授权凭证</div>
<div class="code-group-body">
<p>手机扫描右侧二维码,或登录</p>
<p>网站https://easyweb.vip</p>
<p>查询产品真伪</p>
<img src="https://cdn.eleadmin.com/20200610/20200708230820.png" width="70px" height="70px"/>
<span>515AE3X1</span>
</div>
</div>
<style>
.code-group {
display: inline-block;
border: 1px solid #ccc;
border-radius: 5px;
background-color: #fff;
}
.code-group-title {
border-bottom: 1px solid #ccc;
padding: 10px 15px;
text-align: center;
font-size: 18px;
}
.code-group-body {
text-align: center;
position: relative;
padding: 15px 115px 0 25px;
min-height: 90px;
}
.code-group-body > p {
margin: 0 0 13px 0;
font-size: 15px;
font-family: 幼圆;
color: #333;
font-weight: 600;
}
.code-group-body > img, .code-group-body > span {
position: absolute;
right: 25px;
top: 15px;
}
.code-group-body > span {
top: 90px;
}
</style>
`;
printer.printHtml({html: html});
},
/* 打印自定义表格 */
printTable() {
let html = `
<h2 style="text-align: center;color: #333;">软工xxxx班课程表</h2>
<table class="ele-printer-table">
<colgroup>
<col width="130px"/>
</colgroup>
<tr>
<th style="position: relative;">
<span style="position: absolute;right: 20px;top: 10px;line-height: normal;">星期</span>
<span style="position: absolute;left: 20px;bottom: 10px;line-height: normal;">时间</span>
<div style="height: 1px; width:140px;background-color: #000;position: absolute;left: 0;top: 0;transform: rotate(21deg);transform-origin: 0 0;"></div>
</th>
<th>周一</th>
<th>周二</th>
<th>周三</th>
<th>周四</th>
<th>周五</th>
</tr>
<tr>
<td>8:00-10:00</td>
<td>HTML5网页设计<br/>曲丽丽 - 441教室</td>
<td>数据库原理及应用<br/>严良 - 716机房</td>
<td>JavaSE初级程序设计<br/>肖萧 - 715机房</td>
<td></td>
<td>JavaScript程序设计<br/>董娜 - 733机房</td>
</tr>
<tr>
<td>10:30-12:30</td>
<td></td>
<td>JavaScript程序设计<br/>董娜 - 733机房</td>
<td></td>
<td>锋利的jQuery<br/>程咏 - 303教室</td>
<td>JavaEE应用开发<br/>周星 - 303教室</td>
</tr>
<tr>
<td colspan="6" style="height: auto;">午休</td>
</tr>
<tr>
<td>13:30-15:30</td>
<td>JavaSE初级程序设计<br/>肖萧 - 715机房</td>
<td></td>
<td>HTML5网页设计<br/>曲丽丽 - 441教室</td>
<td></td>
<td></td>
</tr>
<tr>
<td>16:00-18:00</td>
<td></td>
<td>JavaEE应用开发<br/>周星 - 303教室</td>
<td></td>
<td>数据库原理及应用<br/>严良 - 716机房</td>
<td></td>
</tr>
</table>
<style>
th, td {
text-align: center;
line-height: 32px;
}
td {
height: 110px;
}
</style>
`;
printer.printHtml({html: html, horizontal: true});
}
}
}
</script>
<style scoped>
.ant-space {
flex-wrap: wrap;
}
.ant-space .ant-btn {
margin-bottom: 8px;
}
</style>