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

View File

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

View File

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

View File

@ -54,7 +54,7 @@
"@logicflow/extension": "^1.2.19", "@logicflow/extension": "^1.2.19",
"@pureadmin/descriptions": "^1.2.0", "@pureadmin/descriptions": "^1.2.0",
"@pureadmin/table": "^3.0.1", "@pureadmin/table": "^3.0.1",
"@pureadmin/utils": "^2.3.1", "@pureadmin/utils": "^2.4.0",
"@vueuse/core": "^10.7.1", "@vueuse/core": "^10.7.1",
"@vueuse/motion": "^2.0.0", "@vueuse/motion": "^2.0.0",
"@wangeditor/editor": "^5.1.23", "@wangeditor/editor": "^5.1.23",
@ -87,7 +87,7 @@
"v-contextmenu": "3.0.0", "v-contextmenu": "3.0.0",
"v3-infinite-loading": "^1.3.1", "v3-infinite-loading": "^1.3.1",
"version-rocket": "^1.7.1", "version-rocket": "^1.7.1",
"vue": "^3.4.7", "vue": "^3.4.10",
"vue-i18n": "^9.9.0", "vue-i18n": "^9.9.0",
"vue-json-pretty": "^2.3.0", "vue-json-pretty": "^2.3.0",
"vue-pdf-embed": "^1.2.1", "vue-pdf-embed": "^1.2.1",
@ -98,7 +98,7 @@
"vue-waterfall-plugin-next": "^2.3.1", "vue-waterfall-plugin-next": "^2.3.1",
"vue3-danmaku": "^1.6.0", "vue3-danmaku": "^1.6.0",
"vuedraggable": "^4.1.0", "vuedraggable": "^4.1.0",
"wavesurfer.js": "^7.6.3", "wavesurfer.js": "^7.6.4",
"xgplayer": "^3.0.11", "xgplayer": "^3.0.11",
"xlsx": "^0.18.5" "xlsx": "^0.18.5"
}, },
@ -115,7 +115,7 @@
"@pureadmin/theme": "^3.2.0", "@pureadmin/theme": "^3.2.0",
"@types/intro.js": "^5.1.5", "@types/intro.js": "^5.1.5",
"@types/js-cookie": "^3.0.6", "@types/js-cookie": "^3.0.6",
"@types/node": "^20.10.8", "@types/node": "^20.11.0",
"@types/nprogress": "^0.2.3", "@types/nprogress": "^0.2.3",
"@types/qrcode": "^1.5.5", "@types/qrcode": "^1.5.5",
"@types/qs": "^6.9.11", "@types/qs": "^6.9.11",
@ -131,12 +131,12 @@
"eslint-config-prettier": "^9.1.0", "eslint-config-prettier": "^9.1.0",
"eslint-define-config": "^2.1.0", "eslint-define-config": "^2.1.0",
"eslint-plugin-prettier": "^5.1.3", "eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-vue": "^9.19.2", "eslint-plugin-vue": "^9.20.0",
"husky": "^8.0.3", "husky": "^8.0.3",
"lint-staged": "^15.2.0", "lint-staged": "^15.2.0",
"picocolors": "^1.0.0", "picocolors": "^1.0.0",
"postcss": "^8.4.33", "postcss": "^8.4.33",
"postcss-html": "^1.5.0", "postcss-html": "^1.6.0",
"postcss-import": "^15.1.0", "postcss-import": "^15.1.0",
"postcss-scss": "^4.0.9", "postcss-scss": "^4.0.9",
"prettier": "^3.1.1", "prettier": "^3.1.1",
@ -162,7 +162,7 @@
"vue-tsc": "^1.8.27" "vue-tsc": "^1.8.27"
}, },
"engines": { "engines": {
"node": "^18.12.0 || >=20.0.0", "node": "^18.18.0 || ^20.9.0 || >=21.1.0",
"pnpm": ">=8.6.10" "pnpm": ">=8.6.10"
}, },
"packageManager": "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 { useTippy } from "vue-tippy";
import { ElUpload } from "element-plus"; import { ElUpload } from "element-plus";
import type { CSSProperties } from "vue"; import type { CSSProperties } from "vue";
import { useResizeObserver } from "@vueuse/core";
import { longpress } from "@/directives/longpress"; import { longpress } from "@/directives/longpress";
import { delay, debounce, isArray, downloadByBase64 } from "@pureadmin/utils";
import { import {
ref, ref,
unref, unref,
@ -15,6 +13,13 @@ import {
onUnmounted, onUnmounted,
defineComponent defineComponent
} from "vue"; } from "vue";
import {
delay,
debounce,
isArray,
downloadByBase64,
useResizeObserver
} from "@pureadmin/utils";
import { import {
Reload, Reload,
Upload, Upload,
@ -126,9 +131,7 @@ export default defineComponent({
cropper.value?.destroy(); cropper.value?.destroy();
}); });
useResizeObserver(tippyElRef, () => { useResizeObserver(tippyElRef, () => handCropper("reset"));
handCropper("reset");
});
async function init() { async function init() {
const imgEl = unref(imgElRef); 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 Monitor from "@iconify-icons/ep/monitor";
import Tag from "@iconify-icons/ri/bookmark-2-line"; import Tag from "@iconify-icons/ri/bookmark-2-line";
import Table from "@iconify-icons/ri/table-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("ubuntuFill", UbuntuFill);
addIcon("menu", Menu); addIcon("menu", Menu);
addIcon("edit", Edit); addIcon("edit", Edit);
@ -49,3 +51,5 @@ addIcon("lollipop", Lollipop);
addIcon("monitor", Monitor); addIcon("monitor", Monitor);
addIcon("tag", Tag); addIcon("tag", Tag);
addIcon("table", Table); 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"> <div v-if="layout === 'vertical'" class="vertical-header-right">
<!-- 菜单搜索 --> <!-- 菜单搜索 -->
<Search /> <Search id="header-search" />
<!-- 通知 --> <!-- 通知 -->
<Notice id="header-notice" /> <Notice id="header-notice" />
<!-- 国际化 --> <!-- 国际化 -->

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
import type { App } from "vue"; import type { App } from "vue";
import * as echarts from "echarts/core"; import * as echarts from "echarts/core";
import { CanvasRenderer, SVGRenderer } from "echarts/renderers";
import { PieChart, BarChart, LineChart } from "echarts/charts"; import { PieChart, BarChart, LineChart } from "echarts/charts";
import { CanvasRenderer, SVGRenderer } from "echarts/renderers";
import { import {
GridComponent, GridComponent,
TitleComponent, 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, permission = 9,
system = 10, system = 10,
tabs = 11, tabs = 11,
formdesign = 12, about = 12,
flowchart = 13, editor = 13,
ppt = 14, flowchart = 14,
editor = 15, formdesign = 15,
guide = 16, board = 16,
about = 17, ppt = 17,
menuoverflow = 18; guide = 18,
menuoverflow = 19;
export { export {
home, home,
@ -33,11 +34,12 @@ export {
permission, permission,
system, system,
tabs, tabs,
formdesign,
flowchart,
ppt,
editor,
guide,
about, about,
editor,
flowchart,
formdesign,
board,
ppt,
guide,
menuoverflow menuoverflow
}; };

View File

@ -5,6 +5,7 @@ export default {
path: "/about", path: "/about",
redirect: "/about/index", redirect: "/about/index",
meta: { meta: {
icon: "info",
title: $t("menus.hsAbout"), title: $t("menus.hsAbout"),
rank: about 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: { meta: {
title: $t("menus.hsFormDesign"), title: $t("menus.hsFormDesign"),
frameSrc: 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 { .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 { .el-dialog__header {
display: none; display: none;
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -92,7 +92,7 @@ onMounted(() => {
</script> </script>
<template> <template>
<el-scrollbar height="87vh" class="content"> <el-scrollbar max-height="calc(100vh - 90px)" class="content">
<Waterfall :list="list" v-bind="options"> <Waterfall :list="list" v-bind="options">
<template #item="{ item, url, index }"> <template #item="{ item, url, index }">
<div <div
@ -149,3 +149,13 @@ onMounted(() => {
<InfiniteLoading :firstload="false" @infinite="handleLoadMore" /> <InfiniteLoading :firstload="false" @infinite="handleLoadMore" />
</el-scrollbar> </el-scrollbar>
</template> </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" name: "Editor"
}); });
const activeNames = ref(["1"]); const activeNames = ref("1");
</script> </script>
<template> <template>
@ -27,13 +27,13 @@ const activeNames = ref(["1"]);
</template> </template>
<el-collapse v-model="activeNames" accordion> <el-collapse v-model="activeNames" accordion>
<el-collapse-item title="基础用法" name="1"> <el-collapse-item title="基础用法" name="1">
<Base /> <Base v-if="activeNames === '1'" />
</el-collapse-item> </el-collapse-item>
<el-collapse-item title="多个富文本" name="2"> <el-collapse-item title="多个富文本" name="2">
<Multi /> <Multi v-if="activeNames === '2'" />
</el-collapse-item> </el-collapse-item>
<el-collapse-item title="自定义图片上传" name="3"> <el-collapse-item title="自定义图片上传" name="3">
<PicUpload /> <PicUpload v-if="activeNames === '3'" />
</el-collapse-item> </el-collapse-item>
</el-collapse> </el-collapse>
</el-card> </el-card>

View File

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

View File

@ -6,10 +6,26 @@ defineOptions({
name: "Guide" name: "Guide"
}); });
const guide = () => { const onGuide = () => {
intro() intro()
.setOptions({ .setOptions({
steps: [ 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 element: document.querySelector("#header-notice") as
| string | string
@ -49,12 +65,10 @@ const guide = () => {
<template #header> <template #header>
<div class="card-header"> <div class="card-header">
<span class="font-medium"> <span class="font-medium">
引导页对于一些第一次进入项目的人很有用你可以简单介绍下项目的功能 引导页常用于引导式介绍项目的基本功能或亮点
</span> </span>
</div> </div>
</template> </template>
<el-button type="primary" class="mt-[10px]" @click="guide"> <el-button @click="onGuide"> 打开引导页 </el-button>
打开引导页
</el-button>
</el-card> </el-card>
</template> </template>

View File

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

View File

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

View File

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

6
types/global.d.ts vendored
View File

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