mirror of
https://github.com/pure-admin/vue-pure-admin.git
synced 2025-06-06 00:18:51 +08:00
feat: print and perf style
This commit is contained in:
parent
e3fda52801
commit
727c0fe3c0
14
index.html
14
index.html
@ -14,20 +14,16 @@
|
|||||||
<body>
|
<body>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<style>
|
<style>
|
||||||
* {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
html,
|
html,
|
||||||
body {
|
body,
|
||||||
|
#app {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
position: relative;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
font-family: "Reggae One", cursive;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.loader,
|
.loader,
|
||||||
@ -53,6 +49,8 @@
|
|||||||
transform: translateZ(0);
|
transform: translateZ(0);
|
||||||
-webkit-animation-delay: -0.16s;
|
-webkit-animation-delay: -0.16s;
|
||||||
animation-delay: -0.16s;
|
animation-delay: -0.16s;
|
||||||
|
top: 0;
|
||||||
|
transform: translate(-50%, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.loader:before,
|
.loader:before,
|
||||||
@ -96,7 +94,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<div class="loader">Loading...</div>
|
<div class="loader"></div>
|
||||||
</div>
|
</div>
|
||||||
<script type="module" src="/src/main.ts"></script>
|
<script type="module" src="/src/main.ts"></script>
|
||||||
</body>
|
</body>
|
||||||
|
@ -76,7 +76,7 @@ const frameRouter = {
|
|||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "/frame/pure",
|
path: "/iframe/pure",
|
||||||
name: "reFramePure",
|
name: "reFramePure",
|
||||||
meta: {
|
meta: {
|
||||||
i18n: true,
|
i18n: true,
|
||||||
|
@ -116,7 +116,7 @@
|
|||||||
"stylelint-order": "^5.0.0",
|
"stylelint-order": "^5.0.0",
|
||||||
"typescript": "^4.5.5",
|
"typescript": "^4.5.5",
|
||||||
"unplugin-element-plus": "^0.2.0",
|
"unplugin-element-plus": "^0.2.0",
|
||||||
"vite": "^2.8.5",
|
"vite": "^2.8.6",
|
||||||
"vite-plugin-live-reload": "^2.1.0",
|
"vite-plugin-live-reload": "^2.1.0",
|
||||||
"vite-plugin-mock": "^2.9.6",
|
"vite-plugin-mock": "^2.9.6",
|
||||||
"vite-plugin-remove-console": "^0.0.6",
|
"vite-plugin-remove-console": "^0.0.6",
|
||||||
|
5031
pnpm-lock.yaml
generated
5031
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -126,7 +126,7 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.iconfont {
|
.iconfont {
|
||||||
font-size: 25px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.control-container p {
|
.control-container p {
|
||||||
|
@ -24,6 +24,8 @@ import Location from "@iconify-icons/ep/location";
|
|||||||
import Tickets from "@iconify-icons/ep/tickets";
|
import Tickets from "@iconify-icons/ep/tickets";
|
||||||
import OfficeBuilding from "@iconify-icons/ep/office-building";
|
import OfficeBuilding from "@iconify-icons/ep/office-building";
|
||||||
import Notebook from "@iconify-icons/ep/notebook";
|
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";
|
import Monitor from "@iconify-icons/ep/monitor";
|
||||||
addIcon("check", Check);
|
addIcon("check", Check);
|
||||||
addIcon("menu", Menu);
|
addIcon("menu", Menu);
|
||||||
@ -47,6 +49,8 @@ addIcon("location", Location);
|
|||||||
addIcon("tickets", Tickets);
|
addIcon("tickets", Tickets);
|
||||||
addIcon("office-building", OfficeBuilding);
|
addIcon("office-building", OfficeBuilding);
|
||||||
addIcon("notebook", Notebook);
|
addIcon("notebook", Notebook);
|
||||||
|
addIcon("video-play", videoPlay);
|
||||||
|
addIcon("rank", Rank);
|
||||||
addIcon("monitor", Monitor);
|
addIcon("monitor", Monitor);
|
||||||
|
|
||||||
// remixicon
|
// remixicon
|
||||||
|
@ -55,4 +55,8 @@ onMounted(() => {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.main-content {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -8,7 +8,6 @@ import { useAppStoreHook } from "/@/store/modules/app";
|
|||||||
import { remainingPaths } from "/@/router/modules/index";
|
import { remainingPaths } from "/@/router/modules/index";
|
||||||
import { Title } from "../../../public/serverConfig.json";
|
import { Title } from "../../../public/serverConfig.json";
|
||||||
import { useEpThemeStoreHook } from "/@/store/modules/epTheme";
|
import { useEpThemeStoreHook } from "/@/store/modules/epTheme";
|
||||||
import { remainingPaths } from "/@/router/modules/index";
|
|
||||||
|
|
||||||
export function useNav() {
|
export function useNav() {
|
||||||
const pureApp = useAppStoreHook();
|
const pureApp = useAppStoreHook();
|
||||||
|
@ -44,6 +44,12 @@ import {
|
|||||||
ElCollapse,
|
ElCollapse,
|
||||||
ElCollapseItem,
|
ElCollapseItem,
|
||||||
ElTreeV2,
|
ElTreeV2,
|
||||||
|
ElTable,
|
||||||
|
ElTableColumn,
|
||||||
|
ElLink,
|
||||||
|
ElColorPicker,
|
||||||
|
ElSelect,
|
||||||
|
ElOption,
|
||||||
// 指令
|
// 指令
|
||||||
ElLoading,
|
ElLoading,
|
||||||
ElInfiniteScroll
|
ElInfiniteScroll
|
||||||
@ -96,7 +102,13 @@ const components = [
|
|||||||
ElEmpty,
|
ElEmpty,
|
||||||
ElCollapse,
|
ElCollapse,
|
||||||
ElCollapseItem,
|
ElCollapseItem,
|
||||||
ElTreeV2
|
ElTreeV2,
|
||||||
|
ElTable,
|
||||||
|
ElTableColumn,
|
||||||
|
ElLink,
|
||||||
|
ElColorPicker,
|
||||||
|
ElSelect,
|
||||||
|
ElOption
|
||||||
];
|
];
|
||||||
|
|
||||||
export function useElementPlus(app: App) {
|
export function useElementPlus(app: App) {
|
||||||
|
@ -37,6 +37,7 @@ export default {
|
|||||||
hsAble: "Able",
|
hsAble: "Able",
|
||||||
hsMenuTree: "Menu Tree",
|
hsMenuTree: "Menu Tree",
|
||||||
hsWatermark: "Water Mark",
|
hsWatermark: "Water Mark",
|
||||||
|
hsPrint: "Print",
|
||||||
hsExternalPage: "External Page",
|
hsExternalPage: "External Page",
|
||||||
hsPureDocument: "Pure Document",
|
hsPureDocument: "Pure Document",
|
||||||
hsEpDocument: "Element Plus Document"
|
hsEpDocument: "Element Plus Document"
|
||||||
|
@ -37,6 +37,7 @@ export default {
|
|||||||
hsAble: "功能",
|
hsAble: "功能",
|
||||||
hsMenuTree: "菜单树结构",
|
hsMenuTree: "菜单树结构",
|
||||||
hsWatermark: "水印",
|
hsWatermark: "水印",
|
||||||
|
hsPrint: "打印",
|
||||||
hsExternalPage: "外部页面",
|
hsExternalPage: "外部页面",
|
||||||
hsPureDocument: "平台文档",
|
hsPureDocument: "平台文档",
|
||||||
hsEpDocument: "Element Plus文档"
|
hsEpDocument: "Element Plus文档"
|
||||||
|
@ -30,6 +30,15 @@ const ableRouter = {
|
|||||||
title: $t("menus.hsWatermark"),
|
title: $t("menus.hsWatermark"),
|
||||||
i18n: true
|
i18n: true
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/able/print",
|
||||||
|
name: "rePrint",
|
||||||
|
component: () => import("/@/views/able/print.vue"),
|
||||||
|
meta: {
|
||||||
|
title: $t("menus.hsPrint"),
|
||||||
|
i18n: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
@ -12,8 +12,8 @@ body {
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
text-rendering: optimizelegibility;
|
text-rendering: optimizelegibility;
|
||||||
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB,
|
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB",
|
||||||
Microsoft YaHei, Arial, sans-serif;
|
"Microsoft YaHei", "微软雅黑", Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
|
226
src/utils/print.ts
Normal file
226
src/utils/print.ts
Normal 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;
|
@ -6,31 +6,78 @@ export default {
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed } from "vue";
|
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 { extractPathList, deleteChildren } from "/@/utils/tree";
|
||||||
import { usePermissionStoreHook } from "/@/store/modules/permission";
|
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({
|
let dataProps = ref({
|
||||||
value: "uniqueId",
|
value: "uniqueId",
|
||||||
children: "children"
|
children: "children"
|
||||||
});
|
});
|
||||||
|
const treeRef = ref<InstanceType<typeof ElTreeV2>>();
|
||||||
|
|
||||||
let menusData = computed(() => {
|
let menusData = computed(() => {
|
||||||
return deleteChildren(usePermissionStoreHook().menusTree);
|
return deleteChildren(usePermissionStoreHook().menusTree);
|
||||||
});
|
});
|
||||||
|
|
||||||
let expandedKeys = extractPathList(menusData.value);
|
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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<el-tree-v2
|
<el-card>
|
||||||
:data="menusData"
|
<template #header>
|
||||||
:props="dataProps"
|
<div class="card-header">
|
||||||
show-checkbox
|
<span class="font-medium"
|
||||||
:height="500"
|
>菜单树结构(采用element-plus的
|
||||||
:default-expanded-keys="expandedKeys"
|
<el-link
|
||||||
>
|
href="https://element-plus.gitee.io/zh-CN/component/tree-v2.html"
|
||||||
<template #default="{ data }">
|
target="_blank"
|
||||||
<span>{{ $t(data.meta.title) }}</span>
|
:icon="useRenderIcon('node-tree')"
|
||||||
|
style="font-size: 16px; margin: 0 5px 4px 0"
|
||||||
|
>Tree V2</el-link
|
||||||
|
>组件并支持国际化)</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
</template>
|
</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>
|
</template>
|
||||||
|
329
src/views/able/print.vue
Normal file
329
src/views/able/print.vue
Normal 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>
|
@ -1,13 +1,34 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue";
|
||||||
import { useWatermark } from "/@/utils/watermark";
|
import { useWatermark } from "/@/utils/watermark";
|
||||||
|
|
||||||
|
let color = ref("#409EFF");
|
||||||
|
let value = ref("vue-pure-admin");
|
||||||
const { setWatermark, clear } = useWatermark();
|
const { setWatermark, clear } = useWatermark();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<el-card>
|
||||||
<el-button @click="setWatermark('vue-pure-admin')">创建</el-button>
|
<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>
|
<el-button @click="clear">清除</el-button>
|
||||||
</div>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
@ -7,13 +7,19 @@ const url = ref(`${VITE_PUBLIC_PATH}html/button.html`);
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<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>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.iframe {
|
.iframe {
|
||||||
width: 98%;
|
width: 100%;
|
||||||
height: 90vh;
|
height: 60vh;
|
||||||
border-radius: 6px;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -5,7 +5,12 @@ import menuDynamic from "./menuDynamic.vue";
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<el-card>
|
||||||
|
<template #header>
|
||||||
|
<div class="card-header">
|
||||||
|
<span class="font-medium">右键菜单组件</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
<el-row :gutter="24">
|
<el-row :gutter="24">
|
||||||
<el-col :xs="24" :sm="10" :md="10" :lg="8" :xl="10">
|
<el-col :xs="24" :sm="10" :md="10" :lg="8" :xl="10">
|
||||||
<!-- 基本使用 -->
|
<!-- 基本使用 -->
|
||||||
@ -20,5 +25,5 @@ import menuDynamic from "./menuDynamic.vue";
|
|||||||
<menuDynamic />
|
<menuDynamic />
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
|
@ -3,35 +3,32 @@ import { ReNormalCountTo, ReboundCountTo } from "/@/components/ReCountTo";
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<el-card>
|
||||||
<el-row :gutter="24">
|
<template #header>
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
<div class="card-header">
|
||||||
<el-card shadow="always">
|
<span class="font-medium">数字动画组件</span>
|
||||||
<ReNormalCountTo
|
</div>
|
||||||
prefix="$"
|
</template>
|
||||||
:duration="1000"
|
<div class="flex items-center">
|
||||||
:color="'#409EFF'"
|
<ReNormalCountTo
|
||||||
:fontSize="'2.3em'"
|
prefix="$"
|
||||||
:startVal="1"
|
:duration="1000"
|
||||||
:endVal="1000"
|
:color="'#409EFF'"
|
||||||
/>
|
:fontSize="'2em'"
|
||||||
</el-card>
|
:startVal="1"
|
||||||
</el-col>
|
:endVal="1000"
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
/>
|
||||||
<el-card shadow="always">
|
<ul class="flex ml-8">
|
||||||
<ul class="flex">
|
<ReboundCountTo
|
||||||
<ReboundCountTo
|
v-for="(num, inx) of [1, 6, 6, 6]"
|
||||||
v-for="(num, inx) of [1, 6, 6, 6]"
|
:key="inx"
|
||||||
:key="inx"
|
:i="num"
|
||||||
:i="num"
|
:blur="inx"
|
||||||
:blur="inx"
|
:delay="inx + 1"
|
||||||
:delay="inx + 1"
|
/>
|
||||||
/>
|
</ul>
|
||||||
</ul>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -3,9 +3,9 @@ import { ref, nextTick, getCurrentInstance } from "vue";
|
|||||||
import Cropper from "/@/components/ReCropper";
|
import Cropper from "/@/components/ReCropper";
|
||||||
import img from "./picture.jpeg";
|
import img from "./picture.jpeg";
|
||||||
|
|
||||||
const instance = getCurrentInstance();
|
|
||||||
let info = ref<object>(null);
|
let info = ref<object>(null);
|
||||||
let cropperImg = ref<string>("");
|
let cropperImg = ref<string>("");
|
||||||
|
const instance = getCurrentInstance();
|
||||||
|
|
||||||
const onCropper = (): void => {
|
const onCropper = (): void => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
@ -25,14 +25,19 @@ const onCropper = (): void => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<el-card>
|
||||||
|
<template #header>
|
||||||
|
<div class="card-header">
|
||||||
|
<span class="font-medium">图片裁剪组件</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
<div class="cropper-container">
|
<div class="cropper-container">
|
||||||
<Cropper ref="refCropper" :width="'40vw'" :src="img" />
|
<Cropper ref="refCropper" :width="'40vw'" :src="img" />
|
||||||
<img :src="cropperImg" class="croppered" v-if="cropperImg" />
|
<img :src="cropperImg" class="croppered" v-if="cropperImg" />
|
||||||
</div>
|
</div>
|
||||||
<el-button type="primary" @click="onCropper">裁剪</el-button>
|
<el-button type="primary" @click="onCropper">裁剪</el-button>
|
||||||
<p v-if="cropperImg">裁剪后图片信息:{{ info }}</p>
|
<p v-if="cropperImg">裁剪后图片信息:{{ info }}</p>
|
||||||
</div>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted } from "vue";
|
import { ref, onMounted } from "vue";
|
||||||
import draggable from "vuedraggable/src/vuedraggable";
|
import draggable from "vuedraggable/src/vuedraggable";
|
||||||
|
import { useRenderIcon } from "/@/components/ReIcon/src/hooks";
|
||||||
|
|
||||||
let gridLists = ref<Array<Object>>([
|
let gridLists = ref<Array<Object>>([
|
||||||
{ grid: "cn", num: 1 },
|
{ grid: "cn", num: 1 },
|
||||||
@ -47,77 +48,92 @@ onMounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="drag-container">
|
<el-card>
|
||||||
<!-- grid列表拖拽 -->
|
<template #header>
|
||||||
<el-row :gutter="25">
|
<div class="card-header">
|
||||||
<el-col :xs="25" :sm="8" :md="8" :lg="8">
|
<span
|
||||||
<el-card>
|
>拖拽组件,采用开源的<el-link
|
||||||
<template #header>
|
href="https://sortablejs.github.io/vue.draggable.next/#/simple"
|
||||||
<div class="card-header">
|
target="_blank"
|
||||||
<span>grid列表拖拽</span>
|
:icon="useRenderIcon('rank')"
|
||||||
</div>
|
style="font-size: 16px; margin: 0 4px 5px"
|
||||||
</template>
|
>vuedraggable</el-link
|
||||||
<draggable
|
></span
|
||||||
v-model="gridLists"
|
>
|
||||||
class="grid-container"
|
</div>
|
||||||
item-key="grid"
|
</template>
|
||||||
animation="300"
|
<div class="drag-container">
|
||||||
chosenClass="chosen"
|
<!-- grid列表拖拽 -->
|
||||||
forceFallback="true"
|
<el-row :gutter="25">
|
||||||
>
|
<el-col :xs="25" :sm="8" :md="8" :lg="8">
|
||||||
<template #item="{ element }">
|
<el-card>
|
||||||
<div :class="'item' + ' ' + 'item-' + element.num">
|
<template #header>
|
||||||
{{ element.num }}
|
<div class="card-header">
|
||||||
|
<span>grid列表拖拽</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</draggable>
|
<draggable
|
||||||
</el-card>
|
v-model="gridLists"
|
||||||
</el-col>
|
class="grid-container"
|
||||||
|
item-key="grid"
|
||||||
<el-col :xs="25" :sm="8" :md="8" :lg="8">
|
animation="300"
|
||||||
<el-card>
|
chosenClass="chosen"
|
||||||
<template #header>
|
forceFallback="true"
|
||||||
<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>
|
<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>
|
||||||
</div>
|
</el-card>
|
||||||
</el-card>
|
</el-col>
|
||||||
</el-col>
|
</el-row>
|
||||||
</el-row>
|
</div>
|
||||||
</div>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -16,27 +16,34 @@ const settingTB: ContextProps = reactive({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="split-pane">
|
<el-card>
|
||||||
<splitpane :splitSet="settingLR">
|
<template #header>
|
||||||
<!-- #paneL 表示指定该组件为左侧面板 -->
|
<div class="card-header">
|
||||||
<template #paneL>
|
<span class="font-medium">切割面板组件</span>
|
||||||
<!-- 自定义左侧面板的内容 -->
|
</div>
|
||||||
<div class="dv-a">A</div>
|
</template>
|
||||||
</template>
|
<div class="split-pane">
|
||||||
<!-- #paneR 表示指定该组件为右侧面板 -->
|
<splitpane :splitSet="settingLR">
|
||||||
<template #paneR>
|
<!-- #paneL 表示指定该组件为左侧面板 -->
|
||||||
<!-- 再次将右侧面板进行拆分 -->
|
<template #paneL>
|
||||||
<splitpane :splitSet="settingTB">
|
<!-- 自定义左侧面板的内容 -->
|
||||||
<template #paneL>
|
<div class="dv-a">A</div>
|
||||||
<div class="dv-b">B</div>
|
</template>
|
||||||
</template>
|
<!-- #paneR 表示指定该组件为右侧面板 -->
|
||||||
<template #paneR>
|
<template #paneR>
|
||||||
<div class="dv-c">C</div>
|
<!-- 再次将右侧面板进行拆分 -->
|
||||||
</template>
|
<splitpane :splitSet="settingTB">
|
||||||
</splitpane>
|
<template #paneL>
|
||||||
</template>
|
<div class="dv-b">B</div>
|
||||||
</splitpane>
|
</template>
|
||||||
</div>
|
<template #paneR>
|
||||||
|
<div class="dv-c">C</div>
|
||||||
|
</template>
|
||||||
|
</splitpane>
|
||||||
|
</template>
|
||||||
|
</splitpane>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -2,13 +2,16 @@
|
|||||||
import { onMounted } from "vue";
|
import { onMounted } from "vue";
|
||||||
import Player from "xgplayer/dist/simple_player";
|
import Player from "xgplayer/dist/simple_player";
|
||||||
import volume from "xgplayer/es/controls/volume";
|
import volume from "xgplayer/es/controls/volume";
|
||||||
import playbackRate from "xgplayer/es/controls/playbackRate";
|
|
||||||
import screenShot from "xgplayer/es/controls/screenShot";
|
import screenShot from "xgplayer/es/controls/screenShot";
|
||||||
import { deviceDetection } from "/@/utils/deviceDetection";
|
import { deviceDetection } from "/@/utils/deviceDetection";
|
||||||
|
import playbackRate from "xgplayer/es/controls/playbackRate";
|
||||||
|
import { useRenderIcon } from "/@/components/ReIcon/src/hooks";
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
new Player({
|
new Player({
|
||||||
id: "mse",
|
id: "mse",
|
||||||
|
// 默认静音
|
||||||
|
volume: 0,
|
||||||
autoplay: false,
|
autoplay: false,
|
||||||
screenShot: true,
|
screenShot: true,
|
||||||
url: "https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/mp4/xgplayer-demo-720p.mp4",
|
url: "https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/mp4/xgplayer-demo-720p.mp4",
|
||||||
@ -23,7 +26,22 @@ onMounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<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>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -5,12 +5,12 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, onBeforeUnmount, ref, unref } from "vue";
|
|
||||||
import WangEditor from "wangeditor";
|
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 html = ref(null);
|
||||||
|
const editor = ref(null);
|
||||||
let instance: WangEditor;
|
let instance: WangEditor;
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@ -29,17 +29,26 @@ onBeforeUnmount(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<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 ref="editor"></div>
|
||||||
<div :innerHTML="html"></div>
|
<div :innerHTML="html"></div>
|
||||||
</div>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.main-content {
|
|
||||||
margin: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.w-e-text-container) {
|
:deep(.w-e-text-container) {
|
||||||
z-index: 99 !important;
|
z-index: 99 !important;
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, unref, onMounted } from "vue";
|
import demoData from "./dataTurbo.json";
|
||||||
import LogicFlow from "@logicflow/core";
|
|
||||||
import { Snapshot, BpmnElement, Menu } from "@logicflow/extension";
|
|
||||||
import "@logicflow/core/dist/style/index.css";
|
import "@logicflow/core/dist/style/index.css";
|
||||||
import "@logicflow/extension/lib/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 { Control, NodePanel, DataDialog } from "/@/components/ReFlowChart";
|
||||||
import { toLogicflowData } from "/@/components/ReFlowChart/src/adpterForTurbo";
|
import { toLogicflowData } from "/@/components/ReFlowChart/src/adpterForTurbo";
|
||||||
import { BpmnNode } from "/@/components/ReFlowChart/src/config";
|
|
||||||
import demoData from "./dataTurbo.json";
|
|
||||||
|
|
||||||
let lf = ref(null);
|
let lf = ref(null);
|
||||||
let graphData = ref(null);
|
let graphData = ref(null);
|
||||||
@ -57,37 +59,52 @@ onMounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="logic-flow-view">
|
<el-card>
|
||||||
<!-- 辅助工具栏 -->
|
<template #header>
|
||||||
<Control
|
<div class="card-header">
|
||||||
class="demo-control"
|
<span class="font-medium"
|
||||||
v-if="lf"
|
>流程图组件,采用开源的<el-link
|
||||||
:lf="lf"
|
href="http://logic-flow.org/"
|
||||||
:catTurboData="false"
|
target="_blank"
|
||||||
@catData="catData"
|
:icon="useRenderIcon('set-up')"
|
||||||
></Control>
|
style="font-size: 16px; margin: 0 4px 5px"
|
||||||
<!-- 节点面板 -->
|
>LogicFlow</el-link
|
||||||
<NodePanel :lf="lf" :nodeList="nodeList"></NodePanel>
|
></span
|
||||||
<!-- 画布 -->
|
>
|
||||||
<div id="LF-Turbo"></div>
|
</div>
|
||||||
<!-- 数据查看面板 -->
|
</template>
|
||||||
<el-dialog
|
<div class="logic-flow-view">
|
||||||
customClass="flow-dialog"
|
<!-- 辅助工具栏 -->
|
||||||
title="数据"
|
<Control
|
||||||
v-model="dataVisible"
|
class="demo-control"
|
||||||
width="50%"
|
v-if="lf"
|
||||||
>
|
:lf="lf"
|
||||||
<el-scrollbar>
|
:catTurboData="false"
|
||||||
<DataDialog :graphData="graphData"></DataDialog>
|
@catData="catData"
|
||||||
</el-scrollbar>
|
></Control>
|
||||||
</el-dialog>
|
<!-- 节点面板 -->
|
||||||
</div>
|
<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>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
#LF-Turbo {
|
#LF-Turbo {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: calc(100vh - 90px);
|
height: 70vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logic-flow-view {
|
.logic-flow-view {
|
||||||
@ -137,8 +154,4 @@ onMounted(() => {
|
|||||||
height: 85vh;
|
height: 85vh;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-content {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,14 +1,7 @@
|
|||||||
<script lang="ts">
|
|
||||||
export default {
|
|
||||||
name: "reGuide"
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import Driver from "driver.js";
|
import Driver from "driver.js";
|
||||||
import "driver.js/dist/driver.min.css";
|
import "driver.js/dist/driver.min.css";
|
||||||
|
|
||||||
// 步骤
|
|
||||||
const steps = [
|
const steps = [
|
||||||
{
|
{
|
||||||
element: "#header-notice",
|
element: "#header-notice",
|
||||||
@ -72,8 +65,14 @@ const guide = () => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<el-card>
|
||||||
<p>引导页对于一些第一次进入项目的人很有用,你可以简单介绍下项目的功能</p>
|
<template #header>
|
||||||
|
<div class="card-header">
|
||||||
|
<span class="font-medium"
|
||||||
|
>引导页对于一些第一次进入项目的人很有用,你可以简单介绍下项目的功能</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
style="margin-top: 10px"
|
style="margin-top: 10px"
|
||||||
@ -81,7 +80,7 @@ const guide = () => {
|
|||||||
>
|
>
|
||||||
打开引导页
|
打开引导页
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -20,12 +20,16 @@ function changRole(value) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<el-card>
|
||||||
<el-radio-group v-model="auth" @change="changRole">
|
<template #header>
|
||||||
<el-radio-button label="admin"></el-radio-button>
|
<div class="card-header">
|
||||||
<el-radio-button label="test"></el-radio-button>
|
<el-radio-group v-model="auth" @change="changRole">
|
||||||
</el-radio-group>
|
<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-admin'">只有admin可看</p>
|
||||||
<p v-auth="'v-test'">只有test可看</p>
|
<p v-auth="'v-test'">只有test可看</p>
|
||||||
</div>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
|
@ -29,19 +29,23 @@ function changRole() {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<el-card>
|
||||||
<h4>
|
<template #header>
|
||||||
当前角色:
|
<div class="card-header">
|
||||||
<span style="font-size: 26px">{{ purview }}</span>
|
<span>
|
||||||
<p style="color: #ffa500">
|
当前角色:
|
||||||
查看左侧菜单变化(系统管理),模拟后台根据不同角色返回对应路由
|
<span style="font-size: 26px">{{ purview }}</span>
|
||||||
</p>
|
<p style="color: #ffa500">
|
||||||
</h4>
|
查看左侧菜单变化(系统管理),模拟后台根据不同角色返回对应路由
|
||||||
|
</p></span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="changRole"
|
@click="changRole"
|
||||||
:icon="useRenderIcon('user', { color: '#fff' })"
|
:icon="useRenderIcon('user', { color: '#fff' })"
|
||||||
>切换角色</el-button
|
>切换角色</el-button
|
||||||
>
|
>
|
||||||
</div>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from "vue";
|
|
||||||
import { useRouter, useRoute } from "vue-router";
|
import { useRouter, useRoute } from "vue-router";
|
||||||
import { useMultiTagsStoreHook } from "/@/store/modules/multiTags";
|
import { useMultiTagsStoreHook } from "/@/store/modules/multiTags";
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const activeName = ref("tag");
|
|
||||||
|
|
||||||
function toDetail(index: number) {
|
function toDetail(index: number) {
|
||||||
useMultiTagsStoreHook().handleTags("push", {
|
useMultiTagsStoreHook().handleTags("push", {
|
||||||
@ -25,33 +23,16 @@ function toDetail(index: number) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<el-collapse v-model="activeName" class="tabs-container">
|
<el-card>
|
||||||
<el-collapse-item
|
<template #header>
|
||||||
title="标签页复用超出限制自动关闭(使用场景: 动态路由)"
|
<div class="card-header">
|
||||||
name="tag"
|
<span class="font-medium"
|
||||||
>
|
>标签页复用,超出限制自动关闭(使用场景: 动态路由)</span
|
||||||
<el-button v-for="index in 6" :key="index" @click="toDetail(index)">
|
>
|
||||||
打开{{ index }}详情页
|
</div>
|
||||||
</el-button>
|
</template>
|
||||||
</el-collapse-item>
|
<el-button v-for="index in 6" :key="index" @click="toDetail(index)">
|
||||||
</el-collapse>
|
打开{{ index }}详情页
|
||||||
|
</el-button>
|
||||||
|
</el-card>
|
||||||
</template>
|
</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>
|
|
||||||
|
@ -61,7 +61,7 @@ const openDepot = (): void => {
|
|||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<el-card>
|
<el-card style="height: 360px">
|
||||||
<template #header>
|
<template #header>
|
||||||
<span style="font-size: 16px; font-weight: 500">GitHub信息</span>
|
<span style="font-size: 16px; font-weight: 500">GitHub信息</span>
|
||||||
</template>
|
</template>
|
||||||
@ -93,7 +93,7 @@ const openDepot = (): void => {
|
|||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<el-card>
|
<el-card style="height: 360px">
|
||||||
<template #header>
|
<template #header>
|
||||||
<span style="font-size: 16px; font-weight: 500"
|
<span style="font-size: 16px; font-weight: 500"
|
||||||
>GitHub滚动信息</span
|
>GitHub滚动信息</span
|
||||||
|
Loading…
x
Reference in New Issue
Block a user