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

This commit is contained in:
xiaoxian521 2024-01-14 12:49:39 +08:00
commit 17eaf8161f
37 changed files with 794 additions and 536 deletions

2
.nvmrc
View File

@ -1 +1 @@
v20.10.0
v20.11.0

View File

@ -3,7 +3,13 @@ import { readdir, stat } from "node:fs";
import { fileURLToPath } from "node:url";
import { dirname, resolve } from "node:path";
import { sum, formatBytes } from "@pureadmin/utils";
import { dependencies, devDependencies, name, version } from "../package.json";
import {
name,
version,
engines,
dependencies,
devDependencies
} from "../package.json";
/** 启动`node`进程时所在工作目录的绝对路径 */
const root: string = process.cwd();
@ -35,9 +41,9 @@ const alias: Record<string, string> = {
"@build": pathResolve()
};
/** 平台的名称、版本、依赖、最后构建时间 */
/** 平台的名称、版本、运行所需的`node`和`pnpm`版本、依赖、最后构建时间的类型提示 */
const __APP_INFO__ = {
pkg: { name, version, dependencies, devDependencies },
pkg: { name, version, engines, dependencies, devDependencies },
lastBuildTime: dayjs(new Date()).format("YYYY-MM-DD HH:mm:ss")
};

View File

@ -111,6 +111,7 @@ menus:
hsPureTableBase: Base Usage
hsPureTableHigh: High Usage
hsTree: Big Data Tree
hsboard: Paint Board
hsMenuoverflow: Menu Overflow Show Tooltip Text
hsChildMenuoverflow: Child Menu Overflow Show Tooltip Text
status:

View File

@ -111,6 +111,7 @@ menus:
hsPureTableBase: 基础用法23个示例
hsPureTableHigh: 高级用法11个示例
hsTree: 大数据树业务组件
hsboard: 艺术画板
hsMenuoverflow: 目录超出显示 Tooltip 文字提示
hsChildMenuoverflow: 菜单超出显示 Tooltip 文字提示
status:

View File

@ -54,7 +54,7 @@
"@logicflow/extension": "^1.2.19",
"@pureadmin/descriptions": "^1.2.0",
"@pureadmin/table": "^3.0.1",
"@pureadmin/utils": "^2.3.1",
"@pureadmin/utils": "^2.4.0",
"@vueuse/core": "^10.7.1",
"@vueuse/motion": "^2.0.0",
"@wangeditor/editor": "^5.1.23",
@ -87,7 +87,7 @@
"v-contextmenu": "3.0.0",
"v3-infinite-loading": "^1.3.1",
"version-rocket": "^1.7.1",
"vue": "^3.4.7",
"vue": "^3.4.10",
"vue-i18n": "^9.9.0",
"vue-json-pretty": "^2.3.0",
"vue-pdf-embed": "^1.2.1",
@ -98,7 +98,7 @@
"vue-waterfall-plugin-next": "^2.3.1",
"vue3-danmaku": "^1.6.0",
"vuedraggable": "^4.1.0",
"wavesurfer.js": "^7.6.3",
"wavesurfer.js": "^7.6.4",
"xgplayer": "^3.0.11",
"xlsx": "^0.18.5"
},
@ -115,7 +115,7 @@
"@pureadmin/theme": "^3.2.0",
"@types/intro.js": "^5.1.5",
"@types/js-cookie": "^3.0.6",
"@types/node": "^20.10.8",
"@types/node": "^20.11.0",
"@types/nprogress": "^0.2.3",
"@types/qrcode": "^1.5.5",
"@types/qs": "^6.9.11",
@ -131,12 +131,12 @@
"eslint-config-prettier": "^9.1.0",
"eslint-define-config": "^2.1.0",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-vue": "^9.19.2",
"eslint-plugin-vue": "^9.20.0",
"husky": "^8.0.3",
"lint-staged": "^15.2.0",
"picocolors": "^1.0.0",
"postcss": "^8.4.33",
"postcss-html": "^1.5.0",
"postcss-html": "^1.6.0",
"postcss-import": "^15.1.0",
"postcss-scss": "^4.0.9",
"prettier": "^3.1.1",
@ -162,7 +162,7 @@
"vue-tsc": "^1.8.27"
},
"engines": {
"node": "^18.12.0 || >=20.0.0",
"node": "^18.18.0 || ^20.9.0 || >=21.1.0",
"pnpm": ">=8.6.10"
},
"packageManager": "pnpm@8.6.10",

