This commit is contained in:
2022-12-09 16:41:41 +08:00
parent c1cce5a7c2
commit ff7aa8774f
2003 changed files with 156639 additions and 140 deletions

View File

@@ -0,0 +1,16 @@
<script lang="ts">
export default {
name: "GiftIcon",
};
</script>
<script setup lang="ts">
import LayIcon from "../component/icon/index";
const props = defineProps<{
color?: string;
size?: string;
}>();
</script>
<template>
<lay-icon :color="props.color" :size="props.size" type="layui-icon-gift" />
</template>

View File

@@ -0,0 +1,922 @@
<script lang="ts">
export default {
name: "LayTable",
};
</script>
<script setup lang="ts">
import "./index.less";
import {
ref,
watch,
useSlots,
withDefaults,
onMounted,
StyleValue,
WritableComputedRef,
computed,
onBeforeUnmount,
} from "vue";
import { Recordable } from "../../types";
import LayCheckbox from "../checkbox/index.vue";
import LayDropdown from "../dropdown/index.vue";
import LayEmpty from "../empty/index.vue";
import TableRow from "./TableRow.vue";
import TablePage from "./TablePage.vue";
import { nextTick } from "vue";
export interface TableProps {
id?: string;
skin?: string;
size?: string;
page?: Recordable;
columns: Recordable[];
dataSource: Recordable[];
defaultToolbar?: boolean | Recordable[];
selectedKey?: string;
selectedKeys?: Recordable[];
indentSize?: number;
childrenColumnName?: string;
height?: number;
maxHeight?: string;
even?: boolean;
expandIndex?: number;
rowClassName?: string | Function;
cellClassName?: string | Function;
rowStyle?: string | Function;
cellStyle?: string | Function;
spanMethod?: Function;
defaultExpandAll?: boolean;
expandKeys?: Recordable[];
loading?: boolean;
getCheckboxProps?: Function;
getRadioProps?: Function;
}
const props = withDefaults(defineProps<TableProps>(), {
id: "id",
size: "md",
indentSize: 30,
childrenColumnName: "children",
dataSource: () => [],
selectedKeys: () => [],
selectedKey: "",
maxHeight: "auto",
even: false,
rowClassName: "",
cellClassName: "",
expandIndex: 0,
rowStyle: "",
cellStyle: "",
defaultExpandAll: false,
spanMethod: () => {},
expandKeys: () => [],
loading: false,
getCheckboxProps: () => {},
getRadioProps: () => {},
});
const emit = defineEmits([
"change",
"update:expandKeys",
"update:selectedKeys",
"update:selectedKey",
"row-contextmenu",
"row-double",
"row",
]);
const slot = useSlots();
const slots = slot.default && slot.default();
const tableRef = ref();
const s = "";
const allChecked = ref(false);
const hasChecked = ref(false);
const tableDataSource = ref<any[]>([...props.dataSource]);
const tableColumns = computed(() => {
return [...props.columns];
});
const tableHeadColumns = ref<any[]>([]);
const tableBodyColumns = ref<any[]>([]);
/**
* 获取数组深度
*
* @param arr 数组
*/
const getLevel = (arr: any[]) => {
let maxLevel = 0;
(function callBack(arr, level) {
++level;
maxLevel = Math.max(level, maxLevel);
for (let i = 0; i < arr.length; i++) {
let item = arr[i];
if (item.children && item.children.length > 0) {
callBack(item.children, level);
} else {
delete item.children;
}
}
})(arr, 0);
return maxLevel;
};
/**
* 获取叶节点的数量
*
* @param json 当前节点
*/
function getLeafCountTree(json: any) {
if (!json.children || json.children.length == 0) {
json.colspan = 1;
return 1;
} else {
var leafCount = 0;
for (var i = 0; i < json.children.length; i++) {
leafCount = leafCount + getLeafCountTree(json.children[i]);
}
json.colspan = leafCount;
return leafCount;
}
}
/**
* 计算内容列
*
* @param columns 原始列
*/
const findFindNode = (columns: any[]) => {
columns.forEach((column) => {
if (column.children) {
findFindNode(column.children);
} else {
tableBodyColumns.value.push(column);
}
});
};
findFindNode(tableColumns.value);
/**
* 计算显示列
*
* @param columns 原始列
*/
const tableColumnKeys = ref<any[]>([]);
const findFindNodes = (columns: any[]) => {
columns.forEach((column) => {
if (column.children) {
tableColumnKeys.value.push(column.key);
findFindNodes(column.children);
} else {
if (!column.hide) {
tableColumnKeys.value.push(column.key);
}
}
});
};
findFindNodes(tableColumns.value);
/**
* 计算数组差异
*
* @param arr1 数组
* @param arr2 数组
*/
function diff(arr1: any[], arr2: any[]) {
var newArr = [];
arr1 = Array.from(new Set(arr1)); // 去重
arr2 = Array.from(new Set(arr2)); // 去重
newArr = arr1.concat(arr2);
return newArr.filter((x) => !(arr1.includes(x) && arr2.includes(x)));
}
/**
* 计算标题列
*
* @param level 层级, 用于决定会被 push 到的目标数组
*/
const findFinalNode = (level: number, columns: any[]) => {
columns.forEach((column) => {
if (column.children) {
const colSpan = getLeafCountTree(column);
column.colspan = colSpan;
if (!tableHeadColumns.value[level]) {
tableHeadColumns.value[level] = [];
}
// 如果列固定,并且 width 不存在, 设置默认值
if (column.fixed && !column.width) {
column.type ? (column.width = "50px") : (column.width = "100px");
}
tableHeadColumns.value[level].push(column);
findFinalNode(level + 1, column.children);
} else {
const rowSpan = getLevel(columns);
column.rowspan = rowSpan;
if (!tableHeadColumns.value[level]) {
tableHeadColumns.value[level] = [];
}
// 如果列固定,并且 width 不存在, 设置默认值
if (column.fixed && !column.width) {
column.type ? (column.width = "50px") : (column.width = "100px");
}
tableHeadColumns.value[level].push(column);
}
});
};
findFinalNode(0, tableColumns.value);
const tableSelectedKeys = ref<Recordable[]>([...props.selectedKeys]);
const tableExpandKeys = ref<Recordable[]>([...props.expandKeys]);
watch(
() => props.selectedKeys,
() => {
tableSelectedKeys.value = props.selectedKeys;
},
{ deep: true }
);
watch(
() => props.expandKeys,
() => {
tableExpandKeys.value = props.expandKeys;
},
{ deep: true }
);
const tableSelectedKey: WritableComputedRef<string> = computed({
get() {
return props.selectedKey;
},
set(val) {
emit("update:selectedKey", val);
},
});
watch(
() => props.dataSource,
() => {
tableDataSource.value = [...props.dataSource];
tableSelectedKeys.value = [];
tableSelectedKey.value = s;
},
{ deep: true }
);
const changeAll = (isChecked: boolean) => {
if (isChecked) {
const datasources = props.dataSource.filter((item: any, index: number) => {
return !props.getCheckboxProps(item, index)?.disabled;
});
const ids = datasources.map((item) => {
return item[props.id];
});
tableSelectedKeys.value = [...ids];
} else {
tableSelectedKeys.value = [];
}
};
watch(
tableSelectedKeys,
() => {
if (tableSelectedKeys.value.length === props.dataSource.length) {
allChecked.value = true;
} else {
allChecked.value = false;
}
if (tableSelectedKeys.value.length > 0) {
hasChecked.value = true;
} else {
hasChecked.value = false;
}
emit("update:selectedKeys", tableSelectedKeys.value);
},
{ deep: true, immediate: true }
);
watch(
tableExpandKeys,
() => {
emit("update:expandKeys", tableExpandKeys.value);
},
{ deep: true, immediate: true }
);
const change = function (page: any) {
emit("change", page);
};
const rowClick = function (data: any, evt: MouseEvent) {
emit("row", data, evt);
};
const rowDoubleClick = function (data: any, evt: MouseEvent) {
emit("row-double", data, evt);
};
const rowContextmenu = (data: any, evt: MouseEvent) => {
emit("row-contextmenu", data, evt);
};
// 页面打印
const print = () => {
let subOutputRankPrint = tableRef.value as HTMLElement;
let newContent = subOutputRankPrint.innerHTML;
let oldContent = document.body.innerHTML;
document.body.innerHTML = newContent;
window.print();
window.location.reload();
document.body.innerHTML = oldContent;
};
// 报表导出
const exportData = () => {
var tableStr = ``;
for (let tableHeadColumn of tableHeadColumns.value) {
tableStr += "<tr>";
for (let column of tableHeadColumn) {
tableStr += `<td colspan=${column.colspan} rowspan=${column.rowspan}>${column.title}</td>`;
}
tableStr += "</tr>";
}
tableDataSource.value.forEach((item, rowIndex) => {
tableStr += "<tr>";
tableBodyColumns.value.forEach((tableColumn, columnIndex) => {
Object.keys(item).forEach((name) => {
if (tableColumn.key === name) {
const rowColSpan = props.spanMethod(
item,
tableColumn,
rowIndex,
columnIndex
);
const rowspan = rowColSpan ? rowColSpan[0] : 1;
const colspan = rowColSpan ? rowColSpan[1] : 1;
if (rowspan != 0 && colspan != 0) {
tableStr += `<td colspan=${colspan} rowspan=${rowspan}>${item[name]}</td>`;
}
}
});
});
tableStr += "</tr>";
});
var worksheet = "Sheet1";
var uri = "data:application/vnd.ms-excel;base64,";
var exportTemplate = `<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns="http://www.w3.org/TR/REC-html40">
<head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet>
<x:Name>${worksheet}</x:Name>
<x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet>
</x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]-->
</head>
<body>
<table syle="table-layout: fixed;word-wrap: break-word; word-break: break-all;">${tableStr}</table>
</body>
</html>`;
window.location.href = uri + base64(exportTemplate);
return;
};
// BASE64编码
function base64(s: string) {
return window.btoa(unescape(encodeURIComponent(s)));
}
// 列排序
const sortTable = (e: any, key: string, sort: string) => {
let currentSort = e.target.parentNode.getAttribute("lay-sort");
if (sort === "desc") {
if (currentSort === sort) {
e.target.parentNode.setAttribute("lay-sort", "");
tableDataSource.value = [...props.dataSource];
} else {
e.target.parentNode.setAttribute("lay-sort", "desc");
tableDataSource.value.sort((x, y) => {
if (x[key] < y[key]) return 1;
else if (x[key] > y[key]) return -1;
else return 0;
});
}
} else {
if (currentSort === sort) {
e.target.parentNode.setAttribute("lay-sort", "");
tableDataSource.value = [...props.dataSource];
} else {
e.target.parentNode.setAttribute("lay-sort", "asc");
tableDataSource.value.sort((x, y) => {
if (x[key] < y[key]) return -1;
else if (x[key] > y[key]) return 1;
else return 0;
});
}
}
};
let tableBody = ref<HTMLElement | null>(null);
let tableHeader = ref<HTMLElement | null>(null);
let tableHeaderTable = ref<HTMLElement | null>(null);
const tableBodyEmptyWidth = ref();
let scrollWidthCell = ref(0);
const getScrollWidth = () => {
const clientWidth: number = tableBody.value?.clientWidth || 0;
const offsetWidth: number = tableBody.value?.offsetWidth || 0;
if (clientWidth < offsetWidth) {
scrollWidthCell.value = offsetWidth - clientWidth;
} else {
scrollWidthCell.value = 0;
}
tableBodyEmptyWidth.value = tableHeaderTable.value?.offsetWidth + "px";
};
const hasl = ref(false);
const hasr = ref(false);
const classes = computed(() => {
return [
hasl.value ? "layui-table-has-fixed-left" : "",
hasr.value ? "layui-table-has-fixed-right" : "",
];
});
watch(
() => [props.height, props.maxHeight, props.dataSource],
() => {
nextTick(() => {
getScrollWidth();
});
}
);
onMounted(() => {
getScrollWidth();
getFixedColumn();
tableBody.value?.addEventListener("scroll", () => {
getFixedColumn();
});
tableBody.value?.addEventListener("transitionend", () => {
getScrollWidth();
});
window.onresize = () => {
getScrollWidth();
getFixedColumn();
};
});
const getFixedColumn = () => {
tableHeader.value!.scrollLeft = tableBody.value?.scrollLeft || 0;
// @ts-ignore
if (tableBody.value?.scrollWidth > tableBody.value?.clientWidth) {
if (tableBody.value?.scrollLeft == 0) {
hasl.value = false;
hasr.value = true;
} else {
// @ts-ignore
const t = tableBody.value?.scrollLeft + tableBody.value?.offsetWidth + 2;
const s = tableBody.value?.scrollWidth;
// @ts-ignore
if (t > s) {
hasl.value = true;
hasr.value = false;
} else {
hasl.value = true;
hasr.value = true;
}
}
} else {
hasl.value = false;
hasr.value = false;
}
};
const slotsData = ref<string[]>([]);
props.columns.map((value: any) => {
if (value.customSlot) {
slotsData.value.push(value.customSlot);
}
});
const currentIndentSize = ref(0);
const childrenExpandSpace = computed(() => {
return (
props.dataSource.find((value: any) => {
if (value[props.childrenColumnName]) {
return true;
}
}) != undefined
);
});
/**
* @remark 排除 hide 列
*/
const renderFixedStyle = (column: any, columnIndex: number) => {
if (column.fixed) {
if (column.fixed == "left") {
var left = 0;
for (var i = 0; i < columnIndex; i++) {
if (
props.columns[i].fixed &&
props.columns[i].fixed == "left" &&
tableColumnKeys.value.includes(props.columns[i].key)
) {
left = left + Number(props.columns[i]?.width?.replace("px", ""));
}
}
return { left: `${left}px` } as StyleValue;
} else {
var right = 0;
for (var i = columnIndex + 1; i < props.columns.length; i++) {
if (
props.columns[i].fixed &&
props.columns[i].fixed == "right" &&
tableColumnKeys.value.includes(props.columns[i].key)
) {
right = right + Number(props.columns[i]?.width?.replace("px", ""));
}
}
return { right: `${right}px` } as StyleValue;
}
} else {
var isLast = true;
for (var i = columnIndex + 1; i < props.columns.length; i++) {
if (
props.columns[i].fixed == undefined &&
tableColumnKeys.value.includes(props.columns[i].key)
) {
isLast = false;
}
}
return isLast ? ({ "border-right": "none" } as StyleValue) : {};
}
return {} as StyleValue;
};
/**
* @remark 排除 hide 列
*/
const renderFixedClassName = (column: any, columnIndex: number) => {
if (column.fixed) {
if (column.fixed == "left") {
var left = true;
for (var i = columnIndex + 1; i < props.columns.length; i++) {
if (
props.columns[i].fixed &&
props.columns[i].fixed == "left" &&
tableColumnKeys.value.includes(props.columns[i].key)
) {
left = false;
}
}
return left ? `layui-table-fixed-left-last` : "";
} else {
var right = true;
for (var i = 0; i < columnIndex; i++) {
if (
props.columns[i].fixed &&
props.columns[i].fixed == "right" &&
tableColumnKeys.value.includes(props.columns[i].key)
) {
right = false;
}
}
return right ? `layui-table-fixed-right-first` : "";
}
}
};
const hasTotalRow = computed(() => {
let b = false;
props.columns.forEach((item) => {
if (item.totalRow) {
b = true;
}
});
return b;
});
const renderTotalRowCell = (column: any) => {
if (column.totalRow) {
if (column.totalRow != true) {
return column.totalRow;
} else {
if (column.totalRowMethod) {
return column.totalRowMethod(column, tableDataSource.value);
} else {
return totalRowMethod(column, tableDataSource.value);
}
}
}
};
const totalRowMethod = (column: any, dataSource: any[]) => {
let total = 0;
dataSource.forEach((item) => {
total = total + Number(item[column.key]);
});
return total;
};
onBeforeUnmount(() => {
window.onresize = null;
});
</script>
<template>
<div ref="tableRef">
<table class="layui-hide" lay-filter="test"></table>
<div class="layui-form layui-border-box layui-table-view" :class="classes">
<div v-if="defaultToolbar || slot.toolbar" class="layui-table-tool">
<div class="layui-table-tool-temp">
<slot name="toolbar"></slot>
</div>
<div v-if="defaultToolbar" class="layui-table-tool-self">
<lay-dropdown updateAtScroll>
<div class="layui-inline" title="筛选" lay-event>
<i class="layui-icon layui-icon-slider"></i>
</div>
<template #content>
<div class="layui-table-tool-checkbox">
<lay-checkbox
v-for="column in tableHeadColumns[0]"
v-model="tableColumnKeys"
skin="primary"
:disabled="column.children"
:key="column.key"
:value="column.key"
>{{ column.title }}</lay-checkbox
>
</div>
</template>
</lay-dropdown>
<div
class="layui-inline"
title="导出"
lay-event
@click="exportData()"
>
<i class="layui-icon layui-icon-export"></i>
</div>
<div class="layui-inline" title="打印" lay-event @click="print()">
<i class="layui-icon layui-icon-print"></i>
</div>
</div>
</div>
<div class="layui-table-box-header" v-if="slot.header">
<slot name="header"></slot>
</div>
<div class="layui-table-box">
<!-- 表头 -->
<div
class="layui-table-header"
:style="[{ 'padding-right': `${scrollWidthCell}px` }]"
>
<div class="layui-table-header-wrapper" ref="tableHeader">
<table
class="layui-table"
:lay-size="size"
:lay-skin="skin"
ref="tableHeaderTable"
>
<colgroup>
<template v-for="column in tableBodyColumns" :key="column">
<template v-if="tableColumnKeys.includes(column.key)">
<col
:width="column.width"
:style="{
minWidth: column.minWidth ? column.minWidth : '50px',
}"
/>
</template>
</template>
</colgroup>
<thead>
<template
v-for="(
tableHeadColumn, tableHeadColumnIndex
) in tableHeadColumns"
:key="tableHeadColumnIndex"
>
<tr>
<template
v-for="(column, columnIndex) in tableHeadColumn"
:key="column"
>
<th
v-if="tableColumnKeys.includes(column.key)"
:colspan="column.colspan"
:rowspan="column.rowspan"
class="layui-table-cell"
:class="[
renderFixedClassName(column, columnIndex),
column.fixed
? `layui-table-fixed-${column.fixed}`
: '',
column.type == 'checkbox'
? 'layui-table-cell-checkbox'
: '',
column.type == 'radio'
? 'layui-table-cell-radio'
: '',
column.type == 'number'
? 'layui-table-cell-number'
: '',
]"
:style="[
{
textAlign: column.align,
},
renderFixedStyle(column, columnIndex),
]"
>
<template v-if="column.type == 'checkbox'">
<lay-checkbox
v-model="hasChecked"
:is-indeterminate="!allChecked"
skin="primary"
value="all"
@change="changeAll"
/>
</template>
<template v-else>
<span>
<template v-if="column.titleSlot">
<slot :name="column.titleSlot"></slot>
</template>
<template v-else>
{{ column.title }}
</template>
</span>
<!-- 插槽 -->
<span
v-if="column.sort"
class="layui-table-sort layui-inline"
lay-sort
>
<i
@click.stop="sortTable($event, column.key, 'asc')"
class="layui-edge layui-table-sort-asc"
title="升序"
></i>
<i
@click.stop="
sortTable($event, column.key, 'desc')
"
class="layui-edge layui-table-sort-desc"
title="降序"
></i>
</span>
</template>
</th>
</template>
</tr>
</template>
</thead>
</table>
</div>
</div>
<!-- 表身 -->
<div
class="layui-table-body layui-table-main"
:style="{ height: height, maxHeight: maxHeight }"
ref="tableBody"
>
<table
class="layui-table"
v-if="tableDataSource.length > 0 && loading == false"
:class="{ 'layui-table-even': props.even }"
:lay-size="size"
:lay-skin="skin"
>
<colgroup>
<template
v-for="(column, columnIndex) in tableBodyColumns"
:key="columnIndex"
>
<template v-if="tableColumnKeys.includes(column.key)">
<col
:width="column.width"
:style="{
minWidth: column.minWidth ? column.minWidth : '50px',
}"
/>
</template>
</template>
</colgroup>
<tbody>
<!-- 渲染 -->
<template
v-for="(children, index) in tableDataSource"
:key="index"
>
<table-row
:id="id"
:index="index"
:data="children"
:columns="tableBodyColumns"
:indent-size="indentSize"
:currentIndentSize="currentIndentSize"
:tableColumnKeys="tableColumnKeys"
:expandSpace="childrenExpandSpace"
:expandIndex="expandIndex"
:cellStyle="cellStyle"
:cellClassName="cellClassName"
:rowStyle="rowStyle"
:rowClassName="rowClassName"
:spanMethod="spanMethod"
:defaultExpandAll="defaultExpandAll"
:getCheckboxProps="getCheckboxProps"
:getRadioProps="getRadioProps"
v-model:expandKeys="tableExpandKeys"
v-model:selectedKeys="tableSelectedKeys"
v-model:selectedKey="tableSelectedKey"
@row="rowClick"
@row-double="rowDoubleClick"
@row-contextmenu="rowContextmenu"
>
<template v-for="name in slotsData" #[name]="{ data }">
<slot :name="name" :data="data"></slot>
</template>
<template v-if="slot.expand" #expand="{ data }">
<slot name="expand" :data="data"></slot>
</template>
</table-row>
</template>
<tr v-if="hasTotalRow" class="layui-table-total">
<template
v-for="(column, columnIndex) in columns"
:key="columnIndex"
>
<template v-if="tableColumnKeys.includes(column.key)">
<td
:style="[
{
textAlign: column.align,
whiteSpace: column.ellipsisTooltip
? 'nowrap'
: 'normal',
},
renderFixedStyle(column, columnIndex),
]"
:class="[
'layui-table-cell',
renderFixedClassName(column, columnIndex),
column.fixed ? `layui-table-fixed-${column.fixed}` : '',
]"
v-html="renderTotalRowCell(column)"
></td>
</template>
</template>
</tr>
</tbody>
</table>
<template v-if="tableDataSource.length == 0 && loading == false">
<lay-empty></lay-empty>
<div :style="{ width: tableBodyEmptyWidth }"></div>
</template>
<template v-if="loading == true">
<div class="layui-table-loading">
<i
class="layui-icon-loading layui-icon layui-anim layui-anim-rotate layui-anim-loop"
></i>
</div>
</template>
</div>
<div class="layui-table-footer" v-if="slot.footer">
<slot name="footer"></slot>
</div>
</div>
<div v-if="page && page.total > 0" class="layui-table-page">
<table-page
:total="page.total"
:pages="page.pages"
:theme="page.theme"
:limits="page.limits"
:showSkip="page.showSkip"
:show-page="page.showPage"
:showRefresh="page.showRefresh"
:showLimit="page.showLimit"
:showCount="page.showCount"
:count="page.count"
v-model:current="page.current"
v-model:limit="page.limit"
@change="change"
>
</table-page>
</div>
</div>
</div>
</template>

