feat: print and perf style

This commit is contained in:
xiaoxian521 2022-03-02 13:56:07 +08:00
parent e3fda52801
commit 727c0fe3c0
31 changed files with 4475 additions and 1787 deletions

View File

@ -14,20 +14,16 @@
<body>
<div id="app">
<style>
* {
margin: 0;
padding: 0;
}
html,
body {
body,
#app {
width: 100%;
height: 100%;
display: flex;
position: relative;
justify-content: center;
align-items: center;
overflow: hidden;
font-family: "Reggae One", cursive;
}
.loader,
@ -53,6 +49,8 @@
transform: translateZ(0);
-webkit-animation-delay: -0.16s;
animation-delay: -0.16s;
top: 0;
transform: translate(-50%, 0);
}
.loader:before,
@ -96,7 +94,7 @@
}
}
</style>
<div class="loader">Loading...</div>
<div class="loader"></div>
</div>
<script type="module" src="/src/main.ts"></script>
</body>

View File

@ -76,7 +76,7 @@ const frameRouter = {
},
children: [
{
path: "/frame/pure",
path: "/iframe/pure",
name: "reFramePure",
meta: {
i18n: true,

View File

@ -116,7 +116,7 @@
"stylelint-order": "^5.0.0",
"typescript": "^4.5.5",
"unplugin-element-plus": "^0.2.0",
"vite": "^2.8.5",
"vite": "^2.8.6",
"vite-plugin-live-reload": "^2.1.0",
"vite-plugin-mock": "^2.9.6",
"vite-plugin-remove-console": "^0.0.6",

5031
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -126,7 +126,7 @@ onMounted(() => {
}
.iconfont {
font-size: 25px;
font-size: 18px;
}
.control-container p {

View File

@ -24,6 +24,8 @@ import Location from "@iconify-icons/ep/location";
import Tickets from "@iconify-icons/ep/tickets";
import OfficeBuilding from "@iconify-icons/ep/office-building";
import Notebook from "@iconify-icons/ep/notebook";
import Rank from "@iconify-icons/ep/rank";
import videoPlay from "@iconify-icons/ep/video-play";
import Monitor from "@iconify-icons/ep/monitor";
addIcon("check", Check);
addIcon("menu", Menu);
@ -47,6 +49,8 @@ addIcon("location", Location);
addIcon("tickets", Tickets);
addIcon("office-building", OfficeBuilding);
addIcon("notebook", Notebook);
addIcon("video-play", videoPlay);
addIcon("rank", Rank);
addIcon("monitor", Monitor);
// remixicon

View File

@ -55,4 +55,8 @@ onMounted(() => {
box-sizing: border-box;
}
}
.main-content {
margin: 0;
}
</style>

View File

@ -8,7 +8,6 @@ import { useAppStoreHook } from "/@/store/modules/app";
import { remainingPaths } from "/@/router/modules/index";
import { Title } from "../../../public/serverConfig.json";
import { useEpThemeStoreHook } from "/@/store/modules/epTheme";
import { remainingPaths } from "/@/router/modules/index";
export function useNav() {
const pureApp = useAppStoreHook();

View File

@ -44,6 +44,12 @@ import {
ElCollapse,
ElCollapseItem,
ElTreeV2,
ElTable,
ElTableColumn,
ElLink,
ElColorPicker,
ElSelect,
ElOption,
// 指令
ElLoading,
ElInfiniteScroll
@ -96,7 +102,13 @@ const components = [
ElEmpty,
ElCollapse,
ElCollapseItem,
ElTreeV2
ElTreeV2,
ElTable,
ElTableColumn,
ElLink,
ElColorPicker,
ElSelect,
ElOption
];
export function useElementPlus(app: App) {

View File

@ -37,6 +37,7 @@ export default {
hsAble: "Able",
hsMenuTree: "Menu Tree",
hsWatermark: "Water Mark",
hsPrint: "Print",
hsExternalPage: "External Page",
hsPureDocument: "Pure Document",
hsEpDocument: "Element Plus Document"

View File

@ -37,6 +37,7 @@ export default {
hsAble: "功能",
hsMenuTree: "菜单树结构",
hsWatermark: "水印",
hsPrint: "打印",
hsExternalPage: "外部页面",
hsPureDocument: "平台文档",
hsEpDocument: "Element Plus文档"

View File

@ -30,6 +30,15 @@ const ableRouter = {
title: $t("menus.hsWatermark"),
i18n: true
}
},
{
path: "/able/print",
name: "rePrint",
component: () => import("/@/views/able/print.vue"),
meta: {
title: $t("menus.hsPrint"),
i18n: true
}
}
]
};

View File

@ -12,8 +12,8 @@ body {
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
text-rendering: optimizelegibility;
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB,
Microsoft YaHei, Arial, sans-serif;
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB",
"Microsoft YaHei", "微软雅黑", Arial, sans-serif;
}
html {

226
src/utils/print.ts Normal file
View File

@ -0,0 +1,226 @@
interface PrintFunction {
extendOptions: Function;
getStyle: Function;
setDomHeight: Function;
toPrint: Function;
}
const Print = function (dom, options?: object): PrintFunction {
options = options || {};
// @ts-expect-error
if (!(this instanceof Print)) return new Print(dom, options);
this.conf = {
styleStr: "",
// Elements that need to dynamically get and set the height
setDomHeightArr: [],
// Echart dom List
echartDomArr: [],
// Callback before printing
printBeforeFn: null,
// Callback after printing
printDoneCallBack: null
};
for (const key in this.conf) {
// eslint-disable-next-line no-prototype-builtins
if (key && options.hasOwnProperty(key)) {
this.conf[key] = options[key];
}
}
if (typeof dom === "string") {
this.dom = document.querySelector(dom);
} else {
this.dom = this.isDOM(dom) ? dom : dom.$el;
}
if (this.conf.setDomHeightArr && this.conf.setDomHeightArr.length) {
this.setDomHeight(this.conf.setDomHeightArr);
}
this.init();
};
Print.prototype = {
/**
* init
*/
init: function (): void {
const content = this.getStyle() + this.getHtml();
this.writeIframe(content);
},
/**
* Configuration property extension
* @param {Object} obj
* @param {Object} obj2
*/
extendOptions: function <T>(obj, obj2: T): T {
for (const k in obj2) {
obj[k] = obj2[k];
}
return obj;
},
/**
Copy all styles of the original page
*/
getStyle: function (): string {
let str = "";
const styles: NodeListOf<Element> = document.querySelectorAll("style,link");
for (let i = 0; i < styles.length; i++) {
str += styles[i].outerHTML;
}
str += `<style>.no-print{display:none;}${this.conf.styleStr}</style>`;
return str;
},
// form assignment
getHtml: function (): Element {
const inputs = document.querySelectorAll("input");
const selects = document.querySelectorAll("select");
const textareas = document.querySelectorAll("textarea");
for (let k = 0; k < inputs.length; k++) {
if (inputs[k].type == "checkbox" || inputs[k].type == "radio") {
if (inputs[k].checked == true) {
inputs[k].setAttribute("checked", "checked");
} else {
inputs[k].removeAttribute("checked");
}
} else if (inputs[k].type == "text") {
inputs[k].setAttribute("value", inputs[k].value);
} else {
inputs[k].setAttribute("value", inputs[k].value);
}
}
for (let k2 = 0; k2 < textareas.length; k2++) {
if (textareas[k2].type == "textarea") {
textareas[k2].innerHTML = textareas[k2].value;
}
}
for (let k3 = 0; k3 < selects.length; k3++) {
if (selects[k3].type == "select-one") {
const child = selects[k3].children;
for (const i in child) {
if (child[i].tagName == "OPTION") {
// @ts-ignore
if (child[i].selected == true) {
child[i].setAttribute("selected", "selected");
} else {
child[i].removeAttribute("selected");
}
}
}
}
}
return this.dom.outerHTML;
},
/**
create iframe
*/
writeIframe: function (content) {
let w: Document | Window;
let doc: Document;
const iframe: HTMLIFrameElement = document.createElement("iframe");
const f: HTMLIFrameElement = document.body.appendChild(iframe);
iframe.id = "myIframe";
iframe.setAttribute(
"style",
"position:absolute;width:0;height:0;top:-10px;left:-10px;"
);
// eslint-disable-next-line prefer-const
w = f.contentWindow || f.contentDocument;
// eslint-disable-next-line prefer-const
doc = f.contentDocument || f.contentWindow.document;
doc.open();
doc.write(content);
doc.close();
// eslint-disable-next-line @typescript-eslint/no-this-alias
const _this = this;
iframe.onload = function (): void {
// Before popping, callback
if (_this.conf.printBeforeFn) {
_this.conf.printBeforeFn({ doc });
}
_this.drawEchartImg(doc).then(() => {
_this.toPrint(w);
setTimeout(function () {
document.body.removeChild(iframe);
// After popup, callback
if (_this.conf.printDoneCallBack) {
_this.conf.printDoneCallBack();
}
}, 100);
});
};
},
/**
* echarts printing
* @param {Object} doc iframe window
*/
drawEchartImg(doc): Promise<void> {
return new Promise<void>(resolve => {
if (this.conf.echartDomArr && this.conf.echartDomArr.length > 0) {
this.conf.echartDomArr.forEach(e => {
const dom = doc.querySelector("#" + e.$el.id);
const img = new Image();
const w = dom.offsetWidth + "px";
const H = dom.offsetHeight + "px";
img.style.width = w;
img.style.height = H;
img.src = e.imgSrc;
dom.innerHTML = "";
dom.appendChild(img);
});
}
resolve();
});
},
/**
Print
*/
toPrint: function (frameWindow): void {
try {
setTimeout(function () {
frameWindow.focus();
try {
if (!frameWindow.document.execCommand("print", false, null)) {
frameWindow.print();
}
} catch (e) {
frameWindow.print();
}
frameWindow.close();
}, 10);
} catch (err) {
console.error(err);
}
},
isDOM:
typeof HTMLElement === "object"
? function (obj) {
return obj instanceof HTMLElement;
}
: function (obj) {
return (
obj &&
typeof obj === "object" &&
obj.nodeType === 1 &&
typeof obj.nodeName === "string"
);
},
/**
* Set the height of the specified dom element by getting the existing height of the dom element and setting
* @param {Array} arr
*/
setDomHeight(arr) {
if (arr && arr.length) {
arr.forEach(name => {
const domArr = document.querySelectorAll(name);
domArr.forEach(dom => {
dom.style.height = dom.offsetHeight + "px";
});
});
}
}
};
export default Print;

View File

@ -6,31 +6,78 @@ export default {
<script setup lang="ts">
import { ref, computed } from "vue";
import type { ElTreeV2 } from "element-plus";
import { transformI18n } from "/@/plugins/i18n";
import { useRenderIcon } from "/@/components/ReIcon/src/hooks";
import { extractPathList, deleteChildren } from "/@/utils/tree";
import { usePermissionStoreHook } from "/@/store/modules/permission";
import type { TreeNode } from "element-plus/es/components/tree-v2/src/types";
interface treeNode extends TreeNode {
meta: {
title: string;
i18n: boolean;
};
}
const query = ref("");
let dataProps = ref({
value: "uniqueId",
children: "children"
});
const treeRef = ref<InstanceType<typeof ElTreeV2>>();
let menusData = computed(() => {
return deleteChildren(usePermissionStoreHook().menusTree);
});
let expandedKeys = extractPathList(menusData.value);
const onQueryChanged = (query: string) => {
// @ts-expect-error
treeRef.value!.filter(query);
};
const filterMethod = (query: string, node: treeNode) => {
return transformI18n(node.meta.title, node.meta.i18n)!.indexOf(query) !== -1;
};
</script>
<template>
<el-tree-v2
:data="menusData"
:props="dataProps"
show-checkbox
:height="500"
:default-expanded-keys="expandedKeys"
>
<template #default="{ data }">
<span>{{ $t(data.meta.title) }}</span>
<el-card>
<template #header>
<div class="card-header">
<span class="font-medium"
>菜单树结构采用element-plus的
<el-link
href="https://element-plus.gitee.io/zh-CN/component/tree-v2.html"
target="_blank"
:icon="useRenderIcon('node-tree')"
style="font-size: 16px; margin: 0 5px 4px 0"
>Tree V2</el-link
>组件并支持国际化</span
>
</div>
</template>
</el-tree-v2>
<el-input
class="mb-4"
v-model="query"
placeholder="请输入关键字查找"
clearable
@input="onQueryChanged"
></el-input>
<el-tree-v2
ref="treeRef"
:data="menusData"
:props="dataProps"
show-checkbox
:height="500"
:filter-method="filterMethod"
:default-expanded-keys="expandedKeys"
>
<template #default="{ data }">
<span>{{ $t(data.meta.title) }}</span>
</template>
</el-tree-v2>
</el-card>
</template>

329
src/views/able/print.vue Normal file
View File

@ -0,0 +1,329 @@
<script setup lang="ts">
import Print from "/@/utils/print";
import { reactive, ref } from "vue";
import { VxeTablePropTypes } from "vxe-table";
import { ReLine } from "/@/components/ReCharts/index";
interface User {
date: string;
name: string;
address: string;
}
const demo1 = reactive({
tableData: [
{
id: 10001,
name: "Test1",
role: "Develop",
sex: "Man",
age: 28,
address: "test abc"
},
{
id: 10002,
name: "Test2",
role: "Test",
sex: "Women",
age: 22,
address: "Guangzhou"
},
{
id: 10003,
name: "Test3",
role: "PM",
sex: "Man",
age: 32,
address: "Shanghai"
},
{
id: 10004,
name: "Test4",
role: "Designer",
sex: "Women",
age: 24,
address: "Shanghai"
}
]
});
const value = ref("1");
const options = [
{
value: "1",
el: ".el-table",
label: "Element-Plus Table"
},
{
value: "2",
el: ".vxe-table",
label: "Vxe Table"
},
{
value: "3",
el: ".echart",
label: "Echart"
},
{
value: "4",
el: ".img",
label: "Image"
}
];
function onPrint() {
let el = options.filter(v => v.value === value.value)[0]?.el;
Print(el).toPrint;
}
const headerCellStyle: VxeTablePropTypes.HeaderCellStyle = ({ column }) => {
if (column.property === "name") {
return {
backgroundColor: "#f60",
color: "#ffffff"
};
}
};
const rowStyle: VxeTablePropTypes.RowStyle = ({ rowIndex }) => {
if ([2, 3, 5].includes(rowIndex)) {
return {
backgroundColor: "red",
color: "#ffffff"
};
}
};
const cellStyle: VxeTablePropTypes.CellStyle = ({ row, column }) => {
if (column.property === "sex") {
if (row.sex >= "1") {
return {
backgroundColor: "#187"
};
} else if (row.age === 26) {
return {
backgroundColor: "#2db7f5"
};
}
}
};
const tableRowClassName = ({ rowIndex }: { row: User; rowIndex: number }) => {
if (rowIndex === 1) {
return "warning-row";
} else if (rowIndex === 3) {
return "success-row";
}
return "";
};
const tableData: User[] = [
{
date: "2016-05-03",
name: "Tom",
address: "No. 189, Grove St, Los Angeles"
},
{
date: "2016-05-02",
name: "Tom",
address: "No. 189, Grove St, Los Angeles"
},
{
date: "2016-05-04",
name: "Tom",
address: "No. 189, Grove St, Los Angeles"
},
{
date: "2016-05-01",
name: "Tom",
address: "No. 189, Grove St, Los Angeles"
}
];
</script>
<template>
<el-card>
<template #header>
<div class="card-header">
<span class="font-medium">打印功能报表图表图片</span>
<div>
<el-select
v-model="value"
class="m-2"
placeholder="Select"
size="small"
>
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
<el-button size="small" type="primary" @click="onPrint"
>打印</el-button
>
</div>
</div>
</template>
<el-row :gutter="24">
<el-col
:xs="22"
:sm="22"
:md="11"
:lg="11"
:xl="11"
style="margin: 10px; border: 0.01rem solid var(--el-color-primary)"
v-motion
:initial="{
opacity: 0,
y: 100
}"
:enter="{
opacity: 1,
y: 0,
transition: {
delay: 200
}
}"
>
<p class="font-medium pt-1">Element-Plus Table</p>
<el-table
class="el-table"
:data="tableData"
border
style="margin: 40px auto; width: 100%"
:row-class-name="tableRowClassName"
>
<el-table-column prop="date" label="Date" width="180" />
<el-table-column prop="name" label="Name" width="180" />
<el-table-column prop="address" label="Address" />
</el-table>
</el-col>
<el-col
:xs="22"
:sm="22"
:md="11"
:lg="11"
:xl="11"
style="margin: 10px; border: 0.01rem solid var(--el-color-primary)"
v-motion
:initial="{
opacity: 0,
y: 100
}"
:enter="{
opacity: 1,
y: 0,
transition: {
delay: 200
}
}"
>
<p class="font-medium pt-1">Vxe Table</p>
<vxe-table
class="vxe-table"
border
style="margin: 40px auto"
:header-cell-style="headerCellStyle"
:row-style="rowStyle"
:cell-style="cellStyle"
:data="demo1.tableData"
>
<vxe-column type="seq" width="60"></vxe-column>
<vxe-column field="name" title="Name"></vxe-column>
<vxe-column field="sex" title="Sex"></vxe-column>
<vxe-column field="age" title="Age"></vxe-column>
<vxe-column field="attr1" title="Attr1"></vxe-column>
<vxe-column
field="address"
title="Address"
show-overflow
></vxe-column>
</vxe-table>
</el-col>
<el-col
:xs="22"
:sm="22"
:md="11"
:lg="11"
:xl="11"
style="
width: 200px;
height: 300px;
margin: 10px;
border: 0.01rem solid var(--el-color-primary);
"
v-motion
:initial="{
opacity: 0,
y: 100
}"
:enter="{
opacity: 1,
y: 0,
transition: {
delay: 200
}
}"
>
<p class="font-medium pt-1">Echart</p>
<ReLine class="echart" style="margin: 0 auto" />
</el-col>
<el-col
:xs="22"
:sm="22"
:md="11"
:lg="11"
:xl="11"
style="
width: 200px;
height: 300px;
margin: 10px;
border: 0.01rem solid var(--el-color-primary);
"
v-motion
:initial="{
opacity: 0,
y: 100
}"
:enter="{
opacity: 1,
y: 0,
transition: {
delay: 200
}
}"
>
<p class="font-medium pt-1">Image</p>
<img
src="../../assets/avatars.jpg"
alt="avatars"
class="img"
style="width: 200px; height: 200px; margin: 50px auto"
/>
</el-col>
</el-row>
</el-card>
</template>
<style lang="scss" scoped>
:deep(.el-table__row.warning-row) {
--el-table-tr-bg-color: var(--el-color-warning-light-9);
}
:deep(.el-table__row.success-row) {
--el-table-tr-bg-color: var(--el-color-success-light-9);
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
</style>

View File

@ -1,13 +1,34 @@
<script setup lang="ts">
import { ref } from "vue";
import { useWatermark } from "/@/utils/watermark";
let color = ref("#409EFF");
let value = ref("vue-pure-admin");
const { setWatermark, clear } = useWatermark();
</script>
<template>
<div>
<el-button @click="setWatermark('vue-pure-admin')">创建</el-button>
<el-card>
<template #header>
<div class="card-header">
<span class="font-medium">页面水印功能</span>
</div>
</template>
<span>请输入要创建水印的值</span
><el-input
class="mb-4 mr-4"
style="width: 200px"
v-model="value"
clearable
></el-input>
<span>请选择要创建水印的颜色</span
><el-color-picker v-model="color" show-alpha />
<br />
<el-button @click="setWatermark(value, { fillStyle: color })"
>创建</el-button
>
<el-button @click="clear">清除</el-button>
</div>
</el-card>
</template>
<style scoped></style>

View File

@ -7,13 +7,19 @@ const url = ref(`${VITE_PUBLIC_PATH}html/button.html`);
</script>
<template>
<iframe :src="url" frameborder="0" class="iframe"></iframe>
<el-card>
<template #header>
<div class="card-header">
<span class="font-medium">通过iframe引入按钮页面</span>
</div>
</template>
<iframe :src="url" frameborder="0" class="iframe"></iframe>
</el-card>
</template>
<style scoped>
.iframe {
width: 98%;
height: 90vh;
border-radius: 6px;
width: 100%;
height: 60vh;
}
</style>

View File

@ -5,7 +5,12 @@ import menuDynamic from "./menuDynamic.vue";
</script>
<template>
<div>
<el-card>
<template #header>
<div class="card-header">
<span class="font-medium">右键菜单组件</span>
</div>
</template>
<el-row :gutter="24">
<el-col :xs="24" :sm="10" :md="10" :lg="8" :xl="10">
<!-- 基本使用 -->
@ -20,5 +25,5 @@ import menuDynamic from "./menuDynamic.vue";
<menuDynamic />
</el-col>
</el-row>
</div>
</el-card>
</template>

View File

@ -3,35 +3,32 @@ import { ReNormalCountTo, ReboundCountTo } from "/@/components/ReCountTo";
</script>
<template>
<div>
<el-row :gutter="24">
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
<el-card shadow="always">
<ReNormalCountTo
prefix="$"
:duration="1000"
:color="'#409EFF'"
:fontSize="'2.3em'"
:startVal="1"
:endVal="1000"
/>
</el-card>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
<el-card shadow="always">
<ul class="flex">
<ReboundCountTo
v-for="(num, inx) of [1, 6, 6, 6]"
:key="inx"
:i="num"
:blur="inx"
:delay="inx + 1"
/>
</ul>
</el-card>
</el-col>
</el-row>
</div>
<el-card>
<template #header>
<div class="card-header">
<span class="font-medium">数字动画组件</span>
</div>
</template>
<div class="flex items-center">
<ReNormalCountTo
prefix="$"
:duration="1000"
:color="'#409EFF'"
:fontSize="'2em'"
:startVal="1"
:endVal="1000"
/>
<ul class="flex ml-8">
<ReboundCountTo
v-for="(num, inx) of [1, 6, 6, 6]"
:key="inx"
:i="num"
:blur="inx"
:delay="inx + 1"
/>
</ul>
</div>
</el-card>
</template>
<style lang="scss" scoped>

View File

@ -3,9 +3,9 @@ import { ref, nextTick, getCurrentInstance } from "vue";
import Cropper from "/@/components/ReCropper";
import img from "./picture.jpeg";
const instance = getCurrentInstance();
let info = ref<object>(null);
let cropperImg = ref<string>("");
const instance = getCurrentInstance();
const onCropper = (): void => {
nextTick(() => {
@ -25,14 +25,19 @@ const onCropper = (): void => {
</script>
<template>
<div>
<el-card>
<template #header>
<div class="card-header">
<span class="font-medium">图片裁剪组件</span>
</div>
</template>
<div class="cropper-container">
<Cropper ref="refCropper" :width="'40vw'" :src="img" />
<img :src="cropperImg" class="croppered" v-if="cropperImg" />
</div>
<el-button type="primary" @click="onCropper">裁剪</el-button>
<p v-if="cropperImg">裁剪后图片信息{{ info }}</p>
</div>
</el-card>
</template>
<style scoped>

View File

@ -1,6 +1,7 @@
<script setup lang="ts">
import { ref, onMounted } from "vue";
import draggable from "vuedraggable/src/vuedraggable";
import { useRenderIcon } from "/@/components/ReIcon/src/hooks";
let gridLists = ref<Array<Object>>([
{ grid: "cn", num: 1 },
@ -47,77 +48,92 @@ onMounted(() => {
</script>
<template>
<div class="drag-container">
<!-- grid列表拖拽 -->
<el-row :gutter="25">
<el-col :xs="25" :sm="8" :md="8" :lg="8">
<el-card>
<template #header>
<div class="card-header">
<span>grid列表拖拽</span>
</div>
</template>
<draggable
v-model="gridLists"
class="grid-container"
item-key="grid"
animation="300"
chosenClass="chosen"
forceFallback="true"
>
<template #item="{ element }">
<div :class="'item' + ' ' + 'item-' + element.num">
{{ element.num }}
<el-card>
<template #header>
<div class="card-header">
<span
>拖拽组件采用开源的<el-link
href="https://sortablejs.github.io/vue.draggable.next/#/simple"
target="_blank"
:icon="useRenderIcon('rank')"
style="font-size: 16px; margin: 0 4px 5px"
>vuedraggable</el-link
></span
>
</div>
</template>
<div class="drag-container">
<!-- grid列表拖拽 -->
<el-row :gutter="25">
<el-col :xs="25" :sm="8" :md="8" :lg="8">
<el-card>
<template #header>
<div class="card-header">
<span>grid列表拖拽</span>
</div>
</template>
</draggable>
</el-card>
</el-col>
<el-col :xs="25" :sm="8" :md="8" :lg="8">
<el-card>
<template #header>
<div class="card-header">
<span>单列拖拽</span>
</div>
</template>
<!-- 单列拖拽 -->
<draggable
v-model="lists"
item-key="name"
@change="change"
chosen-class="chosen"
force-fallback="true"
animation="300"
>
<template #item="{ element, index }">
<div class="item-single">{{ element.name }} {{ index }}</div>
</template>
</draggable>
</el-card>
</el-col>
<el-col :xs="25" :sm="8" :md="8" :lg="8">
<el-card>
<template #header>
<div class="card-header">
<span>拖拽实现元素位置切换</span>
</div>
</template>
<!-- 拖拽实现元素位置切换 -->
<div class="cut-container">
<div
class="item-cut"
v-for="(item, index) in cutLists"
:key="index"
<draggable
v-model="gridLists"
class="grid-container"
item-key="grid"
animation="300"
chosenClass="chosen"
forceFallback="true"
>
<p>{{ item.name }}</p>
<template #item="{ element }">
<div :class="'item' + ' ' + 'item-' + element.num">
{{ element.num }}
</div>
</template>
</draggable>
</el-card>
</el-col>
<el-col :xs="25" :sm="8" :md="8" :lg="8">
<el-card>
<template #header>
<div class="card-header">
<span>单列拖拽</span>
</div>
</template>
<!-- 单列拖拽 -->
<draggable
v-model="lists"
item-key="name"
@change="change"
chosen-class="chosen"
force-fallback="true"
animation="300"
>
<template #item="{ element, index }">
<div class="item-single">{{ element.name }} {{ index }}</div>
</template>
</draggable>
</el-card>
</el-col>
<el-col :xs="25" :sm="8" :md="8" :lg="8">
<el-card>
<template #header>
<div class="card-header">
<span>拖拽实现元素位置切换</span>
</div>
</template>
<!-- 拖拽实现元素位置切换 -->
<div class="cut-container">
<div
class="item-cut"
v-for="(item, index) in cutLists"
:key="index"
>
<p>{{ item.name }}</p>
</div>
</div>
</div>
</el-card>
</el-col>
</el-row>
</div>
</el-card>
</el-col>
</el-row>
</div>
</el-card>
</template>
<style lang="scss" scoped>

View File

@ -16,27 +16,34 @@ const settingTB: ContextProps = reactive({
</script>
<template>
<div class="split-pane">
<splitpane :splitSet="settingLR">
<!-- #paneL 表示指定该组件为左侧面板 -->
<template #paneL>
<!-- 自定义左侧面板的内容 -->
<div class="dv-a">A</div>
</template>
<!-- #paneR 表示指定该组件为右侧面板 -->
<template #paneR>
<!-- 再次将右侧面板进行拆分 -->
<splitpane :splitSet="settingTB">
<template #paneL>
<div class="dv-b">B</div>
</template>
<template #paneR>
<div class="dv-c">C</div>
</template>
</splitpane>
</template>
</splitpane>
</div>
<el-card>
<template #header>
<div class="card-header">
<span class="font-medium">切割面板组件</span>
</div>
</template>
<div class="split-pane">
<splitpane :splitSet="settingLR">
<!-- #paneL 表示指定该组件为左侧面板 -->
<template #paneL>
<!-- 自定义左侧面板的内容 -->
<div class="dv-a">A</div>
</template>
<!-- #paneR 表示指定该组件为右侧面板 -->
<template #paneR>
<!-- 再次将右侧面板进行拆分 -->
<splitpane :splitSet="settingTB">
<template #paneL>
<div class="dv-b">B</div>
</template>
<template #paneR>
<div class="dv-c">C</div>
</template>
</splitpane>
</template>
</splitpane>
</div>
</el-card>
</template>
<style lang="scss" scoped>

View File

@ -2,13 +2,16 @@
import { onMounted } from "vue";
import Player from "xgplayer/dist/simple_player";
import volume from "xgplayer/es/controls/volume";
import playbackRate from "xgplayer/es/controls/playbackRate";
import screenShot from "xgplayer/es/controls/screenShot";
import { deviceDetection } from "/@/utils/deviceDetection";
import playbackRate from "xgplayer/es/controls/playbackRate";
import { useRenderIcon } from "/@/components/ReIcon/src/hooks";
onMounted(() => {
new Player({
id: "mse",
//
volume: 0,
autoplay: false,
screenShot: true,
url: "https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/mp4/xgplayer-demo-720p.mp4",
@ -23,7 +26,22 @@ onMounted(() => {
</script>
<template>
<div id="mse"></div>
<el-card>
<template #header>
<div class="card-header">
<span class="font-medium"
>视频组件采用开源的<el-link
href="https://v2.h5player.bytedance.com"
target="_blank"
:icon="useRenderIcon('video-play')"
style="font-size: 16px; margin: 0 4px 5px"
>西瓜播放器</el-link
></span
>
</div>
</template>
<div id="mse"></div>
</el-card>
</template>
<style scoped>

View File

@ -5,12 +5,12 @@ export default {
</script>
<script setup lang="ts">
import { onMounted, onBeforeUnmount, ref, unref } from "vue";
import WangEditor from "wangeditor";
import { onMounted, onBeforeUnmount, ref, unref } from "vue";
import { useRenderIcon } from "/@/components/ReIcon/src/hooks";
// eslint-disable-next-line no-undef
const editor = ref(null);
const html = ref(null);
const editor = ref(null);
let instance: WangEditor;
onMounted(() => {
@ -29,17 +29,26 @@ onBeforeUnmount(() => {
</script>
<template>
<div>
<el-card>
<template #header>
<div class="card-header">
<span class="font-medium"
>编辑器组件采用开源的<el-link
href="https://www.wangeditor.com"
target="_blank"
:icon="useRenderIcon('edit')"
style="font-size: 16px; margin: 0 4px 5px"
>wangeditor</el-link
></span
>
</div>
</template>
<div ref="editor"></div>
<div :innerHTML="html"></div>
</div>
</el-card>
</template>
<style lang="scss" scoped>
.main-content {
margin: 40px;
}
:deep(.w-e-text-container) {
z-index: 99 !important;
}

View File

@ -1,13 +1,15 @@
<script setup lang="ts">
import { ref, unref, onMounted } from "vue";
import LogicFlow from "@logicflow/core";
import { Snapshot, BpmnElement, Menu } from "@logicflow/extension";
import demoData from "./dataTurbo.json";
import "@logicflow/core/dist/style/index.css";
import "@logicflow/extension/lib/style/index.css";
import LogicFlow from "@logicflow/core";
import { ref, unref, onMounted } from "vue";
import { useRenderIcon } from "/@/components/ReIcon/src/hooks";
import { BpmnNode } from "/@/components/ReFlowChart/src/config";
import { Snapshot, BpmnElement, Menu } from "@logicflow/extension";
import { Control, NodePanel, DataDialog } from "/@/components/ReFlowChart";
import { toLogicflowData } from "/@/components/ReFlowChart/src/adpterForTurbo";
import { BpmnNode } from "/@/components/ReFlowChart/src/config";
import demoData from "./dataTurbo.json";
let lf = ref(null);
let graphData = ref(null);
@ -57,37 +59,52 @@ onMounted(() => {
</script>
<template>
<div class="logic-flow-view">
<!-- 辅助工具栏 -->
<Control
class="demo-control"
v-if="lf"
:lf="lf"
:catTurboData="false"
@catData="catData"
></Control>
<!-- 节点面板 -->
<NodePanel :lf="lf" :nodeList="nodeList"></NodePanel>
<!-- 画布 -->
<div id="LF-Turbo"></div>
<!-- 数据查看面板 -->
<el-dialog
customClass="flow-dialog"
title="数据"
v-model="dataVisible"
width="50%"
>
<el-scrollbar>
<DataDialog :graphData="graphData"></DataDialog>
</el-scrollbar>
</el-dialog>
</div>
<el-card>
<template #header>
<div class="card-header">
<span class="font-medium"
>流程图组件采用开源的<el-link
href="http://logic-flow.org/"
target="_blank"
:icon="useRenderIcon('set-up')"
style="font-size: 16px; margin: 0 4px 5px"
>LogicFlow</el-link
></span
>
</div>
</template>
<div class="logic-flow-view">
<!-- 辅助工具栏 -->
<Control
class="demo-control"
v-if="lf"
:lf="lf"
:catTurboData="false"
@catData="catData"
></Control>
<!-- 节点面板 -->
<NodePanel :lf="lf" :nodeList="nodeList"></NodePanel>
<!-- 画布 -->
<div id="LF-Turbo"></div>
<!-- 数据查看面板 -->
<el-dialog
customClass="flow-dialog"
title="数据"
v-model="dataVisible"
width="50%"
>
<el-scrollbar>
<DataDialog :graphData="graphData"></DataDialog>
</el-scrollbar>
</el-dialog>
</div>
</el-card>
</template>
<style scoped>
#LF-Turbo {
width: 100%;
height: calc(100vh - 90px);
height: 70vh;
}
.logic-flow-view {
@ -137,8 +154,4 @@ onMounted(() => {
height: 85vh;
overflow: auto;
}
.main-content {
margin: 0;
}
</style>

View File

@ -1,14 +1,7 @@
<script lang="ts">
export default {
name: "reGuide"
};
</script>
<script setup lang="ts">
import Driver from "driver.js";
import "driver.js/dist/driver.min.css";
//
const steps = [
{
element: "#header-notice",
@ -72,8 +65,14 @@ const guide = () => {
</script>
<template>
<div>
<p>引导页对于一些第一次进入项目的人很有用你可以简单介绍下项目的功能</p>
<el-card>
<template #header>
<div class="card-header">
<span class="font-medium"
>引导页对于一些第一次进入项目的人很有用你可以简单介绍下项目的功能</span
>
</div>
</template>
<el-button
type="primary"
style="margin-top: 10px"
@ -81,7 +80,7 @@ const guide = () => {
>
打开引导页
</el-button>
</div>
</el-card>
</template>
<style>

View File

@ -20,12 +20,16 @@ function changRole(value) {
</script>
<template>
<div>
<el-radio-group v-model="auth" @change="changRole">
<el-radio-button label="admin"></el-radio-button>
<el-radio-button label="test"></el-radio-button>
</el-radio-group>
<el-card>
<template #header>
<div class="card-header">
<el-radio-group v-model="auth" @change="changRole">
<el-radio-button label="admin"></el-radio-button>
<el-radio-button label="test"></el-radio-button>
</el-radio-group>
</div>
</template>
<p v-auth="'v-admin'">只有admin可看</p>
<p v-auth="'v-test'">只有test可看</p>
</div>
</el-card>
</template>

View File

@ -29,19 +29,23 @@ function changRole() {
</script>
<template>
<div>
<h4>
当前角色
<span style="font-size: 26px">{{ purview }}</span>
<p style="color: #ffa500">
查看左侧菜单变化(系统管理)模拟后台根据不同角色返回对应路由
</p>
</h4>
<el-card>
<template #header>
<div class="card-header">
<span>
当前角色
<span style="font-size: 26px">{{ purview }}</span>
<p style="color: #ffa500">
查看左侧菜单变化(系统管理)模拟后台根据不同角色返回对应路由
</p></span
>
</div>
</template>
<el-button
type="primary"
@click="changRole"
:icon="useRenderIcon('user', { color: '#fff' })"
>切换角色</el-button
>
</div>
</el-card>
</template>

View File

@ -1,11 +1,9 @@
<script setup lang="ts">
import { ref } from "vue";
import { useRouter, useRoute } from "vue-router";
import { useMultiTagsStoreHook } from "/@/store/modules/multiTags";
const router = useRouter();
const route = useRoute();
const activeName = ref("tag");
function toDetail(index: number) {
useMultiTagsStoreHook().handleTags("push", {
@ -25,33 +23,16 @@ function toDetail(index: number) {
</script>
<template>
<el-collapse v-model="activeName" class="tabs-container">
<el-collapse-item
title="标签页复用超出限制自动关闭(使用场景: 动态路由)"
name="tag"
>
<el-button v-for="index in 6" :key="index" @click="toDetail(index)">
打开{{ index }}详情页
</el-button>
</el-collapse-item>
</el-collapse>
<el-card>
<template #header>
<div class="card-header">
<span class="font-medium"
>标签页复用超出限制自动关闭使用场景: 动态路由</span
>
</div>
</template>
<el-button v-for="index in 6" :key="index" @click="toDetail(index)">
打开{{ index }}详情页
</el-button>
</el-card>
</template>
<style lang="scss" scoped>
.tabs-container {
padding: 10px;
background: #fff;
::v-deep(.el-collapse-item__header) {
line-height: 20px;
}
::v-deep(.el-collapse-item__wrap) {
border-bottom: none;
}
button {
margin: 10px;
}
}
</style>

View File

@ -61,7 +61,7 @@ const openDepot = (): void => {
}
}"
>
<el-card>
<el-card style="height: 360px">
<template #header>
<span style="font-size: 16px; font-weight: 500">GitHub信息</span>
</template>
@ -93,7 +93,7 @@ const openDepot = (): void => {
}
}"
>
<el-card>
<el-card style="height: 360px">
<template #header>
<span style="font-size: 16px; font-weight: 500"
>GitHub滚动信息</span