488
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -3,9 +3,7 @@ import Cropper from "cropperjs";
import { useTippy } from "vue-tippy";
import { ElUpload } from "element-plus";
import type { CSSProperties } from "vue";
import { useResizeObserver } from "@vueuse/core";
import { longpress } from "@/directives/longpress";
import { delay, debounce, isArray, downloadByBase64 } from "@pureadmin/utils";
import {
ref,
unref,
@ -15,6 +13,13 @@ import {
onUnmounted,
defineComponent
} from "vue";
import {
delay,
debounce,
isArray,
downloadByBase64,
useResizeObserver
} from "@pureadmin/utils";
import {
Reload,
Upload,
@ -126,9 +131,7 @@ export default defineComponent({
cropper.value?.destroy();
});
useResizeObserver(tippyElRef, () => {
handCropper("reset");
});
useResizeObserver(tippyElRef, () => handCropper("reset"));
async function init() {
const imgEl = unref(imgElRef);

View File

@ -27,6 +27,8 @@ import Lollipop from "@iconify-icons/ep/lollipop";
import Monitor from "@iconify-icons/ep/monitor";
import Tag from "@iconify-icons/ri/bookmark-2-line";
import Table from "@iconify-icons/ri/table-line";
import Info from "@iconify-icons/ri/file-info-line";
import Artboard from "@iconify-icons/ri/artboard-line";
addIcon("ubuntuFill", UbuntuFill);
addIcon("menu", Menu);
addIcon("edit", Edit);
@ -49,3 +51,5 @@ addIcon("lollipop", Lollipop);
addIcon("monitor", Monitor);
addIcon("tag", Tag);
addIcon("table", Table);
addIcon("info", Info);
addIcon("artboard", Artboard);

View File

@ -46,7 +46,7 @@ const { t, locale, translationCh, translationEn } = useTranslationLang();
<div v-if="layout === 'vertical'" class="vertical-header-right">
<!-- 菜单搜索 -->
<Search />
<Search id="header-search" />
<!-- 通知 -->
<Notice id="header-notice" />
<!-- 国际化 -->

View File

@ -1,6 +1,6 @@
<script setup lang="ts">
import { transformI18n } from "@/plugins/i18n";
import { useResizeObserver } from "@vueuse/core";
import { useResizeObserver } from "@pureadmin/utils";
import { useEpThemeStoreHook } from "@/store/modules/epTheme";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import { ref, computed, getCurrentInstance, onMounted } from "vue";
@ -65,9 +65,7 @@ function resizeResult() {
innerHeight.value = window.innerHeight - window.innerHeight / 10 - 140;
}
useResizeObserver(resultRef, () => {
resizeResult();
});
useResizeObserver(resultRef, resizeResult);
function handleScroll(index: number) {
const curInstance = instance?.proxy?.$refs[`resultItemRef${index}`];

View File

@ -9,11 +9,13 @@ function handleSearch() {
</script>
<template>
<div
class="search-container w-[40px] h-[48px] flex-c cursor-pointer navbar-bg-hover"
@click="handleSearch"
>
<IconifyIconOffline icon="search" />
<div>
<div
class="search-container w-[40px] h-[48px] flex-c cursor-pointer navbar-bg-hover"
@click="handleSearch"
>
<IconifyIconOffline icon="search" />
</div>
<SearchModal v-model:value="show" />
</div>
<SearchModal v-model:value="show" />
</template>

View File

@ -64,7 +64,7 @@ nextTick(() => {
</el-menu>
<div class="horizontal-header-right">
<!-- 菜单搜索 -->
<Search />
<Search id="header-search" />
<!-- 通知 -->
<Notice id="header-notice" />
<!-- 国际化 -->

View File

@ -97,7 +97,7 @@ watch(
</el-menu>
<div class="horizontal-header-right">
<!-- 菜单搜索 -->
<Search />
<Search id="header-search" />
<!-- 通知 -->
<Notice id="header-notice" />
<!-- 国际化 -->

View File

@ -4,12 +4,12 @@ import { emitter } from "@/utils/mitt";
import { RouteConfigs } from "../../types";
import { useTags } from "../../hooks/useTag";
import { routerArrays } from "@/layout/types";
import { useFullscreen, onClickOutside } from "@vueuse/core";
import { handleAliveRoute, getTopMenu } from "@/router/utils";
import { useSettingStoreHook } from "@/store/modules/settings";
import { isEqual, isAllEmpty, debounce } from "@pureadmin/utils";
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
import { ref, watch, unref, toRaw, nextTick, onBeforeUnmount } from "vue";
import { useResizeObserver, useFullscreen, onClickOutside } from "@vueuse/core";
import { isEqual, isAllEmpty, useResizeObserver } from "@pureadmin/utils";
import ExitFullscreen from "@iconify-icons/ri/fullscreen-exit-fill";
import Fullscreen from "@iconify-icons/ri/fullscreen-fill";
@ -503,10 +503,7 @@ onMounted(() => {
});
});
useResizeObserver(
scrollbarDom,
debounce(() => dynamicTagView())
);
useResizeObserver(scrollbarDom, dynamicTagView);
});
onBeforeUnmount(() => {

View File

@ -4,10 +4,8 @@ import "animate.css";
import "@/components/ReIcon/src/offlineIcon";
import { setType } from "./types";
import { useLayout } from "./hooks/useLayout";
import { useResizeObserver } from "@vueuse/core";
import { useAppStoreHook } from "@/store/modules/app";
import { useSettingStoreHook } from "@/store/modules/settings";
import { deviceDetection, useDark, useGlobal } from "@pureadmin/utils";
import { useDataThemeChange } from "@/layout/hooks/useDataThemeChange";
import {
h,
@ -18,6 +16,12 @@ import {
onBeforeMount,
defineComponent
} from "vue";
import {
useDark,
useGlobal,
deviceDetection,
useResizeObserver
} from "@pureadmin/utils";
import navbar from "./components/navbar.vue";
import tag from "./components/tag/index.vue";
@ -84,7 +88,7 @@ let isAutoCloseSidebar = true;
useResizeObserver(appWrapperRef, entries => {
if (isMobile) return;
const entry = entries[0];
const { width } = entry.contentRect;
const [{ inlineSize: width }] = entry.borderBoxSize;
width <= 760 ? setTheme("vertical") : setTheme(useAppStoreHook().layout);
/** width app-wrapper
* 0 < width <= 760 隐藏侧边栏

View File

@ -1,12 +1,12 @@
import App from "./App.vue";
import router from "./router";
import { setupStore } from "@/store";
import ElementPlus from "element-plus";
import { useI18n } from "@/plugins/i18n";
import { getPlatformConfig } from "./config";
import { MotionPlugin } from "@vueuse/motion";
import { useEcharts } from "@/plugins/echarts";
import { createApp, type Directive } from "vue";
import { useElementPlus } from "@/plugins/elementPlus";
import { injectResponsiveStorage } from "@/utils/responsive";
import Table from "@pureadmin/table";
@ -61,7 +61,7 @@ getPlatformConfig(app).then(async config => {
app
.use(MotionPlugin)
.use(useI18n)
.use(ElementPlus)
.use(useElementPlus)
.use(Table)
.use(PureDescriptions)
.use(useEcharts);

View File

@ -1,7 +1,7 @@
import type { App } from "vue";
import * as echarts from "echarts/core";
import { CanvasRenderer, SVGRenderer } from "echarts/renderers";
import { PieChart, BarChart, LineChart } from "echarts/charts";
import { CanvasRenderer, SVGRenderer } from "echarts/renderers";
import {
GridComponent,
TitleComponent,

View File

@ -1,141 +0,0 @@
import type { App, Component } from "vue";
import {
ElTag,
ElAffix,
ElSkeleton,
ElBreadcrumb,
ElBreadcrumbItem,
ElScrollbar,
ElSubMenu,
ElButton,
ElCol,
ElRow,
ElSpace,
ElDivider,
ElCard,
ElDropdown,
ElDialog,
ElMenu,
ElMenuItem,
ElDropdownItem,
ElDropdownMenu,
ElIcon,
ElInput,
ElForm,
ElFormItem,
ElPopover,
ElPopper,
ElTooltip,
ElDrawer,
ElPagination,
ElAlert,
ElRadio,
ElRadioButton,
ElRadioGroup,
ElDescriptions,
ElDescriptionsItem,
ElBacktop,
ElSwitch,
ElBadge,
ElTabs,
ElTabPane,
ElAvatar,
ElEmpty,
ElCollapse,
ElCollapseItem,
ElTable,
ElTableColumn,
ElLink,
ElColorPicker,
ElSelect,
ElOption,
ElTimeline,
ElTimelineItem,
ElResult,
ElSteps,
ElStep,
ElTree,
ElTreeV2,
ElPopconfirm,
ElCheckbox,
ElCheckboxGroup,
// 指令
ElLoading,
ElInfiniteScroll
} from "element-plus";
// Directives
const plugins = [ElLoading, ElInfiniteScroll];
const components = [
ElTag,
ElAffix,
ElSkeleton,
ElBreadcrumb,
ElBreadcrumbItem,
ElScrollbar,
ElSubMenu,
ElButton,
ElCol,
ElRow,
ElSpace,
ElDivider,
ElCard,
ElDropdown,
ElDialog,
ElMenu,
ElMenuItem,
ElDropdownItem,
ElDropdownMenu,
ElIcon,
ElInput,
ElForm,
ElFormItem,
ElPopover,
ElPopper,
ElTooltip,
ElDrawer,
ElPagination,
ElAlert,
ElRadio,
ElRadioButton,
ElRadioGroup,
ElDescriptions,
ElDescriptionsItem,
ElBacktop,
ElSwitch,
ElBadge,
ElTabs,
ElTabPane,
ElAvatar,
ElEmpty,
ElCollapse,
ElCollapseItem,
ElTree,
ElTreeV2,
ElPopconfirm,
ElCheckbox,
ElCheckboxGroup,
ElTable,
ElTableColumn,
ElLink,
ElColorPicker,
ElSelect,
ElOption,
ElTimeline,
ElTimelineItem,
ElResult,
ElSteps,
ElStep
];
export function useElementPlus(app: App) {
// 注册组件
components.forEach((component: Component) => {
app.component(component.name, component);
});
// 注册指令
plugins.forEach(plugin => {
app.use(plugin);
});
}

242
src/plugins/elementPlus.ts Normal file
View File

@ -0,0 +1,242 @@
// 按需引入element-plus该方法稳定且明确。当然也支持https://element-plus.org/zh-CN/guide/quickstart.html#%E6%8C%89%E9%9C%80%E5%AF%BC%E5%85%A5
import type { App, Component } from "vue";
import {
/**
* 便 element-plus 使
* https://github.com/element-plus/element-plus/blob/dev/packages/element-plus/component.ts#L111-L211
* */
ElAffix,
ElAlert,
ElAutocomplete,
ElAutoResizer,
ElAvatar,
ElBacktop,
ElBadge,
ElBreadcrumb,
ElBreadcrumbItem,
ElButton,
ElButtonGroup,
ElCalendar,
ElCard,
ElCarousel,
ElCarouselItem,
ElCascader,
ElCascaderPanel,
ElCheckTag,
ElCheckbox,
ElCheckboxButton,
ElCheckboxGroup,
ElCol,
ElCollapse,
ElCollapseItem,
ElCollapseTransition,
ElColorPicker,
ElConfigProvider,
ElContainer,
ElAside,
ElFooter,
ElHeader,
ElMain,
ElDatePicker,
ElDescriptions,
ElDescriptionsItem,
ElDialog,
ElDivider,
ElDrawer,
ElDropdown,
ElDropdownItem,
ElDropdownMenu,
ElEmpty,
ElForm,
ElFormItem,
ElIcon,
ElImage,
ElImageViewer,
ElInput,
ElInputNumber,
ElLink,
ElMenu,
ElMenuItem,
ElMenuItemGroup,
ElSubMenu,
ElPageHeader,
ElPagination,
ElPopconfirm,
ElPopover,
ElPopper,
ElProgress,
ElRadio,
ElRadioButton,
ElRadioGroup,
ElRate,
ElResult,
ElRow,
ElScrollbar,
ElSelect,
ElOption,
ElOptionGroup,
ElSelectV2,
ElSkeleton,
ElSkeletonItem,
ElSlider,
ElSpace,
ElStatistic,
ElCountdown,
ElSteps,
ElStep,
ElSwitch,
ElTable,
ElTableColumn,
ElTableV2,
ElTabs,
ElTabPane,
ElTag,
ElText,
ElTimePicker,
ElTimeSelect,
ElTimeline,
ElTimelineItem,
ElTooltip,
ElTransfer,
ElTree,
ElTreeSelect,
ElTreeV2,
ElUpload,
ElWatermark,
ElTour,
ElTourStep,
/**
* 便 element-plus 使
* https://github.com/element-plus/element-plus/blob/dev/packages/element-plus/plugin.ts#L11-L16
* */
ElLoading, // v-loading 指令
ElInfiniteScroll, // v-infinite-scroll 指令
ElPopoverDirective, // v-popover 指令
ElMessage, // $message 全局属性对象globalProperties
ElMessageBox, // $msgbox、$alert、$confirm、$prompt 全局属性对象globalProperties
ElNotification // $notify 全局属性对象globalProperties
} from "element-plus";
const components = [
ElAffix,
ElAlert,
ElAutocomplete,
ElAutoResizer,
ElAvatar,
ElBacktop,
ElBadge,
ElBreadcrumb,
ElBreadcrumbItem,
ElButton,
ElButtonGroup,
ElCalendar,
ElCard,
ElCarousel,
ElCarouselItem,
ElCascader,
ElCascaderPanel,
ElCheckTag,
ElCheckbox,
ElCheckboxButton,
ElCheckboxGroup,
ElCol,
ElCollapse,
ElCollapseItem,
ElCollapseTransition,
ElColorPicker,
ElConfigProvider,
ElContainer,
ElAside,
ElFooter,
ElHeader,
ElMain,
ElDatePicker,
ElDescriptions,
ElDescriptionsItem,
ElDialog,
ElDivider,
ElDrawer,
ElDropdown,
ElDropdownItem,
ElDropdownMenu,
ElEmpty,
ElForm,
ElFormItem,
ElIcon,
ElImage,
ElImageViewer,
ElInput,
ElInputNumber,
ElLink,
ElMenu,
ElMenuItem,
ElMenuItemGroup,
ElSubMenu,
ElPageHeader,
ElPagination,
ElPopconfirm,
ElPopover,
ElPopper,
ElProgress,
ElRadio,
ElRadioButton,
ElRadioGroup,
ElRate,
ElResult,
ElRow,
ElScrollbar,
ElSelect,
ElOption,
ElOptionGroup,
ElSelectV2,
ElSkeleton,
ElSkeletonItem,
ElSlider,
ElSpace,
ElStatistic,
ElCountdown,
ElSteps,
ElStep,
ElSwitch,
ElTable,
ElTableColumn,
ElTableV2,
ElTabs,
ElTabPane,
ElTag,
ElText,
ElTimePicker,
ElTimeSelect,
ElTimeline,
ElTimelineItem,
ElTooltip,
ElTransfer,
ElTree,
ElTreeSelect,
ElTreeV2,
ElUpload,
ElWatermark,
ElTour,
ElTourStep
];
const plugins = [
ElLoading,
ElInfiniteScroll,
ElPopoverDirective,
ElMessage,
ElMessageBox,
ElNotification
];
/** 按需引入`element-plus` */
export function useElementPlus(app: App) {
// 全局注册组件
components.forEach((component: Component) => {
app.component(component.name, component);
});
// 全局注册插件
plugins.forEach(plugin => {
app.use(plugin);
});
}

View File

@ -12,13 +12,14 @@ const home = 0, // 平台规定只有 home 路由的 rank 才能为 0 ,所以
permission = 9,
system = 10,
tabs = 11,
formdesign = 12,
flowchart = 13,
ppt = 14,
editor = 15,
guide = 16,
about = 17,
menuoverflow = 18;
about = 12,
editor = 13,
flowchart = 14,
formdesign = 15,
board = 16,
ppt = 17,
guide = 18,
menuoverflow = 19;
export {
home,
@ -33,11 +34,12 @@ export {
permission,
system,
tabs,
formdesign,
flowchart,
ppt,
editor,
guide,
about,
editor,
flowchart,
formdesign,
board,
ppt,
guide,
menuoverflow
};

View File

@ -5,6 +5,7 @@ export default {
path: "/about",
redirect: "/about/index",
meta: {
icon: "info",
title: $t("menus.hsAbout"),
rank: about
},

View File

@ -0,0 +1,25 @@
import { $t } from "@/plugins/i18n";
import { board } from "@/router/enums";
const IFrame = () => import("@/layout/frameView.vue");
export default {
path: "/board",
redirect: "/board/index",
meta: {
icon: "artboard",
title: $t("menus.hsboard"),
rank: board
},
children: [
{
path: "/board/index",
name: "FrameBoard",
component: IFrame,
meta: {
title: $t("menus.hsboard"),
frameSrc: "https://songlh.top/paint-board/",
extraIcon: "IF-pure-iconfont-new svg"
}
}
]
} satisfies RouteConfigsTable;

View File

@ -18,7 +18,8 @@ export default {
meta: {
title: $t("menus.hsFormDesign"),
frameSrc:
"https://haixin-fang.github.io/starfish-vue3-lowcode/playground/index.html#/"
"https://haixin-fang.github.io/vue-form-design/playground/index.html",
frameLoading: false
}
}
]

View File

@ -156,6 +156,18 @@
/* 自定义菜单搜索样式 */
.pure-search-dialog {
@media screen and (width > 760px) and (width <= 940px) {
.el-input__inner {
font-size: 12px;
}
}
@media screen and (width <= 470px) {
.el-input__inner {
font-size: 12px;
}
}
.el-dialog__header {
display: none;
}

View File

@ -36,7 +36,7 @@ onBeforeUnmount(() => {
<template #header>
<div class="card-header">
<span class="font-medium">
页面水印菜单树结构
页面水印
<el-link
href="https://pure-admin-utils.netlify.app/hooks/useWatermark/useWatermark"
target="_blank"
@ -55,12 +55,11 @@ onBeforeUnmount(() => {
</el-space>
<el-space wrap>
<el-button bg text @click="setWatermark(value, { color })">
<el-button plain @click="setWatermark(value, { color })">
创建整页水印
</el-button>
<el-button
bg
text
plain
@click="
setWatermark(value, {
gradient: [
@ -74,8 +73,7 @@ onBeforeUnmount(() => {
创建整页渐变水印
</el-button>
<el-button
bg
text
plain
@click="
setWatermark(value, {
rotate: 0,
@ -90,8 +88,7 @@ onBeforeUnmount(() => {
创建整页渐变且水平90度的水印
</el-button>
<el-button
bg
text
plain
@click="
setWatermark(value, {
gradient: [
@ -106,8 +103,7 @@ onBeforeUnmount(() => {
创建整页渐变且有阴影的水印
</el-button>
<el-button
bg
text
plain
@click="
setWatermark(value, {
globalAlpha: 0.15, //
@ -121,7 +117,7 @@ onBeforeUnmount(() => {
>
创建整页高透明渐变水印
</el-button>
<el-button bg text @click="clear">清除整页水印</el-button>
<el-button plain @click="clear">清除整页水印</el-button>
</el-space>
<el-divider />
@ -130,8 +126,7 @@ onBeforeUnmount(() => {
<el-space wrap class="mt-6">
<el-button
bg
text
plain
@click="
setLocalWatermark('局部水印', {
color,
@ -143,8 +138,7 @@ onBeforeUnmount(() => {
创建局部水印
</el-button>
<el-button
bg
text
plain
@click="
setLocalWatermark('局部水印', {
width: 140,
@ -160,8 +154,7 @@ onBeforeUnmount(() => {
创建局部渐变水印
</el-button>
<el-button
bg
text
plain
@click="
setLocalWatermark('局部水印', {
width: 140,
@ -178,8 +171,7 @@ onBeforeUnmount(() => {
创建局部渐变且水平90度的水印
</el-button>
<el-button
bg
text
plain
@click="
setLocalWatermark('局部水印', {
width: 140,
@ -195,7 +187,7 @@ onBeforeUnmount(() => {
>
创建局部渐变且有阴影的水印
</el-button>
<el-button bg text @click="clearLocal">清除局部水印</el-button>
<el-button plain @click="clearLocal">清除局部水印</el-button>
</el-space>
<el-divider />

View File

@ -1,67 +1,99 @@
export function useColumns() {
const { pkg, lastBuildTime } = __APP_INFO__;
const { version } = pkg;
const { version, engines } = pkg;
const columns = [
{
label: "版本",
label: "当前版本",
cellRenderer: () => {
return <el-tag size="small">{version}</el-tag>;
return (
<el-tag size="large" class="!text-base">
{version}
</el-tag>
);
}
},
{
label: "最后编译时间",
cellRenderer: () => {
return <el-tag size="small">{lastBuildTime}</el-tag>;
}
},
{
label: "文档地址",
cellRenderer: () => {
return (
<a
href="https://yiming_chang.gitee.io/pure-admin-doc"
target="_blank"
>
<span style="color: var(--el-color-primary)"></span>
</a>
<el-tag size="large" class="!text-base">
{lastBuildTime}
</el-tag>
);
}
},
{
label: "预览地址",
label: "推荐 node 版本",
cellRenderer: () => {
return (
<a
href="https://yiming_chang.gitee.io/vue-pure-admin"
target="_blank"
>
<span style="color: var(--el-color-primary)"></span>
</a>
<el-tag size="large" class="!text-base">
{engines.node}
</el-tag>
);
}
},
{
label: "Github",
label: "推荐 pnpm 版本",
cellRenderer: () => {
return (
<el-tag size="large" class="!text-base">
{engines.pnpm}
</el-tag>
);
}
},
{
label: "完整版代码地址",
className: "pure-version",
cellRenderer: () => {
return (
<a
href="https://github.com/pure-admin/vue-pure-admin"
target="_blank"
>
<span style="color: var(--el-color-primary)">Github</span>
<span style="color: var(--el-color-primary)"></span>
</a>
);
}
},
{
label: "精简版",
label: "精简版代码地址",
className: "pure-version",
cellRenderer: () => {
return (
<a
href="https://github.com/pure-admin/pure-admin-thin"
target="_blank"
>
<span style="color: var(--el-color-primary)"></span>
<span style="color: var(--el-color-primary)"></span>
</a>
);
}
},
{
label: "文档地址",
className: "pure-version",
cellRenderer: () => {
return (
<a
href="https://yiming_chang.gitee.io/pure-admin-doc"
target="_blank"
>
<span style="color: var(--el-color-primary)"></span>
</a>
);
}
},
{
label: "预览地址",
className: "pure-version",
cellRenderer: () => {
return (
<a
href="https://yiming_chang.gitee.io/vue-pure-admin"
target="_blank"
>
<span style="color: var(--el-color-primary)"></span>
</a>
);
}

View File

@ -1,5 +1,7 @@
<script setup lang="ts">
import { computed } from "vue";
import { useColumns } from "./columns";
export interface schemaItem {
field: string;
label: string;
@ -17,6 +19,36 @@ const devSchema: schemaItem[] = [];
const { columns } = useColumns();
const words = [
"@pureadmin/descriptions",
"@pureadmin/table",
"@pureadmin/utils",
"@vueuse/core",
"axios",
"dayjs",
"echarts",
"vue",
"element-plus",
"pinia",
"vue-i18n",
"vue-router",
"@iconify/vue",
"@vitejs/plugin-vue",
"@vitejs/plugin-vue-jsx",
"eslint",
"prettier",
"sass",
"stylelint",
"tailwindcss",
"typescript",
"vite",
"vue-tsc"
];
const getMainLabel = computed(
() => (label: string) => words.find(w => w === label) && "main-label"
);
Object.keys(dependencies).forEach(key => {
schema.push({ field: dependencies[key], label: key });
});
@ -29,24 +61,21 @@ Object.keys(devDependencies).forEach(key => {
<template>
<div>
<el-card class="mb-4 box-card" shadow="never">
<template #header>
<div class="card-header">
<span class="font-medium">关于</span>
</div>
</template>
<span style="font-size: 15px">
Pure-Admin 是一个基于Vue3ViteTypeScriptElement-Plus
的中后台解决方案它可以帮助您快速搭建企业级中后台提供现成的开箱解决方案及丰富的示例原则上不收取任何费用及版权可以放心使用不过如需二次开源比如用此平台二次开发并开源请联系作者获取许可
<span>
vue-pure-admin 是一款开源免费且开箱即用的中后台管理系统模版完全采用
ECMAScript 模块ESM规范来编写和组织代码使用了最新的
Vue3ViteElement-PlusTypeScriptPiniaTailwindcss
等主流技术开发
</span>
</el-card>
<el-card class="m-4 box-card" shadow="never">
<template #header>
<div class="card-header">
<span class="font-medium">项目信息</span>
<span class="font-medium">平台信息</span>
</div>
</template>
<PureDescriptions :columns="columns" border :column="3" align="left" />
<PureDescriptions border :columns="columns" :column="4" />
</el-card>
<el-card class="m-4 box-card" shadow="never">
@ -55,19 +84,25 @@ Object.keys(devDependencies).forEach(key => {
<span class="font-medium">生产环境依赖</span>
</div>
</template>
<el-descriptions border>
<el-descriptions border size="small" :column="6">
<el-descriptions-item
v-for="(item, index) in schema"
:key="index"
:label="item.label"
label-align="left"
align="left"
:label-class-name="getMainLabel(item.label)"
class-name="pure-version"
label-align="right"
>
<a
:href="'https://www.npmjs.com/package/' + item.label"
target="_blank"
>
<span style="color: var(--el-color-primary)">{{ item.field }}</span>
<span
:class="getMainLabel(item.label)"
style="color: var(--el-color-primary)"
>
{{ item.field }}
</span>
</a>
</el-descriptions-item>
</el-descriptions>
@ -79,19 +114,25 @@ Object.keys(devDependencies).forEach(key => {
<span class="font-medium">开发环境依赖</span>
</div>
</template>
<el-descriptions border>
<el-descriptions border size="small" :column="5">
<el-descriptions-item
v-for="(item, index) in devSchema"
:key="index"
:label="item.label"
label-align="left"
align="left"
:label-class-name="getMainLabel(item.label)"
class-name="pure-version"
label-align="right"
>
<a
:href="'https://www.npmjs.com/package/' + item.label"
target="_blank"
>
<span style="color: var(--el-color-primary)">{{ item.field }}</span>
<span
:class="getMainLabel(item.label)"
style="color: var(--el-color-primary)"
>
{{ item.field }}
</span>
</a>
</el-descriptions-item>
</el-descriptions>
@ -100,6 +141,21 @@ Object.keys(devDependencies).forEach(key => {
</template>
<style lang="scss" scoped>
:deep(.main-label) {
font-size: 16px !important;
color: var(--el-color-danger) !important;
}
:deep(.pure-version) {
font-size: 14px !important;
font-weight: 600 !important;
opacity: 0.6;
&:hover {
opacity: 1;
}
}
.main-content {
margin: 0 !important;
}

View File

@ -3,8 +3,6 @@ import { ref, onMounted } from "vue";
import Sortable, { Swap } from "sortablejs";
import draggable from "vuedraggable/src/vuedraggable";
import { useAppStoreHook } from "@/store/modules/app";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import Rank from "@iconify-icons/ep/rank";
defineOptions({
name: "Draggable"
@ -64,7 +62,6 @@ onMounted(() => {
<el-link
href="https://sortablejs.github.io/vue.draggable.next/#/simple"
target="_blank"
:icon="useRenderIcon(Rank)"
style="margin: 0 4px 5px; font-size: 16px"
>
vuedraggable

View File

@ -179,6 +179,5 @@ function onChange({ index, option }) {
<el-divider />
<p class="mb-2">change事件</p>
<Segmented :options="optionsChange" @change="onChange" />
<el-divider />
</el-card>
</template>

View File

@ -92,7 +92,7 @@ onMounted(() => {
</script>
<template>
<el-scrollbar height="87vh" class="content">
<el-scrollbar max-height="calc(100vh - 90px)" class="content">
<Waterfall :list="list" v-bind="options">
<template #item="{ item, url, index }">
<div
@ -149,3 +149,13 @@ onMounted(() => {
<InfiniteLoading :firstload="false" @infinite="handleLoadMore" />
</el-scrollbar>
</template>
<style lang="scss" scoped>
.main-content {
margin: 0 !important;
}
:deep(.el-loading-spinner .el-loading-text) {
font-size: 24px;
}
</style>

View File

@ -6,7 +6,7 @@ defineOptions({
name: "Editor"
});
const activeNames = ref(["1"]);
const activeNames = ref("1");
</script>
<template>
@ -27,13 +27,13 @@ const activeNames = ref(["1"]);
</template>
<el-collapse v-model="activeNames" accordion>
<el-collapse-item title="基础用法" name="1">
<Base />
<Base v-if="activeNames === '1'" />
</el-collapse-item>
<el-collapse-item title="多个富文本" name="2">
<Multi />
<Multi v-if="activeNames === '2'" />
</el-collapse-item>
<el-collapse-item title="自定义图片上传" name="3">
<PicUpload />
<PicUpload v-if="activeNames === '3'" />
</el-collapse-item>
</el-collapse>
</el-card>

View File

@ -5,14 +5,11 @@ import "@logicflow/extension/lib/style/index.css";
import LogicFlow from "@logicflow/core";
import { ref, unref, onMounted } from "vue";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import { BpmnNode } from "@/components/ReFlowChart/src/config";
import { Snapshot, BpmnElement, Menu } from "@logicflow/extension";
import { Control, NodePanel, DataDialog } from "@/components/ReFlowChart";
import { toLogicflowData } from "@/components/ReFlowChart/src/adpterForTurbo";
import SetUp from "@iconify-icons/ep/set-up";
defineOptions({
name: "FlowChart"
});
@ -71,9 +68,8 @@ onMounted(() => {
<span class="font-medium">
流程图组件采用开源的
<el-link
href="http://logic-flow.org/"
href="https://site.logic-flow.cn/docs/#/zh/guide/start"
target="_blank"
:icon="useRenderIcon(SetUp)"
style="margin: 0 4px 5px; font-size: 16px"
>
LogicFlow
@ -91,7 +87,7 @@ onMounted(() => {
@catData="catData"
/>
<!-- 节点面板 -->
<NodePanel :lf="lf" :nodeList="nodeList" />
<NodePanel v-if="lf" :lf="lf" :nodeList="nodeList" />
<!-- 画布 -->
<div id="turbo" />
<!-- 数据查看面板 -->

View File

@ -6,10 +6,26 @@ defineOptions({
name: "Guide"
});
const guide = () => {
const onGuide = () => {
intro()
.setOptions({
steps: [
{
element: document.querySelector(".sidebar-logo-container") as
| string
| HTMLElement,
title: "项目名称和Logo",
intro: "您可以在这里设置项目名称和Logo",
position: "left"
},
{
element: document.querySelector("#header-search") as
| string
| HTMLElement,
title: "搜索菜单",
intro: "您可以在这里搜索想要查看的菜单",
position: "left"
},
{
element: document.querySelector("#header-notice") as
| string
@ -49,12 +65,10 @@ const guide = () => {
<template #header>
<div class="card-header">
<span class="font-medium">
引导页对于一些第一次进入项目的人很有用你可以简单介绍下项目的功能
引导页常用于引导式介绍项目的基本功能或亮点
</span>
</div>
</template>
<el-button type="primary" class="mt-[10px]" @click="guide">
打开引导页
</el-button>
<el-button @click="onGuide"> 打开引导页 </el-button>
</el-card>
</template>

View File

@ -77,7 +77,7 @@ const onLogin = async (formEl: FormInstance | undefined) => {
.then(res => {
if (res.success) {
//
initRouter().then(() => {
return initRouter().then(() => {
router.push(getTopMenu(true).path);
message("登录成功", { type: "success" });
});

View File

@ -16,17 +16,17 @@ defineOptions({
</template>
<el-space wrap>
<Auth value="btn_add">
<el-button text bg type="warning">
<el-button plain type="warning">
拥有code'btn_add' 权限可见
</el-button>
</Auth>
<Auth :value="['btn_edit']">
<el-button text bg type="primary">
<el-button plain type="primary">
拥有code['btn_edit'] 权限可见
</el-button>
</Auth>
<Auth :value="['btn_add', 'btn_edit', 'btn_delete']">
<el-button text bg type="danger">
<el-button plain type="danger">
拥有code['btn_add', 'btn_edit', 'btn_delete'] 权限可见
</el-button>
</Auth>
@ -38,16 +38,15 @@ defineOptions({
<div class="card-header">函数方式判断权限</div>
</template>
<el-space wrap>
<el-button v-if="hasAuth('btn_add')" text bg type="warning">
<el-button v-if="hasAuth('btn_add')" plain type="warning">
拥有code'btn_add' 权限可见
</el-button>
<el-button v-if="hasAuth(['btn_edit'])" text bg type="primary">
<el-button v-if="hasAuth(['btn_edit'])" plain type="primary">
拥有code['btn_edit'] 权限可见
</el-button>
<el-button
v-if="hasAuth(['btn_add', 'btn_edit', 'btn_delete'])"
text
bg
plain
type="danger"
>
拥有code['btn_add', 'btn_edit', 'btn_delete'] 权限可见
@ -62,16 +61,15 @@ defineOptions({
</div>
</template>
<el-space wrap>
<el-button v-auth="'btn_add'" text bg type="warning">
<el-button v-auth="'btn_add'" plain type="warning">
拥有code'btn_add' 权限可见
</el-button>
<el-button v-auth="['btn_edit']" text bg type="primary">
<el-button v-auth="['btn_edit']" plain type="primary">
拥有code['btn_edit'] 权限可见
</el-button>
<el-button
v-auth="['btn_add', 'btn_edit', 'btn_delete']"
text
bg
plain
type="danger"
>
拥有code['btn_add', 'btn_edit', 'btn_delete'] 权限可见

View File

@ -111,6 +111,8 @@ declare module "vue" {
ElResult: (typeof import("element-plus"))["ElResult"];
ElSelectV2: (typeof import("element-plus"))["ElSelectV2"];
ElWatermark: (typeof import("element-plus"))["ElWatermark"];
ElTour: (typeof import("element-plus"))["ElTour"];
ElTourStep: (typeof import("element-plus"))["ElTourStep"];
}
interface ComponentCustomProperties {

6
types/global.d.ts vendored
View File

@ -6,12 +6,16 @@ import type { TableColumns } from "@pureadmin/table";
*/
declare global {
/**
*
* `node``pnpm`
*/
const __APP_INFO__: {
pkg: {
name: string;
version: string;
engines: {
node: string;
pnpm: string;
};
dependencies: Recordable<string>;
devDependencies: Recordable<string>;
};