View File

@@ -0,0 +1,79 @@
## Introduction
<p>
<a href="https://www.npmjs.com/package/@layui/icons-vue"><img src="https://img.shields.io/npm/v/@layui/icons-vue.svg?sanitize=true" alt="Version"></a>
<a href="https://www.npmjs.com/package/@layui/icon-vue"><img src="https://img.shields.io/npm/l/@layui/icons-vue.svg?sanitize=true" alt="License"></a>
<a href="https://travis-ci.org/sentsin/layui"><img alt="Build Status" src="https://img.shields.io/travis/sentsin/layui/master.svg"></a>
<a href="https://coveralls.io/r/sentsin/layui?branch=master"><img alt="Test Coverage" src="https://img.shields.io/coveralls/sentsin/layui/master.svg"></a>
</p>
**[🔶 Explore the docs »](http://www.layui-vue.com)** **[Join us](https://jq.qq.com/?_wv=1027&k=ffiUQgnE)**
The abstract trees of the layui iconfont icons.
## Get Started
Use npm to install.
```bash
npm i @layui/icons-vue
```
Font icon files need to be introduced before use
```
import "@layui/icons-vue/lib/index.css"
```
Componentization, using the class of iconfont as the component name.
```
<template>
<AlignCenterIcon></AlignCenterIcon>
<DiamondIcon></DiamondIcon>
</template>
<script lang="ts" setup>
import { AlignCenterIcon, DiamondIcon } from '@layui/icons-vue';
</script>
```
Traditionally, components are rendered by passing class through type.
```
<template>
<!-- 动态图标 -->
<LayIcon type="layui-icon-not-found"></LayIcon>
<LayIcon type="layui-icon-diamond"></LayIcon>
</template>
<script lang="ts" setup>
import { LayIcon } from '@layui/icons-vue';
</script>
```
## Open Source Licence
layui vue is licensed under the [MIT license](https://opensource.org/licenses/MIT).
```
The MIT License (MIT)
Copyright 2021 就眠儀式
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
```

View File

@@ -0,0 +1,899 @@
.markdown-body {
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
margin: 0;
color: #24292f;
background-color: #ffffff;
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";
font-size: 16px;
line-height: 1.5;
word-wrap: break-word;
}
.markdown-body .octicon {
display: inline-block;
fill: currentColor;
vertical-align: text-bottom;
}
.markdown-body h1:hover .anchor .octicon-link:before,
.markdown-body h2:hover .anchor .octicon-link:before,
.markdown-body h3:hover .anchor .octicon-link:before,
.markdown-body h4:hover .anchor .octicon-link:before,
.markdown-body h5:hover .anchor .octicon-link:before,
.markdown-body h6:hover .anchor .octicon-link:before {
width: 16px;
height: 16px;
content: ' ';
display: inline-block;
background-color: currentColor;
-webkit-mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' version='1.1' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg>");
mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' version='1.1' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg>");
}
.markdown-body details,
.markdown-body figcaption,
.markdown-body figure {
display: block;
}
.markdown-body summary {
display: list-item;
}
.markdown-body [hidden] {
display: none !important;
}
.markdown-body a {
background-color: transparent;
color: #0969da;
text-decoration: none;
}
.markdown-body a:active,
.markdown-body a:hover {
outline-width: 0;
}
.markdown-body abbr[title] {
border-bottom: none;
text-decoration: underline dotted;
}
.markdown-body b,
.markdown-body strong {
font-weight: 600;
}
.markdown-body dfn {
font-style: italic;
}
.markdown-body h1 {
margin: .67em 0;
font-weight: 600;
padding-bottom: .3em;
font-size: 2em;
border-bottom: 1px solid hsla(210,18%,87%,1);
}
.markdown-body mark {
background-color: #fff8c5;
color: #24292f;
}
.markdown-body small {
font-size: 90%;
}
.markdown-body sub,
.markdown-body sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
.markdown-body sub {
bottom: -0.25em;
}
.markdown-body sup {
top: -0.5em;
}
.markdown-body img {
border-style: none;
max-width: 100%;
box-sizing: content-box;
background-color: #ffffff;
}
.markdown-body code,
.markdown-body kbd,
.markdown-body pre,
.markdown-body samp {
font-family: monospace,monospace;
font-size: 1em;
}
.markdown-body figure {
margin: 1em 40px;
}
.markdown-body hr {
box-sizing: content-box;
overflow: hidden;
background: transparent;
border-bottom: 1px solid hsla(210,18%,87%,1);
height: .25em;
padding: 0;
margin: 24px 0;
background-color: #d0d7de;
border: 0;
}
.markdown-body [type=button],
.markdown-body [type=reset],
.markdown-body [type=submit] {
-webkit-appearance: button;
}
.markdown-body [type=button]::-moz-focus-inner,
.markdown-body [type=reset]::-moz-focus-inner,
.markdown-body [type=submit]::-moz-focus-inner {
border-style: none;
padding: 0;
}
.markdown-body [type=button]:-moz-focusring,
.markdown-body [type=reset]:-moz-focusring,
.markdown-body [type=submit]:-moz-focusring {
outline: 1px dotted ButtonText;
}
.markdown-body [type=checkbox],
.markdown-body [type=radio] {
box-sizing: border-box;
padding: 0;
}
.markdown-body [type=number]::-webkit-inner-spin-button,
.markdown-body [type=number]::-webkit-outer-spin-button {
height: auto;
}
.markdown-body [type=search] {
-webkit-appearance: textfield;
outline-offset: -2px;
}
.markdown-body [type=search]::-webkit-search-cancel-button,
.markdown-body [type=search]::-webkit-search-decoration {
-webkit-appearance: none;
}
.markdown-body ::-webkit-input-placeholder {
color: inherit;
opacity: .54;
}
.markdown-body ::-webkit-file-upload-button {
-webkit-appearance: button;
font: inherit;
}
.markdown-body a:hover {
text-decoration: underline;
}
.markdown-body hr::before {
display: table;
content: "";
}
.markdown-body hr::after {
display: table;
clear: both;
content: "";
}
.markdown-body td,
.markdown-body th {
padding: 0;
}
.markdown-body details summary {
cursor: pointer;
}
.markdown-body details:not([open])>*:not(summary) {
display: none !important;
}
.markdown-body kbd {
display: inline-block;
padding: 3px 5px;
font: 11px ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;
line-height: 10px;
color: #24292f;
vertical-align: middle;
background-color: #f6f8fa;
border: solid 1px rgba(175,184,193,0.2);
border-bottom-color: rgba(175,184,193,0.2);
border-radius: 6px;
box-shadow: inset 0 -1px 0 rgba(175,184,193,0.2);
}
.markdown-body h1,
.markdown-body h2,
.markdown-body h3,
.markdown-body h4,
.markdown-body h5,
.markdown-body h6 {
margin-top: 24px;
margin-bottom: 16px;
font-weight: 600;
line-height: 1.25;
}
.markdown-body h2 {
font-weight: 600;
padding-bottom: .3em;
font-size: 1.5em;
border-bottom: 1px solid hsla(210,18%,87%,1);
}
.markdown-body h3 {
font-weight: 600;
font-size: 1.25em;
}
.markdown-body h4 {
font-weight: 600;
font-size: 1em;
}
.markdown-body h5 {
font-weight: 600;
font-size: .875em;
}
.markdown-body h6 {
font-weight: 600;
font-size: .85em;
color: #57606a;
}
.markdown-body p {
margin-top: 15;
margin-bottom: 15px;
font-size: 14px;
}
.markdown-body blockquote {
margin: 0;
padding: 0 1em;
color: #57606a;
border-left: .25em solid #d0d7de;
}
.markdown-body ul,
.markdown-body ol {
margin-top: 0;
margin-bottom: 0;
padding-left: 2em;
}
.markdown-body ol ol,
.markdown-body ul ol {
list-style-type: lower-roman;
}
.markdown-body ul ul ol,
.markdown-body ul ol ol,
.markdown-body ol ul ol,
.markdown-body ol ol ol {
list-style-type: lower-alpha;
}
.markdown-body dd {
margin-left: 0;
}
.markdown-body tt,
.markdown-body code {
font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;
font-size: 12px;
}
.markdown-body pre {
margin-top: 0;
margin-bottom: 0;
font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;
font-size: 12px;
word-wrap: normal;
}
.markdown-body .octicon {
display: inline-block;
overflow: visible !important;
vertical-align: text-bottom;
fill: currentColor;
}
.markdown-body ::placeholder {
color: #6e7781;
opacity: 1;
}
.markdown-body input::-webkit-outer-spin-button,
.markdown-body input::-webkit-inner-spin-button {
margin: 0;
-webkit-appearance: none;
appearance: none;
}
.markdown-body .pl-c {
color: #6e7781;
}
.markdown-body .pl-c1,
.markdown-body .pl-s .pl-v {
color: #0550ae;
}
.markdown-body .pl-e,
.markdown-body .pl-en {
color: #8250df;
}
.markdown-body .pl-smi,
.markdown-body .pl-s .pl-s1 {
color: #24292f;
}
.markdown-body .pl-ent {
color: #116329;
}
.markdown-body .pl-k {
color: #cf222e;
}
.markdown-body .pl-s,
.markdown-body .pl-pds,
.markdown-body .pl-s .pl-pse .pl-s1,
.markdown-body .pl-sr,
.markdown-body .pl-sr .pl-cce,
.markdown-body .pl-sr .pl-sre,
.markdown-body .pl-sr .pl-sra {
color: #0a3069;
}
.markdown-body .pl-v,
.markdown-body .pl-smw {
color: #953800;
}
.markdown-body .pl-bu {
color: #82071e;
}
.markdown-body .pl-ii {
color: #f6f8fa;
background-color: #82071e;
}
.markdown-body .pl-c2 {
color: #f6f8fa;
background-color: #cf222e;
}
.markdown-body .pl-sr .pl-cce {
font-weight: bold;
color: #116329;
}
.markdown-body .pl-ml {
color: #3b2300;
}
.markdown-body .pl-mh,
.markdown-body .pl-mh .pl-en,
.markdown-body .pl-ms {
font-weight: bold;
color: #0550ae;
}
.markdown-body .pl-mi {
font-style: italic;
color: #24292f;
}
.markdown-body .pl-mb {
font-weight: bold;
color: #24292f;
}
.markdown-body .pl-md {
color: #82071e;
background-color: #FFEBE9;
}
.markdown-body .pl-mi1 {
color: #116329;
background-color: #dafbe1;
}
.markdown-body .pl-mc {
color: #953800;
background-color: #ffd8b5;
}
.markdown-body .pl-mi2 {
color: #eaeef2;
background-color: #0550ae;
}
.markdown-body .pl-mdr {
font-weight: bold;
color: #8250df;
}
.markdown-body .pl-ba {
color: #57606a;
}
.markdown-body .pl-sg {
color: #8c959f;
}
.markdown-body .pl-corl {
text-decoration: underline;
color: #0a3069;
}
.markdown-body [data-catalyst] {
display: block;
}
.markdown-body g-emoji {
font-family: "Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";
font-size: 1em;
font-style: normal !important;
font-weight: 400;
line-height: 1;
vertical-align: -0.075em;
}
.markdown-body g-emoji img {
width: 1em;
height: 1em;
}
.markdown-body::before {
display: table;
content: "";
}
.markdown-body::after {
display: table;
clear: both;
content: "";
}
.markdown-body>*:first-child {
margin-top: 0 !important;
}
.markdown-body>*:last-child {
margin-bottom: 0 !important;
}
.markdown-body a:not([href]) {
color: inherit;
text-decoration: none;
}
.markdown-body .absent {
color: #cf222e;
}
.markdown-body .anchor {
float: left;
padding-right: 4px;
margin-left: -20px;
line-height: 1;
}
.markdown-body .anchor:focus {
outline: none;
}
.markdown-body p,
.markdown-body blockquote,
.markdown-body ul,
.markdown-body ol,
.markdown-body dl,
.markdown-body pre,
.markdown-body details {
margin-top: 0;
margin-bottom: 16px;
}
.markdown-body blockquote>:first-child {
margin-top: 0;
}
.markdown-body blockquote>:last-child {
margin-bottom: 0;
}
.markdown-body sup>a::before {
content: "[";
}
.markdown-body sup>a::after {
content: "]";
}
.markdown-body h1 .octicon-link,
.markdown-body h2 .octicon-link,
.markdown-body h3 .octicon-link,
.markdown-body h4 .octicon-link,
.markdown-body h5 .octicon-link,
.markdown-body h6 .octicon-link {
color: #24292f;
vertical-align: middle;
visibility: hidden;
}
.markdown-body h1:hover .anchor,
.markdown-body h2:hover .anchor,
.markdown-body h3:hover .anchor,
.markdown-body h4:hover .anchor,
.markdown-body h5:hover .anchor,
.markdown-body h6:hover .anchor {
text-decoration: none;
}
.markdown-body h1:hover .anchor .octicon-link,
.markdown-body h2:hover .anchor .octicon-link,
.markdown-body h3:hover .anchor .octicon-link,
.markdown-body h4:hover .anchor .octicon-link,
.markdown-body h5:hover .anchor .octicon-link,
.markdown-body h6:hover .anchor .octicon-link {
visibility: visible;
}
.markdown-body h1 tt,
.markdown-body h1 code,
.markdown-body h2 tt,
.markdown-body h2 code,
.markdown-body h3 tt,
.markdown-body h3 code,
.markdown-body h4 tt,
.markdown-body h4 code,
.markdown-body h5 tt,
.markdown-body h5 code,
.markdown-body h6 tt,
.markdown-body h6 code {
padding: 0 .2em;
font-size: inherit;
}
.markdown-body ul.no-list,
.markdown-body ol.no-list {
padding: 0;
list-style-type: none;
}
.markdown-body ol[type="1"] {
list-style-type: decimal;
}
.markdown-body ol[type=a] {
list-style-type: lower-alpha;
}
.markdown-body ol[type=i] {
list-style-type: lower-roman;
}
.markdown-body div>ol:not([type]) {
list-style-type: decimal;
}
.markdown-body ul ul,
.markdown-body ul ol,
.markdown-body ol ol,
.markdown-body ol ul {
margin-top: 0;
margin-bottom: 0;
}
.markdown-body li>p {
margin-top: 16px;
}
.markdown-body li+li {
margin-top: .25em;
}
.markdown-body dl {
padding: 0;
}
.markdown-body dl dt {
padding: 0;
margin-top: 16px;
font-size: 1em;
font-style: italic;
font-weight: 600;
}
.markdown-body dl dd {
padding: 0 16px;
margin-bottom: 16px;
}
.markdown-body img[align=right] {
padding-left: 20px;
}
.markdown-body img[align=left] {
padding-right: 20px;
}
.markdown-body .emoji {
max-width: none;
vertical-align: text-top;
background-color: transparent;
}
.markdown-body span.frame {
display: block;
overflow: hidden;
}
.markdown-body span.frame>span {
display: block;
float: left;
width: auto;
padding: 7px;
margin: 13px 0 0;
overflow: hidden;
border: 1px solid #d0d7de;
}
.markdown-body span.frame span img {
display: block;
float: left;
}
.markdown-body span.frame span span {
display: block;
padding: 5px 0 0;
clear: both;
color: #24292f;
}
.markdown-body span.align-center {
display: block;
overflow: hidden;
clear: both;
}
.markdown-body span.align-center>span {
display: block;
margin: 13px auto 0;
overflow: hidden;
text-align: center;
}
.markdown-body span.align-center span img {
margin: 0 auto;
text-align: center;
}
.markdown-body span.align-right {
display: block;
overflow: hidden;
clear: both;
}
.markdown-body span.align-right>span {
display: block;
margin: 13px 0 0;
overflow: hidden;
text-align: right;
}
.markdown-body span.align-right span img {
margin: 0;
text-align: right;
}
.markdown-body span.float-left {
display: block;
float: left;
margin-right: 13px;
overflow: hidden;
}
.markdown-body span.float-left span {
margin: 13px 0 0;
}
.markdown-body span.float-right {
display: block;
float: right;
margin-left: 13px;
overflow: hidden;
}
.markdown-body span.float-right>span {
display: block;
margin: 13px auto 0;
overflow: hidden;
text-align: right;
}
.markdown-body code,
.markdown-body tt {
padding: .2em .4em;
margin: 0;
font-size: 85%;
background-color: rgba(175,184,193,0.2);
border-radius: 6px;
}
.markdown-body code br,
.markdown-body tt br {
display: none;
}
.markdown-body del code {
text-decoration: inherit;
}
.markdown-body pre code {
font-size: 100%;
}
.markdown-body pre>code {
padding: 0;
margin: 0;
word-break: normal;
white-space: pre;
background: transparent;
border: 0;
}
.markdown-body .highlight {
margin-bottom: 16px;
}
.markdown-body .highlight pre {
margin-bottom: 0;
word-break: normal;
}
.markdown-body .highlight pre,
.markdown-body pre {
padding: 16px;
overflow: auto;
font-size: 85%;
line-height: 1.45;
background-color: #f6f8fa;
border-radius: 6px;
}
.markdown-body pre code,
.markdown-body pre tt {
display: inline;
max-width: auto;
padding: 0;
margin: 0;
overflow: visible;
line-height: inherit;
word-wrap: normal;
background-color: transparent;
border: 0;
}
.markdown-body .csv-data td,
.markdown-body .csv-data th {
padding: 5px;
overflow: hidden;
font-size: 12px;
line-height: 1;
text-align: left;
white-space: nowrap;
}
.markdown-body .csv-data .blob-num {
padding: 10px 8px 9px;
text-align: right;
background: #ffffff;
border: 0;
}
.markdown-body .csv-data tr {
border-top: 0;
}
.markdown-body .csv-data th {
font-weight: 600;
background: #f6f8fa;
border-top: 0;
}
.markdown-body .footnotes {
font-size: 12px;
color: #57606a;
border-top: 1px solid #d0d7de;
}
.markdown-body .footnotes ol {
padding-left: 16px;
}
.markdown-body .footnotes li {
position: relative;
}
.markdown-body .footnotes li:target::before {
position: absolute;
top: -8px;
right: -8px;
bottom: -8px;
left: -24px;
pointer-events: none;
content: "";
border: 2px solid #0969da;
border-radius: 6px;
}
.markdown-body .footnotes li:target {
color: #24292f;
}
.markdown-body .footnotes .data-footnote-backref g-emoji {
font-family: monospace;
}
.markdown-body .task-list-item {
list-style-type: none;
}
.markdown-body .task-list-item label {
font-weight: 400;
}
.markdown-body .task-list-item.enabled label {
cursor: pointer;
}
.markdown-body .task-list-item+.task-list-item {
margin-top: 3px;
}
.markdown-body .task-list-item .handle {
display: none;
}
.markdown-body .task-list-item-checkbox {
margin: 0 .2em .25em -1.6em;
vertical-align: middle;
}
.markdown-body .contains-task-list:dir(rtl) .task-list-item-checkbox {
margin: 0 -1.6em .25em .2em;
}
.markdown-body ::-webkit-calendar-picker-indicator {
filter: invert(50%);
}

View File

@@ -0,0 +1,16 @@
<script lang="ts">
export default {
name: "CartIcon",
};
</script>
<script setup lang="ts">
import LayIcon from "../component/icon/index";
const props = defineProps<{
color?: string;
size?: string;
}>();
</script>
<template>
<lay-icon :color="props.color" :size="props.size" type="layui-icon-cart" />
</template>