Merge remote-tracking branch 'origin/main' into gitee

This commit is contained in:
xiaoxian521
2024-01-18 17:50:07 +08:00
57 changed files with 828 additions and 408 deletions

View File

@@ -72,11 +72,11 @@ function onMouseleave() {
<template>
<el-select
class="!w-[200px]"
:model-value="inputValue"
placeholder="请选择动画"
clearable
filterable
placeholder="请选择动画"
popper-class="pure-animate-popper"
:model-value="inputValue"
:filter-method="filterMethod"
@clear="onClear"
>
@@ -121,3 +121,9 @@ function onMouseleave() {
</template>
</el-select>
</template>
<style>
.pure-animate-popper {
min-width: 0 !important;
}
</style>

View File

@@ -129,6 +129,11 @@ export default defineComponent({
onUnmounted(() => {
cropper.value?.destroy();
isReady.value = false;
cropper.value = null;
imgBase64.value = "";
scaleX = 1;
scaleY = 1;
});
useResizeObserver(tippyElRef, () => handCropper("reset"));

View File

@@ -121,7 +121,7 @@ watch(
</script>
<template>
<div class="selector w-[220px]">
<div class="selector">
<el-input v-model="inputValue" disabled>
<template #append>
<el-popover

View File

@@ -423,7 +423,7 @@ function openMenu(tag, e) {
}
currentSelect.value = tag;
const menuMinWidth = 105;
const menuMinWidth = 140;
const offsetLeft = unref(containerDom).getBoundingClientRect().left;
const offsetWidth = unref(containerDom).offsetWidth;
const maxLeft = offsetWidth - menuMinWidth;

View File

@@ -4,11 +4,11 @@ const home = 0, // 平台规定只有 home 路由的 rank 才能为 0 ,所以
able = 1,
components = 2,
table = 3,
frame = 4,
nested = 5,
result = 6,
error = 7,
list = 8,
list = 4,
result = 5,
error = 6,
frame = 7,
nested = 8,
permission = 9,
system = 10,
tabs = 11,
@@ -26,11 +26,11 @@ export {
able,
components,
table,
frame,
nested,
list,
result,
error,
list,
frame,
nested,
permission,
system,
tabs,

View File

@@ -10,30 +10,6 @@ export default {
rank: able
},
children: [
{
path: "/able/videoFrame",
name: "VideoFrame",
component: () => import("@/views/able/video-frame/index.vue"),
meta: {
title: $t("menus.hsVideoFrame")
}
},
{
path: "/able/wavesurfer",
name: "Wavesurfer",
component: () => import("@/views/able/wavesurfer/index.vue"),
meta: {
title: $t("menus.hsWavesurfer")
}
},
{
path: "/able/directives",
name: "Directives",
component: () => import("@/views/able/directives.vue"),
meta: {
title: $t("menus.hsOptimize")
}
},
{
path: "/able/watermark",
name: "WaterMark",
@@ -59,35 +35,11 @@ export default {
}
},
{
path: "/able/iconSelect",
name: "IconSelect",
component: () => import("@/views/able/icon-select.vue"),
path: "/able/excel",
name: "Excel",
component: () => import("@/views/able/excel.vue"),
meta: {
title: $t("menus.hsIconSelect")
}
},
{
path: "/able/timeline",
name: "TimeLine",
component: () => import("@/views/able/timeline.vue"),
meta: {
title: $t("menus.hsTimeline")
}
},
{
path: "/able/menuTree",
name: "MenuTree",
component: () => import("@/views/able/menu-tree.vue"),
meta: {
title: $t("menus.hsMenuTree")
}
},
{
path: "/able/lineTree",
name: "LineTree",
component: () => import("@/views/able/line-tree.vue"),
meta: {
title: $t("menus.hsLineTree")
title: $t("menus.hsExcel")
}
},
{
@@ -98,6 +50,34 @@ export default {
title: $t("menus.hsDebounce")
}
},
{
path: "/able/directives",
name: "Directives",
component: () => import("@/views/able/directives.vue"),
meta: {
title: $t("menus.hsOptimize")
}
},
{
path: "/able/draggable",
name: "Draggable",
component: () => import("@/views/able/draggable.vue"),
meta: {
title: $t("menus.hsdraggable"),
transition: {
enterTransition: "animate__zoomIn",
leaveTransition: "animate__zoomOut"
}
}
},
{
path: "/able/pdf",
name: "Pdf",
component: () => import("@/views/able/pdf.vue"),
meta: {
title: $t("menus.hsPdf")
}
},
{
path: "/able/barcode",
name: "BarCode",
@@ -115,43 +95,47 @@ export default {
}
},
{
path: "/able/cascader",
name: "Cascader",
component: () => import("@/views/able/cascader.vue"),
path: "/able/map",
name: "MapPage",
component: () => import("@/views/able/map.vue"),
meta: {
title: $t("menus.hsCascader")
title: $t("menus.hsmap"),
keepAlive: true,
transition: {
name: "fade"
}
}
},
{
path: "/able/swiper",
name: "Swiper",
component: () => import("@/views/able/swiper.vue"),
path: "/able/wavesurfer",
name: "Wavesurfer",
component: () => import("@/views/able/wavesurfer/index.vue"),
meta: {
title: $t("menus.hsSwiper")
title: $t("menus.hsWavesurfer")
}
},
{
path: "/able/virtualList",
name: "VirtualList",
component: () => import("@/views/able/virtual-list/index.vue"),
path: "/able/video",
name: "VideoPage",
component: () => import("@/views/able/video.vue"),
meta: {
title: $t("menus.hsVirtualList")
title: $t("menus.hsvideo")
}
},
{
path: "/able/pdf",
name: "Pdf",
component: () => import("@/views/able/pdf.vue"),
path: "/able/videoFrame",
name: "VideoFrame",
component: () => import("@/views/able/video-frame/index.vue"),
meta: {
title: $t("menus.hsPdf")
title: $t("menus.hsVideoFrame")
}
},
{
path: "/able/excel",
name: "Excel",
component: () => import("@/views/able/excel.vue"),
path: "/able/danmaku",
name: "Danmaku",
component: () => import("@/views/able/danmaku/index.vue"),
meta: {
title: $t("menus.hsExcel")
title: $t("menus.hsdanmaku")
}
},
{
@@ -162,6 +146,30 @@ export default {
title: $t("menus.hsInfiniteScroll")
}
},
{
path: "/able/menuTree",
name: "MenuTree",
component: () => import("@/views/able/menu-tree.vue"),
meta: {
title: $t("menus.hsMenuTree")
}
},
{
path: "/able/lineTree",
name: "LineTree",
component: () => import("@/views/able/line-tree.vue"),
meta: {
title: $t("menus.hsLineTree")
}
},
{
path: "/able/typeit",
name: "Typeit",
component: () => import("@/views/able/typeit.vue"),
meta: {
title: $t("menus.hstypeit")
}
},
{
path: "/able/sensitive",
name: "Sensitive",

View File

@@ -15,85 +15,31 @@ export default {
name: "DialogPage",
component: () => import("@/views/components/dialog/index.vue"),
meta: {
title: $t("menus.hsdialog"),
extraIcon: "IF-pure-iconfont-new svg",
transition: {
enterTransition: "animate__fadeInLeft",
leaveTransition: "animate__fadeOutRight"
}
title: $t("menus.hsdialog")
}
},
{
path: "/components/message",
name: "Message",
component: () => import("@/views/components/message/index.vue"),
component: () => import("@/views/components/message.vue"),
meta: {
title: $t("menus.hsmessage")
}
},
{
path: "/components/segmented",
name: "Segmented",
component: () => import("@/views/components/segmented/index.vue"),
path: "/components/iconSelect",
name: "IconSelect",
component: () => import("@/views/components/icon-select.vue"),
meta: {
title: $t("menus.hssegmented"),
extraIcon: "IF-pure-iconfont-new svg"
title: $t("menus.hsIconSelect")
}
},
{
path: "/components/waterfall",
name: "Waterfall",
component: () => import("@/views/components/waterfall/index.vue"),
path: "/components/animatecss",
name: "AnimateCss",
component: () => import("@/views/components/animatecss.vue"),
meta: {
title: $t("menus.hswaterfall")
}
},
{
path: "/components/video",
name: "VideoPage",
component: () => import("@/views/components/video/index.vue"),
meta: {
title: $t("menus.hsvideo")
}
},
{
path: "/components/map",
name: "MapPage",
component: () => import("@/views/components/map/index.vue"),
meta: {
title: $t("menus.hsmap"),
keepAlive: true,
transition: {
name: "fade"
}
}
},
{
path: "/components/draggable",
name: "Draggable",
component: () => import("@/views/components/draggable/index.vue"),
meta: {
title: $t("menus.hsdraggable"),
transition: {
enterTransition: "animate__zoomIn",
leaveTransition: "animate__zoomOut"
}
}
},
{
path: "/components/splitPane",
name: "SplitPane",
component: () => import("@/views/components/split-pane/index.vue"),
meta: {
title: $t("menus.hssplitPane")
}
},
{
path: "/components/button",
name: "ButtonPage",
component: () => import("@/views/components/button/index.vue"),
meta: {
title: $t("menus.hsbutton")
title: $t("menus.hsanimatecss")
}
},
{
@@ -105,35 +51,76 @@ export default {
}
},
{
path: "/components/animatecss",
name: "AnimateCss",
component: () => import("@/views/components/animatecss/index.vue"),
path: "/components/checkButton",
name: "CheckButton",
component: () => import("@/views/components/check-button.vue"),
meta: {
title: $t("menus.hsanimatecss")
title: $t("menus.hsCheckButton"),
extraIcon: "IF-pure-iconfont-new svg"
}
},
{
path: "/components/countTo",
name: "CountTo",
component: () => import("@/views/components/count-to/index.vue"),
path: "/components/segmented",
name: "Segmented",
component: () => import("@/views/components/segmented.vue"),
meta: {
title: $t("menus.hscountTo")
title: $t("menus.hssegmented")
}
},
{
path: "/components/cascader",
name: "Cascader",
component: () => import("@/views/components/cascader.vue"),
meta: {
title: $t("menus.hsCascader")
}
},
{
path: "/components/selector",
name: "Selector",
component: () => import("@/views/components/selector/index.vue"),
component: () => import("@/views/components/selector.vue"),
meta: {
title: $t("menus.hsselector")
}
},
{
path: "/components/seamlessScroll",
name: "SeamlessScroll",
component: () => import("@/views/components/seamless-scroll/index.vue"),
path: "/components/waterfall",
name: "Waterfall",
component: () => import("@/views/components/waterfall/index.vue"),
meta: {
title: $t("menus.hsseamless")
title: $t("menus.hswaterfall")
}
},
{
path: "/components/splitPane",
name: "SplitPane",
component: () => import("@/views/components/split-pane.vue"),
meta: {
title: $t("menus.hssplitPane")
}
},
{
path: "/components/swiper",
name: "Swiper",
component: () => import("@/views/components/swiper.vue"),
meta: {
title: $t("menus.hsSwiper")
}
},
{
path: "/components/timeline",
name: "TimeLine",
component: () => import("@/views/components/timeline.vue"),
meta: {
title: $t("menus.hsTimeline")
}
},
{
path: "/components/countTo",
name: "CountTo",
component: () => import("@/views/components/count-to.vue"),
meta: {
title: $t("menus.hscountTo")
}
},
{
@@ -144,28 +131,36 @@ export default {
title: $t("menus.hscontextmenu")
}
},
{
path: "/components/typeit",
name: "Typeit",
component: () => import("@/views/components/typeit/index.vue"),
meta: {
title: $t("menus.hstypeit")
}
},
{
path: "/components/json-editor",
name: "JsonEditor",
component: () => import("@/views/components/json-editor/index.vue"),
component: () => import("@/views/components/json-editor.vue"),
meta: {
title: $t("menus.hsjsoneditor")
}
},
{
path: "/components/danmaku",
name: "Danmaku",
component: () => import("@/views/components/danmaku/index.vue"),
path: "/components/seamlessScroll",
name: "SeamlessScroll",
component: () => import("@/views/components/seamless-scroll.vue"),
meta: {
title: $t("menus.hsdanmaku")
title: $t("menus.hsseamless")
}
},
{
path: "/components/virtualList",
name: "VirtualList",
component: () => import("@/views/components/virtual-list/index.vue"),
meta: {
title: $t("menus.hsVirtualList")
}
},
{
path: "/components/button",
name: "ButtonPage",
component: () => import("@/views/components/button.vue"),
meta: {
title: $t("menus.hsbutton")
}
}
]

View File

@@ -52,8 +52,7 @@ export default {
name: "Menu1-2-2",
meta: {
title: $t("menus.hsmenu1-2-2"),
keepAlive: true,
extraIcon: "IF-pure-iconfont-new svg"
keepAlive: true
}
}
]

View File

@@ -25,10 +25,10 @@ watch(icon, () => {
>
animate.css
</el-link>
选择器组件
选择器
</span>
</div>
</template>
<ReAnimateSelector v-model="icon" />
<ReAnimateSelector v-model="icon" class="!w-[200px]" />
</el-card>
</template>

View File

@@ -14,7 +14,7 @@ const url = ref(`${VITE_PUBLIC_PATH}html/button.html`);
<el-card shadow="never">
<template #header>
<div class="card-header">
<span class="font-medium">通过iframe引入按钮页面</span>
<span class="font-medium">通过 iframe 引入按钮页面</span>
</div>
</template>
<iframe :src="url" frameborder="0" class="iframe w-full h-[60vh]" />

View File

@@ -26,10 +26,10 @@ const handleChange = value => {
<template>
<el-card shadow="never">
<template #header> <p class="font-medium">区域级联选择器</p> </template>
<el-row :gutter="20">
<el-row :gutter="24">
<el-col :xl="12" :lg="12" :md="24" :sm="24" :xs="24">
<div class="flex flex-col items-center justify-center">
<span class="imp">
<span class="text-[var(--el-color-primary)]">
1. 二级联动不带全部选项
<el-cascader
v-model="selectedOptions1"
@@ -58,7 +58,7 @@ const handleChange = value => {
</el-col>
<el-col :xl="12" :lg="12" :md="24" :sm="24" :xs="24">
<div class="flex flex-col items-center justify-center mt-3">
<span class="imp">
<span class="text-[var(--el-color-primary)]">
2. 二级联动带有全部选项
<el-cascader
v-model="selectedOptions3"
@@ -87,7 +87,7 @@ const handleChange = value => {
</el-col>
<el-col :xl="12" :lg="12" :md="24" :sm="24" :xs="24">
<div class="flex flex-col items-center justify-center mt-3">
<span class="imp">
<span class="text-[var(--el-color-primary)]">
3. 三级联动不带全部选项
<el-cascader
v-model="selectedOptions2"
@@ -118,7 +118,7 @@ const handleChange = value => {
</el-col>
<el-col :xl="12" :lg="12" :md="24" :sm="24" :xs="24">
<div class="flex flex-col items-center justify-center mt-3">
<span class="imp">
<span class="text-[var(--el-color-primary)]">
4. 三级联动"全部选项"
<el-cascader
v-model="selectedOptions4"
@@ -150,9 +150,3 @@ const handleChange = value => {
</el-row>
</el-card>
</template>
<style scoped lang="scss">
.imp {
color: var(--el-color-primary);
}
</style>

View File

@@ -0,0 +1,275 @@
<script setup lang="ts">
import { ref } from "vue";
import { message } from "@/utils/message";
import { getKeyList } from "@pureadmin/utils";
defineOptions({
name: "CheckButton"
});
const spaceSize = ref(20);
const size = ref("default");
const radio = ref("wait");
const radioBox = ref("complete");
const radioCustom = ref("progress");
const checkboxGroup = ref(["apple", "tomato"]);
const checkboxGroupBox = ref(["cucumber", "onion", "blueberry"]);
const checkboxGroupCustom = ref(["tomato", "watermelon", "strawberry"]);
/** 单选(可控制间距的按钮样式) */
const checkTag = ref([
{
title: "等待中",
checked: false
},
{
title: "进行中",
checked: true
},
{
title: "已完成",
checked: false
}
]);
const curTagMap = ref({});
function onChecked(tag, index) {
curTagMap.value[index] = Object.assign({
...tag,
checked: !tag.checked
});
checkTag.value.map(item => (item.checked = false));
checkTag.value[index].checked = curTagMap.value[index].checked;
const { title, checked } = curTagMap.value[index];
message(checked ? `已选中${title}` : `取消选中${title}`, {
type: "success"
});
}
/** 多选(可控制间距的按钮样式) */
const checkGroupTag = ref([
{
title: "苹果",
checked: true
},
{
title: "西红柿",
checked: true
},
{
title: "香蕉",
checked: false
}
]);
const curTagGroupMap = ref({});
function onGroupChecked(tag, index) {
curTagGroupMap.value[index] = Object.assign({
...tag,
checked: !tag.checked
});
checkGroupTag.value[index].checked = curTagGroupMap.value[index].checked;
}
</script>
<template>
<el-card shadow="never">
<template #header>
<div class="card-header">
<span class="font-medium">
可选按钮
<br />
<el-radio-group v-model="size" size="small">
<el-radio-button label="large">大尺寸</el-radio-button>
<el-radio-button label="default">默认尺寸</el-radio-button>
<el-radio-button label="small">小尺寸</el-radio-button>
<el-radio-button label="disabled">禁用</el-radio-button>
</el-radio-group>
</span>
</div>
</template>
<p class="mb-2">单选紧凑风格的按钮样式</p>
<el-radio-group
v-model="radio"
:size="size as any"
:disabled="size === 'disabled'"
>
<el-radio-button label="wait">等待中</el-radio-button>
<el-radio-button label="progress">进行中</el-radio-button>
<el-radio-button label="complete">已完成</el-radio-button>
</el-radio-group>
<el-divider />
<p class="mb-2">单选带有边框</p>
<el-radio-group
v-model="radioBox"
:size="size as any"
:disabled="size === 'disabled'"
>
<el-radio label="wait" border>等待中</el-radio>
<el-radio label="progress" border>进行中</el-radio>
<el-radio label="complete" border>已完成</el-radio>
</el-radio-group>
<el-divider />
<p class="mb-2">单选自定义内容</p>
<el-radio-group
v-model="radioCustom"
:size="size as any"
:disabled="size === 'disabled'"
>
<el-radio-button label="wait">
<span class="flex">
<IconifyIconOnline icon="ri:progress-8-fill" class="mr-1" />
等待中
</span>
</el-radio-button>
<el-radio-button label="progress">
<span class="flex">
<IconifyIconOnline icon="ri:progress-6-line" class="mr-1" />
进行中
</span>
</el-radio-button>
<el-radio-button label="complete">
<span class="flex">
<IconifyIconOnline icon="ri:progress-8-line" class="mr-1" />
已完成
</span>
</el-radio-button>
</el-radio-group>
<el-divider />
<p class="mb-2">多选紧凑风格的按钮样式</p>
<el-checkbox-group
v-model="checkboxGroup"
:size="size as any"
:disabled="size === 'disabled'"
>
<el-checkbox-button label="apple">苹果</el-checkbox-button>
<el-checkbox-button label="tomato">西红柿</el-checkbox-button>
<el-checkbox-button label="banana">香蕉</el-checkbox-button>
</el-checkbox-group>
<el-divider />
<p class="mb-2">多选带有边框</p>
<el-checkbox-group
v-model="checkboxGroupBox"
:size="size as any"
:disabled="size === 'disabled'"
>
<el-checkbox label="cucumber" border>黄瓜</el-checkbox>
<el-checkbox label="onion" border>洋葱</el-checkbox>
<el-checkbox label="blueberry" border>蓝莓</el-checkbox>
</el-checkbox-group>
<el-divider />
<p class="mb-2">多选来点不一样的体验</p>
<el-checkbox-group
v-model="checkboxGroupCustom"
class="pure-checkbox"
:size="size as any"
:disabled="size === 'disabled'"
>
<el-checkbox-button label="tomato">
<span class="flex">
<IconifyIconOnline icon="streamline-emojis:tomato" class="mr-1" />
番茄
</span>
</el-checkbox-button>
<el-checkbox-button label="watermelon">
<span class="flex">
<IconifyIconOnline
icon="streamline-emojis:watermelon-1"
class="mr-1"
/>
西瓜
</span>
</el-checkbox-button>
<el-checkbox-button label="strawberry">
<span class="flex">
<IconifyIconOnline
icon="streamline-emojis:strawberry-1"
class="mr-1"
/>
草莓
</span>
</el-checkbox-button>
</el-checkbox-group>
<el-divider />
<p>可控制间距的按钮样式</p>
<el-slider
v-model="spaceSize"
class="mb-2 !w-[300px]"
:show-tooltip="false"
:disabled="size === 'disabled'"
/>
<p class="mb-2">单选</p>
<el-space wrap :size="spaceSize">
<el-check-tag
v-for="(tag, index) in checkTag"
:key="index"
class="select-none"
:checked="tag.checked"
@change="onChecked(tag, index)"
>
{{ tag.title }}
</el-check-tag>
</el-space>
<p class="mb-2 mt-4">
多选
{{
getKeyList(
checkGroupTag.filter(tag => tag.checked),
"title"
)
}}
</p>
<el-space wrap :size="spaceSize">
<el-check-tag
v-for="(tag, index) in checkGroupTag"
:key="index"
class="select-none"
:checked="tag.checked"
@change="onGroupChecked(tag, index)"
>
{{ tag.title }}
</el-check-tag>
</el-space>
</el-card>
</template>
<style lang="scss" scoped>
:deep(.el-divider--horizontal) {
margin: 17px 0;
}
:deep(.pure-checkbox) {
.el-checkbox-button {
/* 选中时的自定义样式 */
&.is-checked {
.el-checkbox-button__inner {
color: var(--el-color-primary);
background-color: var(--el-color-primary-light-8);
border-color: transparent;
border-left-color: #fff;
}
}
/* 禁用时的自定义样式 */
&.is-disabled {
.el-checkbox-button__inner {
color: var(--el-disabled-text-color);
background-color: var(
--el-button-disabled-bg-color,
var(--el-fill-color-blank)
);
border-color: var(
--el-button-disabled-border-color,
var(--el-border-color-light)
);
}
}
}
}
</style>

View File

@@ -1,6 +1,6 @@
<template>
<div>
<p class="mb-2">本使用</p>
<p class="mb-2">础用法</p>
<div v-contextmenu:contextmenu class="wrapper">
<code>右键点击此区域</code>
</div>

View File

@@ -13,12 +13,12 @@ defineOptions({
<el-card shadow="never">
<template #header>
<div class="card-header">
<span class="font-medium">右键菜单组件</span>
<span class="font-medium">右键菜单</span>
</div>
</template>
<el-row :gutter="24">
<el-col :xs="24" :sm="10" :md="10" :lg="8" :xl="10">
<!-- 本使用 -->
<!-- 础用法 -->
<basic />
</el-col>
<el-col :xs="24" :sm="10" :md="10" :lg="8" :xl="10">

View File

@@ -0,0 +1,35 @@
<script setup lang="ts">
import { ReNormalCountTo, ReboundCountTo } from "@/components/ReCountTo";
defineOptions({
name: "CountTo"
});
</script>
<template>
<el-card shadow="never">
<template #header>
<div class="card-header">
<span class="font-medium">数字动画</span>
</div>
</template>
<ReNormalCountTo
prefix="$"
:duration="1000"
:color="'#409EFF'"
:fontSize="'2em'"
:startVal="1"
:endVal="1000"
/>
<br />
<ul class="flex">
<ReboundCountTo
v-for="(num, inx) of [1, 6, 6, 6]"
:key="inx"
:i="num"
:blur="inx"
:delay="inx + 1"
/>
</ul>
</el-card>
</template>

View File

@@ -1,36 +0,0 @@
<script setup lang="ts">
import { ReNormalCountTo, ReboundCountTo } from "@/components/ReCountTo";
defineOptions({
name: "CountTo"
});
</script>
<template>
<el-card shadow="never">
<template #header>
<div class="card-header">
<span class="font-medium">数字动画组件</span>
</div>
</template>
<div class="flex items-center">
<ReNormalCountTo
prefix="$"
:duration="1000"
:color="'#409EFF'"
:fontSize="'2em'"
:startVal="1"
:endVal="1000"
/>
<ul class="flex ml-8">
<ReboundCountTo
v-for="(num, inx) of [1, 6, 6, 6]"
:key="inx"
:i="num"
:blur="inx"
:delay="inx + 1"
/>
</ul>
</div>
</el-card>
</template>

View File

@@ -1,6 +1,6 @@
<script setup lang="tsx">
import { ref } from "vue";
import avatar from "./avatar.png";
import { ref, onBeforeUnmount } from "vue";
import ReCropper from "@/components/ReCropper";
import { formatBytes } from "@pureadmin/utils";
@@ -9,6 +9,7 @@ defineOptions({
});
const infos = ref();
const popoverRef = ref();
const refCropper = ref();
const showPopover = ref(false);
const cropperImg = ref<string>("");
@@ -18,6 +19,10 @@ function onCropper({ base64, blob, info }) {
infos.value = info;
cropperImg.value = base64;
}
onBeforeUnmount(() => {
popoverRef.value.hide();
});
</script>
<template>
@@ -25,7 +30,7 @@ function onCropper({ base64, blob, info }) {
<template #header>
<div class="card-header">
<span class="font-medium">
图片裁剪组件基于开源的
图片裁剪基于开源的
<el-link
href="https://fengyuanchen.github.io/cropperjs/"
target="_blank"
@@ -37,39 +42,41 @@ function onCropper({ base64, blob, info }) {
</span>
</div>
</template>
<el-popover
:visible="showPopover"
placement="right"
width="300px"
:teleported="false"
>
<template #reference>
<ReCropper
ref="refCropper"
class="w-[30vw]"
:src="avatar"
circled
@cropper="onCropper"
@readied="showPopover = true"
/>
</template>
<div class="flex flex-wrap justify-center items-center text-center">
<el-image
v-if="cropperImg"
:src="cropperImg"
:preview-src-list="Array.of(cropperImg)"
fit="cover"
/>
<div v-if="infos" class="mt-1">
<p>
图像大小{{ parseInt(infos.width) }} ×
{{ parseInt(infos.height) }}像素
</p>
<p>
文件大小{{ formatBytes(infos.size) }}{{ infos.size }} 字节
</p>
<div v-loading="!showPopover" element-loading-background="transparent">
<el-popover
ref="popoverRef"
:visible="showPopover"
placement="right"
width="300px"
>
<template #reference>
<ReCropper
ref="refCropper"
class="w-[30vw]"
:src="avatar"
circled
@cropper="onCropper"
@readied="showPopover = true"
/>
</template>
<div class="flex flex-wrap justify-center items-center text-center">
<el-image
v-if="cropperImg"
:src="cropperImg"
:preview-src-list="Array.of(cropperImg)"
fit="cover"
/>
<div v-if="infos" class="mt-1">
<p>
图像大小{{ parseInt(infos.width) }} ×
{{ parseInt(infos.height) }}像素
</p>
<p>
文件大小{{ formatBytes(infos.size) }}{{ infos.size }} 字节
</p>
</div>
</div>
</div>
</el-popover>
</el-popover>
</div>
</el-card>
</template>

View File

@@ -20,8 +20,8 @@ const router = useRouter();
function onBaseClick() {
addDialog({
title: "基本使用",
contentRenderer: () => <p>弹框内容-本使用</p> // jsx 语法 (注意在.vue文件启用jsx语法需要在script开启lang="tsx"
title: "基础用法",
contentRenderer: () => <p>弹框内容-础用法</p> // jsx 语法 (注意在.vue文件启用jsx语法需要在script开启lang="tsx"
});
}
@@ -422,7 +422,7 @@ function onBeforeSureClick() {
title: "点击底部确定按钮的回调",
contentRenderer: () => (
<p>
弹框内容-点击底部确定按钮的回调会暂停弹框的关闭经常用于新增编辑弹框内容后调用接口
弹框内容-点击底部确定按钮的回调会暂停弹框的关闭经常用于新增修改弹框内容后调用接口
</p>
),
beforeSure: (done, { options, index }) => {
@@ -454,15 +454,16 @@ function onBeforeSureClick() {
采用函数式调用弹框组件更多操作实例请参考
<span
class="cursor-pointer text-primary"
@click="router.push({ name: 'Dept' })"
>系统管理页面</span
@click="router.push({ name: 'SystemDept' })"
>
系统管理页面
</span>
</span>
</div>
</template>
<el-space wrap>
<el-button @click="onBaseClick"> 本使用 </el-button>
<el-button @click="onBaseClick"> 础用法 </el-button>
<el-button @click="onDraggableClick"> 可拖拽 </el-button>
<el-button @click="onFullscreenClick"> 全屏 </el-button>
<el-button @click="onFullscreenIconClick"> 全屏按钮 </el-button>
@@ -510,7 +511,7 @@ function onBeforeSureClick() {
点击底部取消按钮的回调会暂停弹框的关闭
</el-button>
<el-button @click="onBeforeSureClick">
点击底部确定按钮的回调会暂停弹框的关闭经常用于新增编辑弹框内容后调用接口
点击底部确定按钮的回调会暂停弹框的关闭经常用于新增修改弹框内容后调用接口
</el-button>
</el-space>
</el-card>

View File

@@ -16,6 +16,6 @@ const icon = ref("ep:add-location");
<span class="font-medium">图标选择器</span>
</div>
</template>
<IconSelect v-model="icon" />
<IconSelect v-model="icon" class="w-[200px]" />
</el-card>
</template>

View File

@@ -76,7 +76,7 @@ watch(
<template #header>
<div class="card-header">
<span class="font-medium">
JSON编辑器组件采用开源的
JSON编辑器采用开源的
<el-link
href="https://github.com/leezng/vue-json-pretty"
target="_blank"
@@ -87,7 +87,7 @@ watch(
支持大数据量
</span>
<span class="font-medium">
当然我们还有一款代码编辑器组件推荐这里就不做演示了采用开源的
当然还有一款代码编辑器推荐这里就不做演示了采用开源的
<el-link
href="https://github.com/surmon-china/vue-codemirror"
target="_blank"

View File

@@ -14,7 +14,7 @@ defineOptions({
<el-card shadow="never">
<template #header>
<div class="card-header">
<span class="font-medium"> Message提示 </span>
<span class="font-medium"> 消息提示 </span>
</div>
</template>

View File

@@ -53,7 +53,7 @@ function changeDirection(val) {
<el-card class="box-card" shadow="never">
<template #header>
<div class="card-header">
<span class="font-medium">无缝滚动示例</span>
<span class="font-medium">无缝滚动</span>
<el-button
class="button"
link

View File

@@ -30,6 +30,30 @@ const optionsBasis: Array<OptionsType> = [
}
];
/** tooltip 提示 */
const optionsTooltip: Array<OptionsType> = [
{
label: "周一",
tip: "周一启航,新的篇章"
},
{
label: "周二",
tip: "周二律动,携手共进"
},
{
label: "周三",
tip: "周三昂扬,激情不减"
},
{
label: "周四",
tip: "周四精进,事半功倍"
},
{
label: "周五",
tip: "周五喜悦,收尾归档"
}
];
/** 禁用 */
const optionsDisabled: Array<OptionsType> = [
{
@@ -51,7 +75,7 @@ const optionsDisabled: Array<OptionsType> = [
}
];
/** 设置图标 */
/** 设置图标 */
const optionsIcon: Array<OptionsType> = [
{
label: "周一",
@@ -65,8 +89,7 @@ const optionsIcon: Array<OptionsType> = [
icon: "terminalWindowLine"
},
{
label: "周四",
icon: "streamline-emojis:airplane"
label: "周四"
},
{
label: "周五",
@@ -99,7 +122,7 @@ const optionsLabel: Array<OptionsType> = [
label: () => (
<div>
{h(useRenderIcon(HomeFilled), {
class: "m-auto w-[20px] h-[20px]"
class: "m-auto mt-1 w-[18px] h-[18px]"
})}
<p>周一</p>
</div>
@@ -109,7 +132,7 @@ const optionsLabel: Array<OptionsType> = [
label: () => (
<div>
{h(useRenderIcon("terminalWindowLine"), {
class: "m-auto w-[20px] h-[20px]"
class: "m-auto mt-1 w-[18px] h-[18px]"
})}
<p>周二</p>
</div>
@@ -119,7 +142,7 @@ const optionsLabel: Array<OptionsType> = [
label: () => (
<div>
{h(useRenderIcon("streamline-emojis:cow-face"), {
class: "m-auto w-[20px] h-[20px]"
class: "m-auto mt-1 w-[18px] h-[18px]"
})}
<p>周三</p>
</div>
@@ -142,7 +165,7 @@ const optionsChange: Array<OptionsType> = [
}
];
/** change事件 */
/** change 事件 */
function onChange({ index, option }) {
const { label, value } = option;
message(`当前选中项索引为:${index},名字为${label},值为${value}`, {
@@ -158,26 +181,37 @@ function onChange({ index, option }) {
<span class="font-medium">分段控制器</span>
</div>
</template>
<p class="mb-2">
基础用法v-model<span class="text-primary">
{{ optionsBasis[value].label }}
</span>
</p>
<Segmented v-model="value" :options="optionsBasis" />
<el-divider />
<p class="mb-2">禁用</p>
<Segmented :options="optionsDisabled" />
<el-divider />
<p class="mb-2">设置图标</p>
<Segmented :options="optionsIcon" />
<el-divider />
<p class="mb-2">只设置图标</p>
<Segmented :options="optionsOnlyIcon" />
<el-divider />
<p class="mb-2">自定义渲染</p>
<Segmented :options="optionsLabel" />
<el-divider />
<p class="mb-2">change事件</p>
<Segmented :options="optionsChange" @change="onChange" />
<el-scrollbar>
<p class="mb-2">
基础用法v-model<span class="text-primary">
{{ optionsBasis[value].label }}
</span>
</p>
<Segmented v-model="value" :options="optionsBasis" />
<el-divider />
<p class="mb-2">tooltip 提示</p>
<Segmented :options="optionsTooltip" />
<el-divider />
<p class="mb-2">change 事件</p>
<Segmented :options="optionsChange" @change="onChange" />
<el-divider />
<p class="mb-2">禁用</p>
<Segmented :options="optionsDisabled" />
<el-divider />
<p class="mb-2">可设置图标</p>
<Segmented :options="optionsIcon" />
<el-divider />
<p class="mb-2">只设置图标</p>
<Segmented :options="optionsOnlyIcon" />
<el-divider />
<p class="mb-2">自定义渲染</p>
<Segmented :options="optionsLabel" />
</el-scrollbar>
</el-card>
</template>
<style scoped>
:deep(.el-divider--horizontal) {
margin: 17px 0;
}
</style>

View File

@@ -9,7 +9,7 @@ defineOptions({
const selectRange = ref<string>("");
const dataLists = ref([
{
title: "基本使用",
title: "基础用法",
echo: [],
disabled: false
},

View File

@@ -23,7 +23,7 @@ const settingTB: ContextProps = reactive({
<el-card shadow="never">
<template #header>
<div class="card-header">
<span class="font-medium">切割面板组件</span>
<span class="font-medium">切割面板</span>
</div>
</template>
<div class="split-pane">
@@ -31,17 +31,21 @@ const settingTB: ContextProps = reactive({
<!-- #paneL 表示指定该组件为左侧面板 -->
<template #paneL>
<!-- 自定义左侧面板的内容 -->
<div class="dv-a">A</div>
<el-scrollbar>
<div class="dv-a">A</div>
</el-scrollbar>
</template>
<!-- #paneR 表示指定该组件为右侧面板 -->
<template #paneR>
<!-- 再次将右侧面板进行拆分 -->
<splitpane :splitSet="settingTB">
<template #paneL>
<div class="dv-b">B</div>
<el-scrollbar><div class="dv-b">B</div></el-scrollbar>
</template>
<template #paneR>
<div class="dv-c">C</div>
<el-scrollbar>
<div class="dv-c">C</div>
</el-scrollbar>
</template>
</splitpane>
</template>
@@ -51,36 +55,25 @@ const settingTB: ContextProps = reactive({
</template>
<style lang="scss" scoped>
$W: 100%;
$H: 70vh;
.split-pane {
width: 70vw;
height: $H;
width: 100%;
height: calc(100vh - 260px);
font-size: 50px;
color: #fff;
text-align: center;
border: 1px solid #e5e6eb;
.dv-a,
.dv-b,
.dv-c {
width: $W;
height: $W;
line-height: $H;
.dv-a {
padding-top: 30vh;
color: rgba($color: dodgerblue, $alpha: 80%);
}
.dv-b,
.dv-c {
line-height: 250px;
}
.dv-b {
padding-top: 10vh;
color: rgba($color: #000, $alpha: 80%);
}
.dv-c {
padding-top: 18vh;
color: rgba($color: #ce272d, $alpha: 80%);
}
}

View File

@@ -1,5 +1,6 @@
<script setup lang="ts">
import { markRaw } from "vue";
import { randomGradient } from "@pureadmin/utils";
import { useRenderFlicker } from "@/components/ReFlicker";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import Iphone from "@iconify-icons/ep/iphone";
@@ -11,15 +12,26 @@ defineOptions({
const { lastBuildTime } = __APP_INFO__;
const activities = [
{
content: "支持圆点闪动",
content: "支持圆点发光",
timestamp: lastBuildTime,
icon: markRaw(useRenderFlicker())
},
{
content: "支持方形闪动",
content: "支持方形发光",
timestamp: lastBuildTime,
icon: markRaw(useRenderFlicker({ borderRadius: 0, background: "#67C23A" }))
},
{
content: "支持渐变发光",
timestamp: lastBuildTime,
icon: markRaw(
useRenderFlicker({
background: randomGradient({
randomizeHue: true
})
})
)
},
{
content: "支持默认颜色",
timestamp: lastBuildTime
@@ -70,7 +82,7 @@ const activities = [
placement="bottom"
>
<div class="message">
vue-pure-admin是基于Vue3.0+TypeScript+Vite+Element-Plus编写的一套后台管理系统
vue-pure-admin 是一款开源免费且开箱即用的中后台管理系统模版
</div>
</el-timeline-item>
</el-timeline>

View File

@@ -56,7 +56,7 @@ export function useColumns() {
];
const handleEdit = (index: number, row) => {
message(`编辑了第 ${index} 行,数据为:${JSON.stringify(row)}`, {
message(`修改了第 ${index} 行,数据为:${JSON.stringify(row)}`, {
type: "success"
});
};

View File

@@ -15,7 +15,7 @@ export function useColumns() {
);
const handleEdit = (index: number, row) => {
message(`编辑了第 ${index} 行,数据为:${JSON.stringify(row)}`, {
message(`修改了第 ${index} 行,数据为:${JSON.stringify(row)}`, {
type: "success"
});
};

View File

@@ -30,11 +30,11 @@ export function useColumns() {
disabled: true
},
{
label: "编辑",
label: "修改",
tips: "Edit",
fn: row =>
message(
`编辑了第 ${
`修改了第 ${
dataList.value.findIndex(v => v.id === row.id) + 1
} 行,数据为:${JSON.stringify(row)}`,
{

View File

@@ -5,11 +5,11 @@ import { clone, delay } from "@pureadmin/utils";
import EditPen from "@iconify-icons/ep/edit-pen";
import Check from "@iconify-icons/ep/check";
// 温馨提示:编辑整行方法雷同将cellRenderer后面渲染的组件抽出来做对应处理即可
// 温馨提示:修改整行方法雷同将cellRenderer后面渲染的组件抽出来做对应处理即可
export function useColumns() {
// 编辑值(可多个)
// 修改值(可多个)
const inputValMap = ref({});
// 是否正处于编辑状态(可多个)
// 是否正处于修改状态(可多个)
const editStatus = ref({});
// 当前激活的单元格(唯一)
const activeIndex = ref(-1);
@@ -43,7 +43,7 @@ export function useColumns() {
const columns: TableColumnList = [
{
label: "ID编辑",
label: "ID修改",
prop: "id",
// class="flex-bc" flex-bc 代表 flex justify-between items-center 具体看 src/style/tailwind.css 文件
cellRenderer: ({ row, index }) => (
@@ -93,7 +93,7 @@ export function useColumns() {
inputValMap.value[index] = Object.assign({}, inputValMap.value[index], {
value: id
});
// 处于编辑状态
// 处于修改状态
editStatus.value[index] = Object.assign({}, editStatus.value[index], {
editing: true
});
@@ -112,14 +112,14 @@ export function useColumns() {
function onSure(index) {
dataList.value[index].id = inputValMap.value[index].value;
message(
`编辑了第 ${index + 1} 行,编辑后数据为:${JSON.stringify(
`修改了第 ${index + 1} 行,修改后数据为:${JSON.stringify(
dataList.value[index]
)}`,
{
type: "success"
}
);
// 编辑状态关闭
// 修改状态关闭
editStatus.value[index] = Object.assign({}, editStatus.value[index], {
editing: false
});

View File

@@ -53,7 +53,7 @@ export const list = [
{
key: "edit",
content: rendContent("edit"),
title: "单元格编辑",
title: "单元格修改",
component: Edit
},
{

View File

@@ -10,7 +10,7 @@ import Refresh from "@iconify-icons/ep/refresh";
import AddFill from "@iconify-icons/ri/add-circle-line";
defineOptions({
name: "Dept"
name: "SystemDept"
});
const formRef = ref();
@@ -71,7 +71,7 @@ const {
</el-form>
<PureTableBar
title="部门列表(仅演示,操作后不生效)"
title="部门管理(仅演示,操作后不生效)"
:columns="columns"
:tableRef="tableRef?.getTableRef()"
@refresh="onSearch"
@@ -111,10 +111,20 @@ const {
link
type="primary"
:size="size"
:icon="useRenderIcon(EditPen)"
@click="openDialog('编辑', row)"
:icon="useRenderIcon(AddFill)"
@click="openDialog('新增', { parentId: row.id } as any)"
>
编辑
新增
</el-button>
<el-button
class="reset-margin"
link
type="primary"
:size="size"
:icon="useRenderIcon(EditPen)"
@click="openDialog('修改', row)"
>
修改
</el-button>
<el-popconfirm
:title="`是否确认删除部门名称为${row.name}的这条数据`"

View File

@@ -57,7 +57,7 @@ export function useDept() {
{
label: "操作",
fixed: "right",
width: 160,
width: 210,
slot: "operation"
}
];
@@ -141,7 +141,7 @@ export function useDept() {
// 实际开发先调用新增接口,再进行下面操作
chores();
} else {
// 实际开发先调用编辑接口,再进行下面操作
// 实际开发先调用修改接口,再进行下面操作
chores();
}
}
@@ -168,7 +168,7 @@ export function useDept() {
onSearch,
/** 重置 */
resetForm,
/** 新增、编辑部门 */
/** 新增、修改部门 */
openDialog,
/** 删除部门 */
handleDelete,

View File

@@ -13,7 +13,7 @@ import Menu from "@iconify-icons/ep/menu";
import AddFill from "@iconify-icons/ri/add-circle-line";
defineOptions({
name: "Role"
name: "SystemRole"
});
const formRef = ref();
@@ -87,7 +87,7 @@ const {
</el-form>
<PureTableBar
title="角色列表(仅演示,操作后不生效)"
title="角色管理(仅演示,操作后不生效)"
:columns="columns"
@refresh="onSearch"
>
@@ -127,7 +127,7 @@ const {
type="primary"
:size="size"
:icon="useRenderIcon(EditPen)"
@click="openDialog('编辑', row)"
@click="openDialog('修改', row)"
>
修改
</el-button>

View File

@@ -200,7 +200,7 @@ export function useRole() {
// 实际开发先调用新增接口,再进行下面操作
chores();
} else {
// 实际开发先调用编辑接口,再进行下面操作
// 实际开发先调用修改接口,再进行下面操作
chores();
}
}

View File

@@ -15,7 +15,7 @@ import Refresh from "@iconify-icons/ep/refresh";
import AddFill from "@iconify-icons/ri/add-circle-line";
defineOptions({
name: "User"
name: "SystemUser"
});
const treeRef = ref();
@@ -173,7 +173,7 @@ const {
type="primary"
:size="size"
:icon="useRenderIcon(EditPen)"
@click="openDialog('编辑', row)"
@click="openDialog('修改', row)"
>
修改
</el-button>

View File

@@ -342,7 +342,7 @@ export function useUser(tableRef: Ref, treeRef: Ref) {
// 实际开发先调用新增接口,再进行下面操作
chores();
} else {
// 实际开发先调用编辑接口,再进行下面操作
// 实际开发先调用修改接口,再进行下面操作
chores();
}
}